From bf265e1659ff5ebbc1fd730b6f8fcd5979c5ba22 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Wed, 25 Jul 2018 04:47:00 +0100 Subject: [PATCH] add peripherals --- src/peripherals/bootrom/BootRom.bsv | 133 ++ src/peripherals/clint/clint.bsv | 101 ++ src/peripherals/flexbus/FlexBus_Types.bsv | 1239 +++++++++++++++++ src/peripherals/jtagdtm/jtagdefines.bsv | 19 + src/peripherals/jtagdtm/jtagdtm.bsv | 568 ++++++++ src/peripherals/jtagdtm/jtagdtm_new.bsv | 337 +++++ .../sdram/bsvmksdram_model_wrapper.bsv | 124 ++ src/peripherals/sdram/bsvmksdrc_top.bsv | 928 ++++++++++++ .../controller/parallel_prog_delay_cell.v | 42 + .../sdram/controller/sdrc_bank_ctl.v | 602 ++++++++ .../sdram/controller/sdrc_bank_fsm.v | 401 ++++++ .../sdram/controller/sdrc_bs_convert.v | 258 ++++ src/peripherals/sdram/controller/sdrc_core.v | 508 +++++++ .../sdram/controller/sdrc_req_gen.v | 371 +++++ src/peripherals/sdram/controller/sdrc_top.v | 325 +++++ .../sdram/controller/sdrc_xfr_ctl.v | 939 +++++++++++++ src/peripherals/sdram/sdr_top.bsv | 814 +++++++++++ src/peripherals/sdram/tb_bsv_wrapper.bsv | 365 +++++ src/peripherals/sdram/tb_top.bsv | 99 ++ src/peripherals/tdm/TCM.bsv | 151 ++ src/peripherals/vme/Memory_vme_16.bsv | 363 +++++ src/peripherals/vme/Memory_vme_32.bsv | 338 +++++ src/peripherals/vme/Memory_vme_8.bsv | 297 ++++ src/peripherals/vme/vme_defines.bsv | 29 + src/peripherals/vme/vme_master.bsv | 750 ++++++++++ src/peripherals/vme/vme_parameters.bsv | 17 + src/peripherals/vme/vme_top.bsv | 456 ++++++ src/uncore/axi4/SlaveWrapper.bsv | 62 + src/uncore/debug/DebugModule.bsv | 654 +++++++++ src/uncore/debug/RBB_Shakti.bsv | 28 + src/uncore/debug/RBB_Shakti.c | 144 ++ src/uncore/debug/RBB_Shakti.h | 23 + src/uncore/debug/defines.bsv | 23 + src/uncore/tilelink/TLMemoryMap.bsv | 67 + src/uncore/tilelink/Tilelink.bsv | 70 + src/uncore/tilelink/Tilelink_Types.bsv | 406 ++++++ 36 files changed, 12051 insertions(+) create mode 100644 src/peripherals/bootrom/BootRom.bsv create mode 100644 src/peripherals/clint/clint.bsv create mode 100644 src/peripherals/flexbus/FlexBus_Types.bsv create mode 100644 src/peripherals/jtagdtm/jtagdefines.bsv create mode 100644 src/peripherals/jtagdtm/jtagdtm.bsv create mode 100644 src/peripherals/jtagdtm/jtagdtm_new.bsv create mode 100644 src/peripherals/sdram/bsvmksdram_model_wrapper.bsv create mode 100644 src/peripherals/sdram/bsvmksdrc_top.bsv create mode 100755 src/peripherals/sdram/controller/parallel_prog_delay_cell.v create mode 100755 src/peripherals/sdram/controller/sdrc_bank_ctl.v create mode 100755 src/peripherals/sdram/controller/sdrc_bank_fsm.v create mode 100755 src/peripherals/sdram/controller/sdrc_bs_convert.v create mode 100755 src/peripherals/sdram/controller/sdrc_core.v create mode 100755 src/peripherals/sdram/controller/sdrc_req_gen.v create mode 100755 src/peripherals/sdram/controller/sdrc_top.v create mode 100755 src/peripherals/sdram/controller/sdrc_xfr_ctl.v create mode 100644 src/peripherals/sdram/sdr_top.bsv create mode 100644 src/peripherals/sdram/tb_bsv_wrapper.bsv create mode 100644 src/peripherals/sdram/tb_top.bsv create mode 100644 src/peripherals/tdm/TCM.bsv create mode 100644 src/peripherals/vme/Memory_vme_16.bsv create mode 100644 src/peripherals/vme/Memory_vme_32.bsv create mode 100644 src/peripherals/vme/Memory_vme_8.bsv create mode 100644 src/peripherals/vme/vme_defines.bsv create mode 100644 src/peripherals/vme/vme_master.bsv create mode 100644 src/peripherals/vme/vme_parameters.bsv create mode 100644 src/peripherals/vme/vme_top.bsv create mode 100644 src/uncore/axi4/SlaveWrapper.bsv create mode 100644 src/uncore/debug/DebugModule.bsv create mode 100644 src/uncore/debug/RBB_Shakti.bsv create mode 100644 src/uncore/debug/RBB_Shakti.c create mode 100644 src/uncore/debug/RBB_Shakti.h create mode 100644 src/uncore/debug/defines.bsv create mode 100644 src/uncore/tilelink/TLMemoryMap.bsv create mode 100644 src/uncore/tilelink/Tilelink.bsv create mode 100644 src/uncore/tilelink/Tilelink_Types.bsv diff --git a/src/peripherals/bootrom/BootRom.bsv b/src/peripherals/bootrom/BootRom.bsv new file mode 100644 index 0000000..cd67f37 --- /dev/null +++ b/src/peripherals/bootrom/BootRom.bsv @@ -0,0 +1,133 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +package BootRom; + import defined_types::*; + `include "defined_parameters.bsv" + import BRAMCore :: *; + import DReg::*; + import Semi_FIFOF :: *; + import AXI4_Types :: *; + import AXI4_Fabric :: *; + import BUtils::*; + import axi_addr_generator::*; + +interface BootRom_IFC; + interface AXI4_Slave_IFC#(`PADDR,`Reg_width,`USERSPACE) axi_slave; +endinterface +typedef enum{Idle,HandleBurst} Mem_state deriving(Bits,Eq); +(*synthesize*) +module mkBootRom (BootRom_IFC); + + // we create 2 32-bit BRAMs since the xilinx tool is easily able to map them to BRAM32BE cells + // which makes it easy to use data2mem for updating the bit file. + BRAM_PORT#(Bit#(13),Bit#(32)) dmemMSB <- mkBRAMCore1Load(valueOf(TExp#(13)),False,"boot.MSB",False); + BRAM_PORT#(Bit#(13),Bit#(32)) dmemLSB <- mkBRAMCore1Load(valueOf(TExp#(13)),False,"boot.LSB",False); + + AXI4_Slave_Xactor_IFC #(`PADDR, `Reg_width, `USERSPACE) s_xactor <- mkAXI4_Slave_Xactor; + + Reg#(Mem_state) rd_state <-mkReg(Idle); + Reg#(Mem_state) wr_state <-mkReg(Idle); + Reg#(Bit#(8)) rg_readburst_counter<-mkReg(0); + Reg#(AXI4_Rd_Addr #(`PADDR,`USERSPACE)) rg_read_packet <-mkReg(?); + Reg#(AXI4_Wr_Resp #(`USERSPACE)) rg_write_response <-mkReg(?); + + rule rl_wr_respond(wr_state==Idle); + let aw <- pop_o (s_xactor.o_wr_addr); + let w <- pop_o (s_xactor.o_wr_data); + let b = AXI4_Wr_Resp {bresp: AXI4_SLVERR, buser: aw.awuser, bid:aw.awid}; + rg_write_response<=b; + $display($time,"\tBootROM: Illegal Write operation on BootROM"); + if(aw.awburst!=0) + wr_state<=HandleBurst; + else + s_xactor.i_wr_resp.enq (b); + endrule + + rule rl_wr_burst_response(wr_state==HandleBurst); + let w <- pop_o (s_xactor.o_wr_data); + if(w.wlast) begin + wr_state<=Idle; + s_xactor.i_wr_resp.enq (rg_write_response); + end + endrule + + rule rl_rd_request(rd_state==Idle); + let ar<- pop_o(s_xactor.o_rd_addr); + rg_read_packet<=ar; + Bit#(13) index_address=(ar.araddr-`BootRomBase)[15:3]; + dmemLSB.put(False,index_address,?); + dmemMSB.put(False,index_address,?); + rd_state<=HandleBurst; + `ifdef verbose $display($time,"\tBootROM: Recieved Read Request for Address: %h Index Address: %h",ar.araddr,index_address); `endif + endrule + + rule rl_rd_response(rd_state==HandleBurst); + Bit#(`Reg_width) data0 = {dmemMSB.read(),dmemLSB.read()}; + AXI4_Rd_Data#(`Reg_width,`USERSPACE) r = AXI4_Rd_Data {rresp: AXI4_OKAY, rdata: data0 ,rlast:rg_readburst_counter==rg_read_packet.arlen, ruser: 0, rid:rg_read_packet.arid}; + let transfer_size=rg_read_packet.arsize; + let address=rg_read_packet.araddr; + if(transfer_size==2)begin // 32 bit + if(address[2:0]==0) + r.rdata=duplicate(data0[31:0]); + else + r.rdata=duplicate(data0[63:32]); + end + else if (transfer_size=='d1)begin // half_word + if(address[2:0] ==0) + r.rdata = duplicate(data0[15:0]); + else if(address[2:0] ==2) + r.rdata = duplicate(data0[31:16]); + else if(address[2:0] ==4) + r.rdata = duplicate(data0[47:32]); + else if(address[2:0] ==6) + r.rdata = duplicate(data0[63:48]); + end + else if (transfer_size=='d0) begin// one byte + if(address[2:0] ==0) + r.rdata = duplicate(data0[7:0]); + else if(address[2:0] ==1) + r.rdata = duplicate(data0[15:8]); + else if(address[2:0] ==2) + r.rdata = duplicate(data0[23:16]); + else if(address[2:0] ==3) + r.rdata = duplicate(data0[31:24]); + else if(address[2:0] ==4) + r.rdata = duplicate(data0[39:32]); + else if(address[2:0] ==5) + r.rdata = duplicate(data0[47:40]); + else if(address[2:0] ==6) + r.rdata = duplicate(data0[55:48]); + else if(address[2:0] ==7) + r.rdata = duplicate(data0[63:56]); + end + s_xactor.i_rd_data.enq(r); + address=burst_address_generator(rg_read_packet.arlen, rg_read_packet.arsize, rg_read_packet.arburst,rg_read_packet.araddr); + Bit#(13) index_address=(address-`BootRomBase)[15:3]; + if(rg_readburst_counter==rg_read_packet.arlen)begin + rg_readburst_counter<=0; + rd_state<=Idle; + end + else begin + dmemLSB.put(False,index_address,?); + dmemMSB.put(False,index_address,?); + rg_readburst_counter<=rg_readburst_counter+1; + end + rg_read_packet.araddr<=address; + Bit#(64) new_data=r.rdata; + `ifdef verbose $display($time,"\tBootROM : Responding Read Request with CurrAddr: %h Data: %8h BurstCounter: %d BurstValue: %d NextAddress: %h",rg_read_packet.araddr,new_data,rg_readburst_counter,rg_read_packet.arlen,address); `endif + endrule + + interface axi_slave= s_xactor.axi_side; +endmodule +endpackage diff --git a/src/peripherals/clint/clint.bsv b/src/peripherals/clint/clint.bsv new file mode 100644 index 0000000..cdd4f4f --- /dev/null +++ b/src/peripherals/clint/clint.bsv @@ -0,0 +1,101 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ + +package clint; + /*=== library imports === */ + import ConfigReg::*; + import Semi_FIFOF::*; + import AXI4_Lite_Types::*; + import BUtils ::*; + /*======================== */ + /*==== Project imports ====*/ + import defined_types::*; + `include "defined_parameters.bsv" + /*=========================*/ + + interface Ifc_clint; + method Bit#(1) msip_int; + method Bit#(1) mtip_int; + method Bit#(`Reg_width) mtime; + interface AXI4_Lite_Slave_IFC#(`PADDR, `Reg_width,`USERSPACE) axi4_slave; + endinterface + + function Reg#(t) writeSideEffect(Reg#(t) r, Action a); + return (interface Reg; + method t _read = r._read; + method Action _write(t x); + r._write(x); + a; + endmethod + endinterface); + endfunction + + (*synthesize*) + module mkclint(Ifc_clint); + + AXI4_Lite_Slave_Xactor_IFC #(`PADDR, `Reg_width, `USERSPACE) s_xactor <- mkAXI4_Lite_Slave_Xactor; + Wire#(Bool) wr_mtimecmp_written<-mkDWire(False); + Reg#(Bit#(1)) msip <-mkReg(0); + Reg#(Bit#(1)) mtip <-mkReg(0); + Reg#(Bit#(64)) rgmtime<-mkReg(0); + Reg#(Bit#(64)) rgmtimecmp<-mkReg(0); + Reg#(Bit#(64)) csr_mtimecmp=writeSideEffect(rgmtimecmp,wr_mtimecmp_written._write(True)); + Reg#(Bit#(2)) rg_tick <-mkReg(0); + + rule generate_time_interrupt(!wr_mtimecmp_written); + mtip<=pack(rgmtime>=rgmtimecmp); + endrule + rule clear_interrupt(wr_mtimecmp_written); + mtip<=0; + endrule + rule increment_timer; + if(rg_tick==0)begin + rgmtime<=rgmtime+1; + end + rg_tick<=rg_tick+1; + endrule + + + rule axi_read_transaction; + let ar <- pop_o(s_xactor.o_rd_addr); + let r = AXI4_Lite_Rd_Data {rresp: AXI4_LITE_OKAY, rdata: ?, ruser: 0}; + case (ar.araddr[15:0]) matches + 'h0000: r.rdata=zeroExtend(msip); // MSIP interrupt bit + 'h4000: r.rdata=csr_mtimecmp; + 'hbff8: r.rdata=rgmtime; + default: begin r.rdata=0; r.rresp=AXI4_LITE_SLVERR; end + endcase + s_xactor.i_rd_data.enq(r); + endrule + + rule axi_write_transaction; + let aw <- pop_o(s_xactor.o_wr_addr); + let w <- pop_o(s_xactor.o_wr_data); + let r = AXI4_Lite_Wr_Resp {bresp: AXI4_LITE_OKAY, buser: 0 }; + + case (aw.awaddr[15:0]) matches + 'h0000: msip<=w.wdata[0]; // MSIP interrupt bit + 'h4000: csr_mtimecmp<=w.wdata; + default: r.bresp=AXI4_LITE_SLVERR; + endcase + s_xactor.i_wr_resp.enq (r); + endrule + + interface axi4_slave = s_xactor.axi_side; + method Bit#(1) msip_int=msip; + method Bit#(1) mtip_int=mtip; + method Bit#(`Reg_width) mtime = rgmtime; + + endmodule +endpackage diff --git a/src/peripherals/flexbus/FlexBus_Types.bsv b/src/peripherals/flexbus/FlexBus_Types.bsv new file mode 100644 index 0000000..9211640 --- /dev/null +++ b/src/peripherals/flexbus/FlexBus_Types.bsv @@ -0,0 +1,1239 @@ +// Copyright (c) 2017 Bluespec, Inc. All Rights Reserved + +package FlexBus_Types; + +// ================================================================ +// See export list below +// ================================================================ +// Exports + +export + +// RTL-level interfaces (signals/buses) +FlexBus_Slave_IFC (..), +FlexBus_Master_IFC (..), + + +// Higher-level enums and structs for the FlexBus +FlexBus_States (..), + +FlexBus_Payload (..), +FlexBus_Attr (..), +FlexBus_din (..), +FlexBus_Signals (..), + +// Higher-level FIFO-like interfaces for the 5 AXI4 channels, +FlexBus_Register_IFC (..), +FlexBus_Register_Output_IFC (..), +FlexBus_Register_Input_IFC (..), + +AXI4_Slave_to_FlexBus_Master_Xactor_IFC (..), + +// Transactors from RTL-level interfacecs to FIFO-like interfaces. +mkAXI4_Slave_to_FlexBus_Master_Xactor; + +// ================================================================ +// BSV library imports + +import Vector :: *; +import FIFOF :: *; +import SpecialFIFOs:: *; +import Connectable :: *; +import ConfigReg :: *; +`include "defined_parameters.bsv" + +// ---------------- +// BSV additional libs + +import Semi_FIFOF :: *; +import AXI4_Types :: *; + +import Memory_AXI4 :: *; + +// **************************************************************** +// **************************************************************** +// Section: RTL-level interfaces +// **************************************************************** +// **************************************************************** + +// ================================================================ +// These are the signal-level interfaces for an FlexBus master. +// The (*..*) attributes ensure that when bsc compiles this to Verilog, +// we get exactly the signals specified in the FlexBus spec. + +interface FlexBus_Master_IFC; + // FlexBus External Signals + + // AD inout bus separate for now in BSV + (* always_ready, result="AD" *) method Bit #(32) m_AD; // out + + //(* always_ready, always_enabled *) method Action m_din ((* port="din" *) Bit #(32) din); // in + method Action m_din ((* port="din" *) Bit #(32) din); // in + + (* always_ready, result="R_Wn" *) method Bit #(1) m_R_Wn; // out + (* always_ready, result="TSIZ" *) method Bit #(2) m_TSIZ; // out + + (* always_ready, result="FBCSn" *) method Bit #(6) m_FBCSn; // out + (* always_ready, result="BEn_BWEn" *) method Bit #(4) m_BE_BWEn; // out + (* always_ready, result="TBSTn" *) method Bit #(1) m_TBSTn; // out + (* always_ready, result="OEn" *) method Bit #(1) m_OEn; // out + + (* always_ready, result="ALE" *) method Bit #(1) m_ALE; // out + //(* always_ready, always_enabled *) method Action m_TAn ((* port="TAn" *) Bit #(1) tAn); // in + method Action m_TAn ((* port="TAn" *) Bit #(1) tAn); // in + +endinterface: FlexBus_Master_IFC + +interface FlexBus_Register_Input_IFC; + method Action reset (Bit#(32) ad_bus); + method Action m_ad_bus (Bit#(32) ad_bus); + method Action m_data_bus (Bit#(32) data_bus); +endinterface: FlexBus_Register_Input_IFC + +interface FlexBus_Register_Output_IFC; + (* always_ready, always_enabled *) method Bit#(6) m_FBCSn(); + (* always_ready, always_enabled *) method Bit#(6) m_SWS(); + (* always_ready, always_enabled *) method Bit#(1) m_SWS_EN(); + (* always_ready, always_enabled *) method Bit#(2) m_ASET(); + (* always_ready, always_enabled *) method Bit#(2) m_RDAH(); + (* always_ready, always_enabled *) method Bit#(2) m_WRAH(); + (* always_ready, always_enabled *) method Bit#(6) m_WS(); + (* always_ready, always_enabled *) method Bit#(1) m_AA(); + (* always_ready, always_enabled *) method Bit#(2) m_PS(); + (* always_ready, always_enabled *) method Bit#(1) m_BEM(); + (* always_ready, always_enabled *) method Bit#(1) m_BSTR(); + (* always_ready, always_enabled *) method Bit#(1) m_BSTW(); +endinterface: FlexBus_Register_Output_IFC + +interface FlexBus_Register_IFC; + interface FlexBus_Register_Input_IFC inp_side; + interface FlexBus_Register_Output_IFC op_side; +endinterface: FlexBus_Register_IFC + +// ================================================================ +// These are the signal-level interfaces for an AXI4-Lite slave. +// The (*..*) attributes ensure that when bsc compiles this to Verilog, +// we get exactly the signals specified in the ARM spec. + +interface FlexBus_Slave_IFC ; + + (* always_ready, always_enabled *) method Action m_AD ( (* port="AD" *) Bit #(32) i_AD); // in + + + (* always_ready, always_enabled *) method Action m_ALE ( (* port="ALE" *) Bit #(1) i_ALE); // in + + (* always_ready, always_enabled *) method Action m_R_Wn ( (* port="R_Wn" *) Bit #(1) i_R_Wn); // in + (* always_ready, always_enabled *) method Action m_TSIZ ( (* port="TSIZ" *) Bit #(2) i_TSIZ); // in + + (* always_ready, always_enabled *) method Action m_FBCSn ( (* port="FBCSn" *) Bit #(6) i_FBCSn); // in + (* always_ready, always_enabled *) method Action m_BE_BWEn ( (* port="BE_BWEn" *) Bit #(4) i_BE_BWEn); // in + (* always_ready, always_enabled *) method Action m_TBSTn ( (* port="TBSTn" *) Bit #(1) i_TBSTn); // in + (* always_ready, always_enabled *) method Action m_OEn ( (* port="OEn" *) Bit #(1) i_OEn); // in + + (* always_ready, result="din" *) method Bit #(32) m_din; // out + (* always_ready, result="TAn" *) method Bit #(1) m_TAn; // out + +endinterface: FlexBus_Slave_IFC + + +// ================================================================ +// Connecting signal-level interfaces + +instance Connectable #(FlexBus_Master_IFC , + FlexBus_Slave_IFC ); + + module mkConnection #(FlexBus_Master_IFC flexbus_m, + FlexBus_Slave_IFC flexbus_s) + (Empty); + + (* fire_when_enabled, no_implicit_conditions *) + rule rl_flexbus_AD_signals; + flexbus_s.m_AD (flexbus_m.m_AD); + endrule + + + (* fire_when_enabled, no_implicit_conditions *) + rule rl_flexbus_Attr_signals; + flexbus_s.m_ALE (flexbus_m.m_ALE); + flexbus_s.m_R_Wn (flexbus_m.m_R_Wn); + flexbus_s.m_TSIZ (flexbus_m.m_TSIZ); + endrule + (* fire_when_enabled, no_implicit_conditions *) + rule rl_flexbus_signals; + flexbus_s.m_FBCSn (flexbus_m.m_FBCSn); + flexbus_s.m_BE_BWEn (flexbus_m.m_BE_BWEn); + flexbus_s.m_TBSTn (flexbus_m.m_TBSTn); + flexbus_s.m_OEn (flexbus_m.m_OEn); + endrule + (* fire_when_enabled *) + //(* fire_when_enabled, no_implicit_conditions *) + rule rl_flexbus_input_signals; + flexbus_m.m_din (flexbus_s.m_din); + flexbus_m.m_TAn (flexbus_s.m_TAn); + endrule + + endmodule +endinstance + +// **************************************************************** +// **************************************************************** +// Section: Higher-level FIFO-like interfaces and transactors +// **************************************************************** +// **************************************************************** + +// ================================================================ +// Higher-level types for payloads (rather than just bits) + +typedef enum { IDLE, FlexBus_S0_DEQ_WR_FIFOS, FlexBus_S0_DEQ_RD_FIFOS, FlexBus_S1_ADDR, FlexBus_S2_WRITE, FlexBus_S3_BURST, FlexBus_S4_HOLD } FlexBus_States deriving (Bits, Eq, FShow); +typedef enum { IDLE, FlexBus_S0_CHK_FIFOS, FlexBus_S0_DEQ_FIFOS, FlexBus_WRITE_DUMMY1, FlexBus_WRITE_DUMMY2 } FlexBus_States_wr deriving (Bits, Eq, FShow); +typedef enum { IDLE, FlexBus_S0_CHK_FIFOS, FlexBus_S0_DEQ_FIFOS} FlexBus_States_rd deriving (Bits, Eq, FShow); + +//FlexBus Addr. Data Payload + +typedef struct { + Bit #(32) s_AD; // out + } FlexBus_Payload +deriving (Bits, FShow); + +typedef struct { + Bit #(32) din; // in + } FlexBus_din +deriving (Bits, FShow); + +//FlexBus Attributes + +typedef struct { + Bit #(1) s_R_Wn; // out + Bit #(2) s_TSIZ; // out + } FlexBus_Attr +deriving (Bits, FShow); + +typedef struct { + Bit #(6) s_FBCSn; // out + Bit #(4) s_BEn_BWEn; // out + Bit #(1) s_TBSTn; // out + Bit #(1) s_OEn; // out + } FlexBus_Signals #(numeric type wd_addr, numeric type wd_data) +deriving (Bits, FShow); + +// FlexBus Control Signals + +// Bit s_ALE; // out +// Bit s_TAn; // in + +/* ---------------------------------------------------------------- + + module mkFlexBusTop (Empty); + AXI4_Slave_to_FlexBus_Master_Xactor_IFC#(56, 64,10) + flexbus_xactor_ifc <- mkAXI4_Slave_to_FlexBus_Master_Xactor; + + endmodule + + +// ---------------------------------------------------------------- */ +// AXI4 Lite Slave to FlexBus Master transactor interface + +interface AXI4_Slave_to_FlexBus_Master_Xactor_IFC #(numeric type wd_addr, + numeric type wd_data, + numeric type wd_user); + method Action reset; + + // AXI side + interface AXI4_Slave_IFC #(wd_addr, wd_data, wd_user) axi_side; + + // FlexBus side + interface FlexBus_Master_IFC flexbus_side; + +endinterface: AXI4_Slave_to_FlexBus_Master_Xactor_IFC + +// ---------------------------------------------------------------- + +// AXI4 Lite Slave to FlexBus Master transactor + +module mkAXI4_Slave_to_FlexBus_Master_Xactor + (AXI4_Slave_to_FlexBus_Master_Xactor_IFC #(wd_addr, wd_data, wd_user)) + provisos (Add#(a__, 8, wd_addr), + Add#(b__, 64, wd_data), + //Bits#(Bit#(56), wd_addr), + //Bits#(Bit#(64), wd_data), + //Bits#(Bit#(32), wd_fb_addr), + //Bits#(Bit#(32), wd_fb_data), + //Bits#(Inout#(Bit#(32)), a__), + // Bits#(Inout#(Bit#(32)), wd_Fb_addr), + //Bits#(Inout#(Bit#(32)), 48), + Div#(wd_data, 16, 4)); + Bool unguarded = True; + Bool guarded = False; + //let wD_FB_ADDR = valueOf(wd_fb_addr); + //let wD_FB_DATA = valueOf(wd_fb_data); + + FlexBus_Register_IFC register_ifc <- mkFlexBus_Registers; + + Reg#(Bit#(32)) r_AD <- mkReg(0); + Reg#(Bit#(32)) r_din <- mkReg(0); + Reg#(Bit#(1)) r_R_Wn <- mkReg(1'b1); + Reg#(Bit#(2)) r_TSIZ <- mkReg(2'b00); + Reg#(Bit#(6)) r_FBCSn <- mkReg(6'h3F); + Reg#(Bit#(4)) r_BE_BWEn <- mkReg(4'hF); + Reg#(Bit#(1)) r_TBSTn <- mkReg(1'b1); + Reg#(Bit#(1)) r_OEn <- mkReg(1'b1); + Reg#(Bit#(1)) r_ALE <- mkReg(1'b0); + Reg#(Bit#(1)) r_ext_TAn <- mkReg(1'b0); + Reg#(Bit#(1)) r_int_TAn <- mkReg(1'b1); + + Reg#(Bit#(2)) r_ASET <- mkReg(2'b00); + Reg#(Bit#(2)) r_PS <- mkReg(2'b00); + Reg#(Bit#(3)) r_rpt_cnt <- mkReg(3'b000); + Reg#(Bit#(2)) r_burst_cnt <- mkReg(2'b00); + Reg#(Bit#(2)) r_hld_cnt <- mkReg(2'b00); + Reg#(Bit#(6)) r_WS_cnt <- mkReg(6'h00); + Reg#(Bit#(6)) r_SWS_cnt <- mkReg(6'h00); + Reg#(Bit#(wd_addr)) r_awaddr <- mkReg(0); + Reg#(Bit#(2)) r_awsize <- mkReg(0); + Reg#(Bit#(wd_addr)) r2_awaddr <- mkReg(0); + Reg#(Bit#(wd_data)) r_wdata <- mkReg(0); + Reg#(AXI4_Resp) r_wrbresp <- mkReg(AXI4_OKAY); + Reg#(AXI4_Resp) r_rresp <- mkReg(AXI4_OKAY); + Reg#(Bit#(wd_data)) r_rd_data <- mkReg(0); + Reg#(Bit#(TDiv#(wd_data,8))) r1_wstrb <- mkReg(0); + Reg#(Bit#(TDiv#(wd_data,8))) r2_wstrb <- mkReg(0); + Reg#(Bit#(wd_addr)) r_araddr <- mkReg(0); + Reg#(Bit#(wd_addr)) r2_araddr <- mkReg(0); + Reg#(Bit#(2)) r_arsize <- mkReg(0); + Reg#(Bit#(4)) r_arid <- mkReg(0); + Reg#(Bit#(4)) r_awid <- mkReg(0); + Reg#(Bit#(1)) wr_pending <- mkReg(0); + Reg#(Bit#(1)) r_chk_fifos_wr <- mkReg(0); + Reg#(Bit#(1)) r_chk_fifos_rd <- mkReg(0); + ConfigReg#(Bit#(1)) rd_wrb <- mkConfigReg(1); + Reg#(Bool) r_rready <- mkReg(False); + Reg#(Bool) r2_rready <- mkReg(False); + + Reg#(Bool) r1_awvalid <- mkReg(False); + Reg#(Bool) r2_awvalid <- mkReg(False); + Reg#(Bool) r1_wvalid <- mkReg(False); + Reg#(Bool) r2_wvalid <- mkReg(False); + Reg#(Bool) r1_arvalid <- mkReg(False); + Reg#(Bool) r2_arvalid <- mkReg(False); + + Reg#(Bool) r1_OEn <- mkReg(True); + + Reg#(Bit#(8)) r_AD_32bit_data_byte1 <- mkReg(0); + Reg#(Bit#(8)) r_AD_32bit_data_byte2 <- mkReg(0); + Reg#(Bit#(8)) r_AD_32bit_data_byte3 <- mkReg(0); + Reg#(Bit#(8)) r_AD_32bit_data_byte4 <- mkReg(0); + + Reg#(Bit#(8)) r_AD_32bit_addr_byte1 <- mkReg(0); + Reg#(Bit#(8)) r_AD_32bit_addr_byte2 <- mkReg(0); + Reg#(Bit#(8)) r_AD_32bit_addr_byte3 <- mkReg(0); + Reg#(Bit#(8)) r_AD_32bit_addr_byte4 <- mkReg(0); + + Reg#(Bit#(8)) r_rd_data_32bit_byte1 <- mkReg(0); + Reg#(Bit#(8)) r_rd_data_32bit_byte2 <- mkReg(0); + Reg#(Bit#(8)) r_rd_data_32bit_byte3 <- mkReg(0); + Reg#(Bit#(8)) r_rd_data_32bit_byte4 <- mkReg(0); + + Reg#(Bit#(32)) r_MBAR <- mkReg(32'h04000000); + + Reg#(FlexBus_States) flexbus_state <- mkReg(IDLE); + Reg#(FlexBus_States_rd) flexbus_state_rd <- mkReg(FlexBus_S0_CHK_FIFOS); + Reg#(FlexBus_States_wr) flexbus_state_wr <- mkReg(FlexBus_S0_CHK_FIFOS); + + // These FIFOs are guarded on BSV side, unguarded on AXI side + FIFOF #(AXI4_Wr_Addr #(wd_addr, wd_user)) f_wr_addr <- mkGFIFOF (unguarded, guarded); + FIFOF #(AXI4_Wr_Data #(wd_data)) f_wr_data <- mkGFIFOF (unguarded, unguarded); + FIFOF #(AXI4_Wr_Resp #(wd_user)) f_wr_resp <- mkGFIFOF (guarded, unguarded); + + FIFOF #(AXI4_Rd_Addr #(wd_addr, wd_user)) f_rd_addr <- mkGFIFOF (unguarded, guarded); + FIFOF #(AXI4_Rd_Data #(wd_data, wd_user)) f_rd_data <- mkGFIFOF (guarded, unguarded); + + Reg#(Maybe#(Bit#(1))) c_TAn[2] <- mkCReg(2, tagged Invalid); + Reg#(Maybe#(Bit#(32))) c_din[2] <- mkCReg(2, tagged Invalid); + + //TriState#(Bit#(32)) tri_AD_out <- mkTriState(r1_OEn,r_AD); + + // ---------------------------------------------------------------- + + rule rl_OEn; + if (r_OEn == 1'b0) + r1_OEn <= False; + else + r1_OEn <= True; + endrule + + rule rl_state_S0_CHK_FIFO_RD(flexbus_state_rd == FlexBus_S0_CHK_FIFOS); + `ifdef verbose_debug $display("STATE S0 CHK FIFOS RD FIRED"); `endif + if (f_rd_addr.notEmpty) begin + register_ifc.inp_side.m_ad_bus(f_rd_addr.first.araddr[31:0]); + flexbus_state_rd <= FlexBus_S0_DEQ_FIFOS; + `ifdef verbose_debug_l2 $display("READ ADDR FIFO WAS READ FIRST r_araddr=%h \n", f_rd_addr.first.araddr); `endif + end + endrule + + (* preempts = "rl_check_read_fifo, rl_check_write_fifo" *) + rule rl_check_read_fifo (r_chk_fifos_rd == 1'b1 && f_rd_addr.notEmpty); + rd_wrb <= 1'b1; + r_chk_fifos_rd <= 1'b0; + r_chk_fifos_wr <= 1'b0; + endrule + + rule rl_check_write_fifo(r_chk_fifos_wr == 1'b1 && f_wr_addr.notEmpty && f_wr_data.notEmpty); + if (f_wr_addr.first.awaddr[31:16] != r_MBAR[31:16]) begin + rd_wrb <= 1'b0; + r_chk_fifos_rd <= 1'b0; + r_chk_fifos_wr <= 1'b0; + end + endrule + + rule rl_state_S0_CHK_FIFOS_WR(flexbus_state_wr == FlexBus_S0_CHK_FIFOS); + `ifdef verbose_debug $display("STATE S0 CHK FIFOS WR FIRED"); `endif + if (f_wr_addr.notEmpty && f_wr_data.notEmpty) begin + if (f_wr_addr.first.awaddr[31:16] == r_MBAR[31:16]) begin + f_wr_addr.deq; f_wr_data.deq; + end + else begin + flexbus_state_wr <= FlexBus_S0_DEQ_FIFOS; + end + register_ifc.inp_side.m_ad_bus(f_wr_addr.first.awaddr[31:0]); + register_ifc.inp_side.m_data_bus(f_wr_data.first.wdata[31:0]); + end + endrule + + rule rl_state_S0_DEQ_FIFOS (flexbus_state_rd == FlexBus_S0_DEQ_FIFOS || flexbus_state_wr == FlexBus_S0_DEQ_FIFOS); + `ifdef verbose_debug $display("STATE S0 DEQ FIFOS FIRED"); `endif + if (rd_wrb == 1'b1) begin + flexbus_state <= FlexBus_S0_DEQ_RD_FIFOS; + flexbus_state_rd <= IDLE; + flexbus_state_wr <= IDLE; + end + else if (rd_wrb == 1'b0) begin + flexbus_state <= FlexBus_S0_DEQ_WR_FIFOS; + flexbus_state_rd <= IDLE; + flexbus_state_wr <= IDLE; + end + if (flexbus_state_rd == FlexBus_S0_DEQ_FIFOS && flexbus_state_wr == FlexBus_S0_DEQ_FIFOS) wr_pending <= 1'b1; + endrule + + rule rl_state_S0_DEQ_WR_FIFOS (flexbus_state == FlexBus_S0_DEQ_WR_FIFOS); + `ifdef verbose_debug $display("STATE S0 DEQ WR FIFOS FIRED"); `endif + r_ASET <= register_ifc.op_side.m_ASET; + Bit#(3) v_awsize = 3'b000; + if ((f_wr_addr.notEmpty) ) begin + r1_awvalid <= f_wr_addr.notEmpty; + f_wr_addr.deq; + r_chk_fifos_wr <= 1'b1; + r_chk_fifos_rd <= 1'b1; + AXI4_Wr_Addr#(wd_addr, wd_user) wr_addr = f_wr_addr.first; + r_awaddr <= f_wr_addr.first.awaddr; + v_awsize = f_wr_addr.first.awsize; + r_awid <= f_wr_addr.first.awid; + case (v_awsize) matches + {3'b000}: r_awsize <= 2'b01; + {3'b001}: r_awsize <= 2'b10; + {3'b010}: r_awsize <= 2'b00; + endcase + `ifdef verbose_debug_l2 $display("ADDR FIFO WAS NOT EMPTY SO I DEQUEUED r_awaddr=%h \n", r_awaddr); `endif + end + if ((f_wr_data.notEmpty) ) begin + r1_wvalid <= f_wr_data.notEmpty; + f_wr_data.deq; + `ifdef verbose_debug_l2 $display("DATA FIFO WAS NOT EMPTY SO I DEQUEUED\n"); `endif + AXI4_Wr_Data#(wd_data) wr_data = f_wr_data.first; + r_wdata <= f_wr_data.first.wdata; + r1_wstrb <= f_wr_data.first.wstrb; + `ifdef verbose_debug_l2 $display(" dequeued first r_wdata = %h", r_wdata); `endif + end + if (f_wr_addr.notEmpty && f_wr_data.notEmpty) begin + flexbus_state <= FlexBus_S1_ADDR; + end + endrule + + rule rl_S0_DEQ_RD_FIFOS (flexbus_state == FlexBus_S0_DEQ_RD_FIFOS); + `ifdef verbose_debug $display("STATE S0 DEQ RD FIFOS FIRED"); `endif + r_ASET <= register_ifc.op_side.m_ASET; + Bit#(3) v_arsize = 3'b000; + if ((f_rd_addr.notEmpty) ) begin + r1_arvalid <= f_rd_addr.notEmpty; + f_rd_addr.deq; + r_chk_fifos_wr <= 1'b1; + r_chk_fifos_rd <= 1'b1; + AXI4_Rd_Addr#(wd_addr, wd_user) rd_addr = f_rd_addr.first; + r_araddr <= f_rd_addr.first.araddr; + v_arsize = f_rd_addr.first.arsize; + r_arid <= f_rd_addr.first.arid; + case (v_arsize) matches + {3'b000}: r_arsize <= 2'b01; + {3'b001}: r_arsize <= 2'b10; + {3'b010}: r_arsize <= 2'b00; + endcase + r_rd_data_32bit_byte1 <= 0; + r_rd_data_32bit_byte2 <= 0; + r_rd_data_32bit_byte3 <= 0; + r_rd_data_32bit_byte4 <= 0; + `ifdef verbose_debug_l2 $display("ADDR FIFO WAS NOT EMPTY SO I DEQUEUED r_araddr=%h \n", f_rd_addr.first.araddr); `endif + end + if (f_rd_addr.notEmpty) begin + flexbus_state <= FlexBus_S1_ADDR; + end + endrule + + rule rl_enq_wr_resp; + Bool bready = f_wr_resp.notFull; + if (f_wr_resp.notFull) + f_wr_resp.enq (AXI4_Wr_Resp {bresp:r_wrbresp, + buser:0, + bid:r_awid}); + endrule + + + rule rl_enq_rd_data; + Bool rready = f_rd_data.notFull; + if (f_rd_data.notFull && r2_rready) begin + f_rd_data.enq (AXI4_Rd_Data {rdata: r_rd_data, + rresp: r_rresp, + rlast: True, + ruser:0, + rid:r_arid}); + //AXI4_Slave_IFC.m_rready(True); + `ifdef verbose_debug $display("RD DATA FIFO WAS NOT FULL SO I ENQUEUED r_rd_data=%h r2_rready= %b\n", r_rd_data, r2_rready); `endif + end + endrule + + rule rl_state_S1_ADDR (flexbus_state == FlexBus_S1_ADDR); //Address state + `ifdef verbose_debug $display("STATE S1 FIRED");`endif + r_PS <= register_ifc.op_side.m_PS; + r_WS_cnt <= register_ifc.op_side.m_WS; + r_OEn <= 1'b1; + r_BE_BWEn <= 4'hF; + r_FBCSn <= 6'h3F; + r_ALE <= 1'b1; + `ifdef verbose_debug_l2 $display(" r_ASET was ASSIGNED = %b", r_ASET); `endif + if (r_rpt_cnt == 3'b000) begin + if (r1_arvalid) begin + r_AD <= r_araddr[31:0]; + r_R_Wn <= 1'b1; // Read + r_TSIZ <= r_arsize; + end + else if (r1_awvalid && r1_wvalid) begin + r_AD <= r_awaddr[31:0]; + r_R_Wn <= 1'b0; // WriteBar + r_TSIZ <= r_awsize; + end + end + else begin + if (r_R_Wn == 1'b0) r_AD <= r_awaddr[31:0]; + else r_AD <= r_araddr[31:0]; + r_TBSTn <= 1'b1; + r_TSIZ <= register_ifc.op_side.m_PS; + end + if (( r_ASET != 2'b00) ) begin + r_ASET <= r_ASET - 1; + end + else begin + flexbus_state <= FlexBus_S2_WRITE; + if (r_rpt_cnt != 3'b000) + r_rpt_cnt <= r_rpt_cnt -1; + end + endrule + + rule rl_assign_AD_bus_reg (flexbus_state == FlexBus_S1_ADDR) ; // Address an Attributes Phase + `ifdef verbose_debug_l2 $display(" ASSIGN AD BUS FIRED"); `endif + + r2_awvalid <= r1_awvalid; + r2_wvalid <= r1_wvalid; + r2_wstrb <= r1_wstrb; + r2_arvalid <= r1_arvalid; + + r2_araddr <= r_araddr; + r2_awaddr <= r_awaddr; + + r_AD_32bit_data_byte1 <= pack(r_wdata[7:0]); + r_AD_32bit_data_byte2 <= pack(r_wdata[15:8]); + r_AD_32bit_data_byte3 <= pack(r_wdata[23:16]); + r_AD_32bit_data_byte4 <= pack(r_wdata[31:24]); + r_AD_32bit_addr_byte1 <= pack(r_awaddr[31:24]); + r_AD_32bit_addr_byte2 <= pack(r_awaddr[23:16]); + r_AD_32bit_addr_byte3 <= pack(r_awaddr[15:8]); + r_AD_32bit_addr_byte4 <= pack(r_awaddr[7:0]); + `ifdef verbose_debug_l2 $display("r_wdata after ASSIGN = %h r_PS = %b r_AD_32bit_data_byte1=%h ", r_wdata, r_PS, r_AD_32bit_data_byte1); + $display("r_awaddr after ASSIGN = %h r_PS = %b r_AD_32bit_addr_byte1=%h ", r_awaddr, r_PS, r_AD_32bit_addr_byte1); `endif + endrule + + rule rl_assign_rd_data; + r_rd_data[63:0] <= pack({32'h00000000, r_rd_data_32bit_byte4, r_rd_data_32bit_byte3, r_rd_data_32bit_byte2, r_rd_data_32bit_byte1}); + r2_rready <= r_rready; + `ifdef verbose_debug_l2 $display("ASSIGN READ DATA FIRED AND r_rd_data = %h r_rready=%b r2_rready=%b", r_rd_data, r_rready, r2_rready);`endif + endrule + + rule rl_read_ext_signals; + if (isValid(c_TAn[1])) begin + r_ext_TAn <= fromMaybe(?,c_TAn[1]); + c_TAn[1]<= tagged Invalid; + end + if (isValid(c_din[1])) begin + r_din <= fromMaybe(?,c_din[1]); + c_din[1]<= tagged Invalid; + end + //r_din <= tri_AD_out._read; + endrule + + rule rl_state_S2_WRITE (flexbus_state == FlexBus_S2_WRITE); //Write Phase + `ifdef verbose_debug $display("STATE S2 FIRED"); `endif + r_ALE <= 1'b0; + r_FBCSn <= register_ifc.op_side.m_FBCSn; + r_SWS_cnt <= register_ifc.op_side.m_SWS; + if (r_R_Wn == 1'b1) + r_hld_cnt <= register_ifc.op_side.m_RDAH; + else + r_hld_cnt <= register_ifc.op_side.m_WRAH; + if (r_R_Wn == 1'b1) begin + r_OEn <= 1'b0; + if ((register_ifc.op_side.m_BSTR == 1'b1) && ((r_PS == 2'b01) || (r_PS == 2'b10) || (r_PS == 2'b11))) begin + r_TBSTn <= 1'b0; + end + end + else begin + // ASSIGN WRITE DATA DEPENDING ON BURST INHIBITED OR NOT + if ((r_rpt_cnt == 3'b000) ) begin + if (r_PS == 2'b01) begin + r_AD <= pack({r_AD_32bit_data_byte1,r_AD_32bit_addr_byte2,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + end + else if ((r_PS == 2'b10) || (r_PS == 2'b11)) begin + r_AD <= pack({r_AD_32bit_data_byte1,r_AD_32bit_data_byte2,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + end + else begin + r_AD <= pack({r_AD_32bit_data_byte1,r_AD_32bit_data_byte2,r_AD_32bit_data_byte3,r_AD_32bit_data_byte4}); + end + end + else if (r_rpt_cnt == 3'b011) begin + r_AD <= pack({r_AD_32bit_data_byte2,r_AD_32bit_addr_byte2,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + end + else if (r_rpt_cnt == 3'b010) + r_AD <= pack({r_AD_32bit_data_byte3,r_AD_32bit_addr_byte2,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + else if (r_rpt_cnt == 3'b001) begin + if (r_awsize == 2'b00) begin + if ((r_PS == 2'b10) || (r_PS == 2'b11)) + r_AD <= pack({r_AD_32bit_data_byte3,r_AD_32bit_data_byte4,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + else if ((r_PS == 2'b01)) + r_AD <= pack({r_AD_32bit_data_byte4,r_AD_32bit_addr_byte2,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + end + else if (r_awsize == 2'b10) begin + if (r_PS == 2'b01) r_AD <= pack({r_AD_32bit_data_byte2,r_AD_32bit_addr_byte2,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + + end + end + if (register_ifc.op_side.m_BEM == 1'b1) + r_BE_BWEn <= r2_wstrb[3:0]; + if ((register_ifc.op_side.m_BSTW == 1'b1) && ((r_PS == 2'b01) || (r_PS == 2'b10) || (r_PS == 2'b11))) begin + r_TBSTn <= 1'b0; + end + end + if (r_WS_cnt == 6'h00) begin + if (r_ext_TAn == 1'b0) begin + //r_int_TAn <= 1'b0; + flexbus_state <= FlexBus_S3_BURST; + end + if (register_ifc.op_side.m_AA == 1'b1) begin + r_int_TAn <= 1'b1; + end + r_WS_cnt <= register_ifc.op_side.m_WS; + if (r_R_Wn == 1'b1) begin + if (r_arsize == 2'b00) begin + if ((register_ifc.op_side.m_BSTR == 1'b1) && ((r_PS == 2'b01) || (r_PS == 2'b10) || (r_PS == 2'b11))) begin + if (r_PS == 2'b01) r_burst_cnt <= 2'b11; + if ((r_PS == 2'b10)||(r_PS == 2'b11)) r_burst_cnt <= 2'b01; + end + else if ((register_ifc.op_side.m_BSTR == 1'b0) && ((r_PS == 2'b01) || (r_PS == 2'b10) || (r_PS == 2'b11))) begin + if ((r_PS == 2'b01) && (r_rpt_cnt == 3'b000)) r_rpt_cnt <= 3'b100; + if (((r_PS == 2'b10)||(r_PS == 2'b11)) && (r_rpt_cnt == 3'b000)) r_rpt_cnt <= 3'b010; + end + end + else if (r_arsize == 2'b10) begin + if ((register_ifc.op_side.m_BSTR == 1'b1) && (r_PS == 2'b01)) begin + r_burst_cnt <= 2'b01; + end + else if ((register_ifc.op_side.m_BSTR == 1'b0) && (r_PS == 2'b01)) begin + if ((r_rpt_cnt == 3'b000)) r_rpt_cnt <= 3'b010; + end + end + end + else begin + if (r_awsize == 2'b00) begin + if ((register_ifc.op_side.m_BSTW == 1'b1) && ((r_PS == 2'b01) || (r_PS == 2'b10) || (r_PS == 2'b11))) begin + if (r_PS == 2'b01) r_burst_cnt <= 2'b11; + if ((r_PS == 2'b10)||(r_PS == 2'b11)) r_burst_cnt <= 2'b01; + end + else if ((register_ifc.op_side.m_BSTW == 1'b0) && ((r_PS == 2'b01) || (r_PS == 2'b10) || (r_PS == 2'b11))) begin + if ((r_PS == 2'b01) && (r_rpt_cnt == 3'b000)) r_rpt_cnt <= 3'b100; + if (((r_PS == 2'b10)||(r_PS == 2'b11)) && (r_rpt_cnt == 3'b000)) r_rpt_cnt <= 3'b010; + end + end + else if (r_awsize == 2'b10) begin + if ((register_ifc.op_side.m_BSTW == 1'b1) && (r_PS == 2'b01)) begin + r_burst_cnt <= 2'b01; + end + else if ((register_ifc.op_side.m_BSTW == 1'b0) && (r_PS == 2'b01)) begin + if ((r_rpt_cnt == 3'b000)) r_rpt_cnt <= 3'b010; + end + end + end + end + else begin + r_WS_cnt <= r_WS_cnt -1; + end + `ifdef verbose_debug_l2 $display("r_AD after WRITE = %h r_ASET=%b r_R_Wn= %b r_PS = %b r_AD_32bit_data_byte1=%h ", r_AD, r_ASET, r_R_Wn, r_PS, r_AD_32bit_data_byte1); `endif + endrule + + rule rl_state_S3_BURST (flexbus_state == FlexBus_S3_BURST); // Data Phase with/without bursting terminated prematurely externally + `ifdef verbose_debug $display("STATE S3 FIRED"); `endif + `ifdef verbose_debug_l2 + $display("r_rpt_cnt in BURST = %b", r_rpt_cnt); + $display("r_burst_cnt in BURST = %b, BSTW=%b", r_burst_cnt,register_ifc.op_side.m_BSTW); + $display (" r_AD in BURST = %h", r_AD); + $display("r_AD after WRITE = %h r_R_Wn= %b r_PS = %b r_AD_32bit_data_byte1=%h r_AD_32bit_data_byte2=%h r_AD_32bit_data_byte3=%h", r_AD, r_R_Wn, r_PS, r_AD_32bit_data_byte1,r_AD_32bit_data_byte2,r_AD_32bit_data_byte3); + `endif + if (r_ext_TAn == 1'b1) begin // premature external termination SLVERR response + flexbus_state <= FlexBus_S4_HOLD; + if (r_R_Wn == 1'b1) begin + r_rresp <= AXI4_SLVERR; //SLVERR + end else begin + r_wrbresp <= AXI4_SLVERR; //SLVERR + end + end + else if (r_rpt_cnt == 3'b001) begin + if (r_R_Wn == 1'b1) begin + if (r_arsize == 2'b00) begin + if (r_PS == 2'b01) begin + r_rd_data_32bit_byte4 <= r_din[7:0]; + end + else if ((r_PS == 2'b10) || (r_PS == 2'b11)) begin + r_rd_data_32bit_byte3 <= r_din[7:0]; + r_rd_data_32bit_byte4 <= r_din[15:8]; + end + end + else if (r_arsize == 2'b10) begin + if (r_PS == 2'b01) + r_rd_data_32bit_byte2 <= r_din[7:0]; + end + r_rready <= True; + //r_rpt_cnt <= r_rpt_cnt -1; + end + //else + flexbus_state <= FlexBus_S4_HOLD; + if (register_ifc.op_side.m_AA == 1'b1) begin // check this functionality later for now + r_OEn <= 1'b1; + r_BE_BWEn <= 4'hF; + r_FBCSn <= 6'h3F; + end + end + else if (r_rpt_cnt != 3'b000) begin + flexbus_state <= FlexBus_S1_ADDR; + r_ASET <= register_ifc.op_side.m_ASET; + if (register_ifc.op_side.m_AA == 1'b1) begin + r_OEn <= 1'b1; + r_BE_BWEn <= 4'hF; + r_FBCSn <= 6'h3F; + end + if (r_R_Wn == 1'b1) begin + if ((r_PS == 2'b01) && (r_rpt_cnt == 3'b100)) + r_rd_data_32bit_byte1 <= r_din[7:0]; + else if ((r_PS == 2'b01) && (r_rpt_cnt == 3'b011)) + r_rd_data_32bit_byte2 <= r_din[7:0]; + else if ((r_PS == 2'b01) && (r_rpt_cnt == 3'b010)) begin + if (r_arsize == 2'b00) + r_rd_data_32bit_byte3 <= r_din[7:0]; + else if (r_arsize == 2'b10) + r_rd_data_32bit_byte1 <= r_din[7:0]; + end + else if ((r_PS == 2'b10) || (r_PS == 2'b11)) begin + r_rd_data_32bit_byte1 <= r_din[7:0]; + r_rd_data_32bit_byte2 <= r_din[15:8]; + end + end + end + else if (r_burst_cnt == 2'b01) begin + if (r_ext_TAn == 1'b1) begin + flexbus_state <= FlexBus_S4_HOLD; + end + else begin + if (r_R_Wn == 1'b0) begin + if (r_awsize == 2'b00) begin + if (r_PS == 2'b01) + r_AD <= pack({r_AD_32bit_data_byte4,r_AD_32bit_addr_byte2,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + else if ((r_PS == 2'b10) || (r_PS == 2'b11)) + r_AD <= pack({r_AD_32bit_data_byte3,r_AD_32bit_data_byte4,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + //else + // r_AD <= pack({r_AD_32bit_data_byte1,r_AD_32bit_data_byte2,r_AD_32bit_data_byte3,r_AD_32bit_data_byte4}); + end + else if (r_awsize == 2'b10) begin + if (r_PS == 2'b01) r_AD <= pack({r_AD_32bit_data_byte2,r_AD_32bit_addr_byte2,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + end + end + else begin + if (r_arsize == 2'b00) begin + if (r_PS == 2'b01) + r_rd_data_32bit_byte3 <= r_din[7:0]; + else if ((r_PS == 2'b10) || (r_PS == 2'b11)) begin + r_rd_data_32bit_byte1 <= r_din[7:0]; + r_rd_data_32bit_byte2 <= r_din[15:8]; + end + end + else if (r_arsize == 2'b10) begin + if (r_PS == 2'b01) + r_rd_data_32bit_byte1 <= r_din[7:0]; + end + end + if (register_ifc.op_side.m_SWS_EN == 1'b1) begin + if (r_SWS_cnt == 6'h00) begin + r_SWS_cnt <= register_ifc.op_side.m_SWS; + if (register_ifc.op_side.m_AA == 1'b1) begin + r_int_TAn <= 1'b1; + r_OEn <= 1'b1; + r_BE_BWEn <= 4'hF; + r_FBCSn <= 6'h3F; + end + r_burst_cnt <= r_burst_cnt -1; + //flexbus_state <= FlexBus_S4_HOLD; + end + else begin + r_SWS_cnt <= r_SWS_cnt -1; + end + end + else begin + if (r_WS_cnt == 6'h00) begin + r_WS_cnt <= register_ifc.op_side.m_WS; + if (register_ifc.op_side.m_AA == 1'b1) begin + r_int_TAn <= 1'b1; + r_OEn <= 1'b1; + r_BE_BWEn <= 4'hF; + r_FBCSn <= 6'h3F; + end + r_burst_cnt <= r_burst_cnt -1; + //flexbus_state <= FlexBus_S4_HOLD; + end + else + r_WS_cnt <= r_WS_cnt - 1; + end + end + end + else if (r_burst_cnt != 2'b00) begin + if (r_R_Wn == 1'b0) begin + if ((r_PS == 2'b01) && (r_burst_cnt == 2'b11)) + r_AD <= pack({r_AD_32bit_data_byte2,r_AD_32bit_addr_byte2,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + else if ((r_PS == 2'b01) && (r_burst_cnt == 2'b10)) begin + r_AD <= pack({r_AD_32bit_data_byte3,r_AD_32bit_addr_byte2,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + end + //else if ((r_PS == 2'b01) && (r_burst_cnt == 2'b01)) + // r_AD <= pack({r_AD_32bit_data_byte3,r_AD_32bit_addr_byte2,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + //else if ((r_PS == 2'b10) || (r_PS == 2'b11)) + // r_AD <= pack({r_AD_32bit_data_byte3,r_AD_32bit_data_byte4,r_AD_32bit_addr_byte3,r_AD_32bit_addr_byte4}); + end + else begin + if ((r_PS == 2'b01) && (r_burst_cnt == 2'b11)) + r_rd_data_32bit_byte1 <= r_din[7:0]; + else if ((r_PS == 2'b01) && (r_burst_cnt == 2'b10)) begin + r_rd_data_32bit_byte2 <= r_din[7:0]; + end + end + if (register_ifc.op_side.m_SWS_EN == 1'b1) begin + if (r_SWS_cnt == 6'h00) begin + r_SWS_cnt <= register_ifc.op_side.m_SWS; + if (register_ifc.op_side.m_AA == 1'b1) + r_int_TAn <= 1'b1; + r_burst_cnt <= r_burst_cnt -1; + end + else begin + r_SWS_cnt <= r_SWS_cnt -1; + end + end + else begin + if (r_WS_cnt == 6'h00) begin + r_WS_cnt <= register_ifc.op_side.m_WS; + if (register_ifc.op_side.m_AA == 1'b1) + r_int_TAn <= 1'b1; + r_burst_cnt <= r_burst_cnt -1; + end + else begin + r_WS_cnt <= r_WS_cnt - 1; + end + end + end + else if (r_burst_cnt == 2'b00) begin + flexbus_state <= FlexBus_S4_HOLD; + if (r_R_Wn == 1'b1) begin + if (r_arsize == 2'b00) begin + if (r_PS == 2'b01) begin + r_rd_data_32bit_byte4 <= r_din[7:0]; + end + else if ((r_PS == 2'b10) || (r_PS == 2'b11)) begin + r_rd_data_32bit_byte3 <= r_din[7:0]; + r_rd_data_32bit_byte4 <= r_din[15:8]; + end + else begin + r_rd_data_32bit_byte1 <= r_din[7:0]; + r_rd_data_32bit_byte2 <= r_din[15:8]; + r_rd_data_32bit_byte3 <= r_din[23:16]; + r_rd_data_32bit_byte4 <= r_din[31:24]; + end + end + else if (r_arsize == 2'b10) begin + if (r_PS == 2'b01) + r_rd_data_32bit_byte2 <= r_din[7:0]; + //if ((r_PS == 2'b10) || (r_PS == 2'b11)) begin + else begin + r_rd_data_32bit_byte1 <= r_din[7:0]; + r_rd_data_32bit_byte2 <= r_din[15:8]; + end + end + else if (r_arsize == 2'b01) begin + r_rd_data_32bit_byte1 <= r_din[7:0]; + end + r_rready <= True; + end + if (register_ifc.op_side.m_AA == 1'b1) begin // check this functionality later for now + r_OEn <= 1'b1; + r_BE_BWEn <= 4'hF; + r_FBCSn <= 6'h3F; + end + end + endrule + + rule rl_state_S4_HOLD (flexbus_state == FlexBus_S4_HOLD); //Address Phase + `ifdef verbose_debug $display("STATE S4 FIRED");`endif + r_int_TAn <= 1'b1; + r_R_Wn <= 1'b1; + r_OEn <= 1'b1; + r_BE_BWEn <= 4'hF; + r_FBCSn <= 6'h3F; + r_TBSTn <= 1'b1; + if (r_hld_cnt == 2'b00) begin + if (wr_pending == 1'b1) begin + flexbus_state <= FlexBus_S0_DEQ_WR_FIFOS; + flexbus_state_wr <= IDLE; + flexbus_state_rd <= IDLE; + wr_pending <= 1'b0; + end + else begin + flexbus_state <= IDLE; + flexbus_state_wr <= FlexBus_S0_CHK_FIFOS; + flexbus_state_rd <= FlexBus_S0_CHK_FIFOS; + end + r1_arvalid <= False; + r1_awvalid <= False; + r1_wvalid <= False; + + r_rready <= False; + r_wrbresp <= AXI4_OKAY; + r_rresp <= AXI4_OKAY; + r_ASET <= 2'b00; + r_rpt_cnt <= 3'b000; + r_burst_cnt <= 2'b00; + r_hld_cnt <= 2'b00; + r_WS_cnt <= 6'h00; + r_SWS_cnt <= 6'h00; + r_awaddr <= 0; + r_wdata <= 0; + //r_rd_data <= 0; + r1_wstrb <= 0; + //r2_wstrb <= 0; + r_araddr <= 0; + end + else + r_hld_cnt <= r_hld_cnt -1; + endrule + + // ---------------------------------------------------------------- + // INTERFACE + + method Action reset; + `ifdef verbose_debug_l2 $display (" I RESET \n"); `endif + f_wr_addr.clear; + f_wr_data.clear; + f_wr_resp.clear; + f_rd_addr.clear; + f_rd_data.clear; + + c_TAn[0]<= tagged Invalid; + c_din[0]<= tagged Invalid; + endmethod + + // AXI side + interface axi_side = interface AXI4_Slave_IFC; + + // Wr Addr channel + method Action m_awvalid (Bool awvalid, + Bit #(wd_addr) awaddr, + Bit#(3) awsize, + Bit #(wd_user) awuser, + Bit#(8) awlen, + Bit#(2) awburst, + Bit#(4) awid + ); + if (awvalid && f_wr_addr.notFull) begin + f_wr_addr.enq (AXI4_Wr_Addr {awaddr: awaddr, + awuser: awuser, + awlen:awlen, + awsize:awsize, + awburst:awburst, + awid:awid}); + end + endmethod + + method Bool m_awready; + return f_wr_addr.notFull; + endmethod + + // Wr Data channel + method Action m_wvalid (Bool wvalid, + Bit #(wd_data) wdata, + Bit #(TDiv #(wd_data, 8)) wstrb, + Bool wlast, + Bit#(4) wid); + if (wvalid && f_wr_data.notFull) begin + f_wr_data.enq (AXI4_Wr_Data {wdata: wdata, wstrb: wstrb, wlast:wlast, wid: wid}); + end + endmethod + + method Bool m_wready; + return f_wr_data.notFull; + endmethod + + // Wr Response channel + method Bool m_bvalid = f_wr_resp.notEmpty; + method Bit #(2) m_bresp = pack (f_wr_resp.first.bresp); + method Bit #(wd_user) m_buser = f_wr_resp.first.buser; + method Bit #(4) m_bid = f_wr_resp.first.bid; + method Action m_bready (Bool bready); + if (bready && f_wr_resp.notEmpty) + f_wr_resp.deq; + endmethod + + // Rd Addr channel + method Action m_arvalid (Bool arvalid, + Bit #(wd_addr) araddr, + Bit#(3) arsize, + Bit #(wd_user) aruser, + Bit#(8) arlen, + Bit#(2) arburst, + Bit#(4) arid); + if (arvalid && f_rd_addr.notFull) begin + f_rd_addr.enq (AXI4_Rd_Addr {araddr: araddr, + aruser: aruser, + arlen : arlen, + arsize: arsize, + arburst:arburst, + arid:arid}); + end + endmethod + + method Bool m_arready; + return f_rd_addr.notFull; + endmethod + + // Rd Data channel + method Bool m_rvalid = f_rd_data.notEmpty; + method Bit #(2) m_rresp = pack (f_rd_data.first.rresp); + method Bit #(wd_data) m_rdata = f_rd_data.first.rdata; + method Bool m_rlast = f_rd_data.first.rlast; + method Bit #(wd_user) m_ruser = f_rd_data.first.ruser; + method Bit#(4) m_rid=f_rd_data.first.rid; + + method Action m_rready (Bool rready); + if (rready && f_rd_data.notEmpty) + f_rd_data.deq; + endmethod + endinterface; + +interface flexbus_side = interface FlexBus_Master_IFC; + //interface io_AD_master = tri_AD_out.io; + + method Action m_TAn (Bit #(1) tAn) if(c_TAn[0] matches tagged Invalid); + c_TAn[0] <= tagged Valid tAn; + endmethod + method Action m_din ( Bit#(32) din )if(c_din[0] matches tagged Invalid); + c_din[0] <= tagged Valid din; + endmethod + method Bit #(32) m_AD; + return r_AD; + endmethod + + + method Bit #(1) m_R_Wn; // out + return r_R_Wn; + endmethod + method Bit #(2) m_TSIZ; // out + return r_TSIZ; + endmethod + + + + method Bit #(6) m_FBCSn; // out + return r_FBCSn; + endmethod + method Bit #(4) m_BE_BWEn; // out + return r_BE_BWEn; + endmethod + method Bit #(1) m_TBSTn; // out + return r_TBSTn; + endmethod + method Bit #(1) m_OEn; // out + return r_OEn; + endmethod + + method Bit #(1) m_ALE; // out + return r_ALE; + endmethod + //endinterface; + + endinterface; + +endmodule: mkAXI4_Slave_to_FlexBus_Master_Xactor + +module mkFlexBus_Registers (FlexBus_Register_IFC); + +// Vectors of Chip Select AR, MR and Control Registers + Vector#(6, Reg#(Bit#(32)) ) vec_addr_regs <- replicateM (mkReg(0)); + Vector#(6, Reg#(Bit#(32)) ) vec_mask_regs <- replicateM (mkReg(0)); + Vector#(6, Reg#(Bit#(32)) ) vec_cntr_regs <- replicateM (mkReg(0)); + +// Control Register Fields + + Reg#(Bit#(6)) r_FBCSn <- mkReg(6'h3F); + Reg#(Bit#(6)) r_SWS <- mkReg(6'h00); + Reg#(Bit#(1)) r_SWS_EN <- mkReg(1'b0); + Reg#(Bit#(2)) r_ASET <- mkReg(2'b00); + Reg#(Bit#(2)) r_RDAH <- mkReg(2'b00); + Reg#(Bit#(2)) r_WRAH <- mkReg(2'b00); + Reg#(Bit#(6)) r_WS <- mkReg(6'h00); + Reg#(Bit#(1)) r_AA <- mkReg(1'b0); + Reg#(Bit#(2)) r_PS <- mkReg(2'b00); + Reg#(Bit#(1)) r_BEM <- mkReg(1'b0); + Reg#(Bit#(1)) r_BSTR <- mkReg(1'b0); + Reg#(Bit#(1)) r_BSTW <- mkReg(1'b0); + + Reg#(Bit#(32)) r_rom_cntr_reg_0 <- mkReg(0); + Reg#(Bit#(32)) r_ad_bus <- mkReg(32'hFFFFFFFF); + Reg#(Bit#(32)) r_data_bus <- mkReg(32'h00000000); + Reg#(Bit#(32)) r_MBAR <- mkReg(32'h04000000); +//------------------------------------------------------------------------ + + rule rl_write_config_regs; + Bit#(32) v_MBAR = r_MBAR + 'h0500; + for (int i=0; i<6; i=i+1) begin + if ( v_MBAR == r_ad_bus) begin + vec_addr_regs[i][31:16] <= r_data_bus[31:16]; + end + v_MBAR = v_MBAR + 'h04; + if ( v_MBAR == r_ad_bus) begin + vec_mask_regs[i] <= r_data_bus; + end + v_MBAR = v_MBAR + 'h04; + if ( v_MBAR == r_ad_bus) begin + vec_cntr_regs[i] <= r_data_bus; + end + v_MBAR = v_MBAR + 'h04; + end + endrule + + rule rl_generate_individual_chip_sels; + + Bit#(6) chp_sel_vec = 6'h3F; + Bit#(32) r_cntr_reg_sel = 32'h00000000; + for (int i=0; i<6; i=i+1) begin + if ((~vec_mask_regs[i] & vec_addr_regs[i]) == (~vec_mask_regs[i] & pack({r_ad_bus[31:16],16'h0000}))) begin + chp_sel_vec[i] = 1'b0; + end + end + r_FBCSn <= pack({chp_sel_vec[5],chp_sel_vec[4],chp_sel_vec[3],chp_sel_vec[2],chp_sel_vec[1],chp_sel_vec[0]}); + + case (pack({chp_sel_vec[5],chp_sel_vec[4],chp_sel_vec[3],chp_sel_vec[2],chp_sel_vec[1],chp_sel_vec[0]})) matches + {6'b111110}: r_cntr_reg_sel = vec_cntr_regs[0]; + {6'b111101}: r_cntr_reg_sel = vec_cntr_regs[1]; + {6'b111011}: r_cntr_reg_sel = vec_cntr_regs[2]; + {6'b110111}: r_cntr_reg_sel = vec_cntr_regs[3]; + {6'b101111}: r_cntr_reg_sel = vec_cntr_regs[4]; + {6'b011111}: r_cntr_reg_sel = vec_cntr_regs[5]; + endcase + + r_SWS <= r_cntr_reg_sel[31:26]; + r_SWS_EN <= r_cntr_reg_sel[23]; + r_ASET <= r_cntr_reg_sel[21:20]; + r_RDAH <= r_cntr_reg_sel[19:18]; + r_WRAH <= r_cntr_reg_sel[17:16]; + //r_WS <= r_cntr_reg_sel[15:10]; + r_WS <= 6'h06; + r_AA <= r_cntr_reg_sel[8]; + r_PS <= r_cntr_reg_sel[7:6]; + r_BEM <= r_cntr_reg_sel[5]; + r_BSTR <= r_cntr_reg_sel[4]; + r_BSTW <= r_cntr_reg_sel[3]; + endrule +//------------------------------------------------------------------------- +// FlexBus Register Input Interface +interface inp_side = interface FlexBus_Register_Input_IFC; + method Action reset (Bit #(32) ad_bus); + for (int i=0; i<6; i=i+1) + vec_addr_regs[i] <= 32'h00000000; + for (int i=0; i<6; i=i+1) + vec_mask_regs[i] <= 32'h00000000; + for (int i=0; i<6; i=i+1) + vec_cntr_regs[i] <= 32'h00000000; + r_rom_cntr_reg_0[8] <= ad_bus[2]; + r_rom_cntr_reg_0[7:6] <= ad_bus[1:0]; + r_rom_cntr_reg_0[5] <= ad_bus[3]; + r_rom_cntr_reg_0[15:10] <= 6'h3F; + r_rom_cntr_reg_0[21:16] <= 6'h3F; + vec_cntr_regs[0] <= r_rom_cntr_reg_0; + endmethod + method Action m_ad_bus (Bit #(32) ad_bus); + r_ad_bus <= ad_bus; + endmethod + method Action m_data_bus (Bit #(32) data_bus); + r_data_bus <= data_bus; + endmethod + endinterface; + +// FlexBus Register Output Interface +interface op_side = interface FlexBus_Register_Output_IFC; + method Bit#(6) m_FBCSn (); + return r_FBCSn; + endmethod + method Bit#(6) m_SWS (); + return r_SWS; + endmethod + method Bit#(1) m_SWS_EN (); + return r_SWS_EN; + endmethod + method Bit#(2) m_ASET (); + return r_ASET; + endmethod + method Bit#(2) m_RDAH (); + return r_RDAH; + endmethod + method Bit#(2) m_WRAH (); + return r_WRAH; + endmethod + method Bit#(6) m_WS (); + return r_WS; + endmethod + method Bit#(1) m_AA (); + return r_AA; + endmethod + method Bit#(2) m_PS (); + return r_PS; + endmethod + method Bit#(1) m_BEM (); + return r_BEM; + endmethod + method Bit#(1) m_BSTR (); + return r_BSTR; + endmethod + method Bit#(1) m_BSTW (); + return r_BSTW; + endmethod + endinterface; + +endmodule: mkFlexBus_Registers + + +endpackage diff --git a/src/peripherals/jtagdtm/jtagdefines.bsv b/src/peripherals/jtagdtm/jtagdefines.bsv new file mode 100644 index 0000000..83b1daf --- /dev/null +++ b/src/peripherals/jtagdtm/jtagdefines.bsv @@ -0,0 +1,19 @@ +`define EXTEST 'h00 +`define IDCODE 'h01 +`define SAMPLE_PRELOAD 'h02 +`define SCANMODE_TE 'h03 +`define SCAN1 'h04 +`define SCAN2 'h05 +`define SCAN3 'h06 +`define SCAN4 'h07 +`define SCAN5 'h08 +`define SCANALL 'h12 +`define SCANEN 'h13 +`define FULLSCANEN 'h14 +`define DEBUG 'h0A +`define MBIST 'h09 +`define BYPASS 'h1f +`define DTMCONTROL 'h10 +`define DMIACCESS 'h11 +//`define IDCODEVALUE 32'h10e31913 +`define IDCODEVALUE 32'h100039D3 diff --git a/src/peripherals/jtagdtm/jtagdtm.bsv b/src/peripherals/jtagdtm/jtagdtm.bsv new file mode 100644 index 0000000..aea5b37 --- /dev/null +++ b/src/peripherals/jtagdtm/jtagdtm.bsv @@ -0,0 +1,568 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +package jtagdtm; +/*====== Package imports ======= */ + import Clocks::*; + import ConcatReg::*; + import FIFO::*; + import FIFOF::*; + import SpecialFIFOs::*; + import DReg::*; +/*======= Project imports ===== */ + `include "jtagdefines.bsv" + import defined_types::*; +/*============================== */ + +interface Ifc_jtagdtm; + /*======== Scan input pins ===== */ + (*always_enabled,always_ready*) + method Action scan_out_1_i(Bit#(1) scan_out_1); + (*always_enabled,always_ready*) + method Action scan_out_2_i(Bit#(1) scan_out_2); + (*always_enabled,always_ready*) + method Action scan_out_3_i(Bit#(1) scan_out_3); + (*always_enabled,always_ready*) + method Action scan_out_4_i(Bit#(1) scan_out_4); + (*always_enabled,always_ready*) + method Action scan_out_5_i(Bit#(1) scan_out_5); + /*======= SCAN Output Pins ====== */ + (*always_enabled,always_ready*) + method Bit#(1) scan_in_1; + (*always_enabled,always_ready*) + method Bit#(1) scan_in_2; + (*always_enabled,always_ready*) + method Bit#(1) scan_in_3; + (*always_enabled,always_ready*) + method Bit#(1) scan_in_4; + (*always_enabled,always_ready*) + method Bit#(1) scan_in_5; + (*always_enabled,always_ready*) + method Bit#(1) scan_en; + (*always_enabled,always_ready*) + method Bit#(1) scan_mode_te; + /*======= BOUNDARY SCAN Output Pin ====== */ + (*always_enabled,always_ready*) + method Action bs_chain_i(Bit#(1) bs_chain); + /*======= BOUNDARY SCAN input Pins ====== */ + (*always_enabled,always_ready*) + method Bit#(1) shiftBscan2Edge; + (*always_enabled,always_ready*) + method Bit#(1) selectJtagInput; + (*always_enabled,always_ready*) + method Bit#(1) selectJtagOutput; + (*always_enabled,always_ready*) + method Bit#(1) updateBscan; + (*always_enabled,always_ready*) + method Bit#(1) bscan_in; + (*always_enabled,always_ready*) + method Bit#(1) scan_shift_en; + /*======== JTAG input pins ===== */ + (*always_enabled,always_ready*) + method Action tms_i(Bit#(1) tms); + (*always_enabled,always_ready*) + method Action tdi_i(Bit#(1) tdi); + /*==== inputs from Sub-modules === */ + method Action debug_tdi_i(Bit#(1) debug_tdi); + /*======= JTAG Output Pins ====== */ + (*always_enabled,always_ready*) + method Bit#(1) tdo; + method Bit#(1) tdo_oe; + /*======== TAP States ============= */ + method Bit#(1) shift_dr; + method Bit#(1) pause_dr; + method Bit#(1) update_dr; + method Bit#(1) capture_dr; + /*=========== Output for BS Chain ==== */ + method Bit#(1) extest_select; + method Bit#(1) sample_preload_select; + method Bit#(1) debug_select; + method Bit#(1) debug_tdo; + /*================================ */ + method Action response_from_dm(Bit#(34) responsedm); + method ActionValue#(Bit#(40)) request_to_dm; + +endinterface + + function Reg#(t) readOnlyReg(t r); + return (interface Reg; + method t _read = r; + method Action _write(t x) = noAction; + endinterface); + endfunction + function Reg#(Bit#(1)) condwriteSideEffect(Reg#(Bit#(1)) r, Action a); + return (interface Reg; + method Bit#(1) _read = r._read; + method Action _write(Bit#(1) x); + r._write(x); + if(x==1) + a; + endmethod + endinterface); + endfunction + + + +typedef enum {TestLogicReset = 4'h0, RunTestIdle = 4'h1, SelectDRScan = 4'h2, + CaptureDR = 4'h3, ShiftDR = 4'h4, Exit1DR = 4'h5, + PauseDR = 4'h6, Exit2DR = 4'h7, UpdateDR = 4'h8, + SelectIRScan = 4'h9, CaptureIR = 4'ha, ShiftIR = 4'hb, + Exit1IR = 4'hc, PauseIR = 4'hd, Exit2IR = 4'he, + UpdateIR = 4'hf } TapStates deriving(Bits,Eq,FShow); + + (*synthesize*) + (*descending_urgency="scan_logic,scan_shift_en"*) + module mkjtagdtm(Ifc_jtagdtm); + Clock def_clk<-exposeCurrentClock; + Clock invert_clock<-invertCurrentClock; + Reset invert_reset<-mkAsyncResetFromCR(0,invert_clock); + + /*========= FIFOs to communicate with the DM==== */ + FIFOF#(Bit#(40)) request_to_DM <-mkUGFIFOF1(); + FIFOF#(Bit#(34)) response_from_DM <-mkUGFIFOF1(); + /*================================================ */ + + /*=== Wires to capture the input pins === */ + Wire#(Bit#(1)) wr_tms<-mkDWire(0); + Wire#(Bit#(1)) wr_tdi<-mkDWire(0); + Reg#(Bit#(1)) wr_debug_tdi<-mkRegA(0); + Reg#(Bit#(1)) wr_bs_chain_tdo<-mkRegA(0); + /*======================================== */ + + Wire#(Bit#(1)) wr_scan_in_1_all <-mkDWire(0); + Wire#(Bit#(1)) wr_scan_in_2_out1 <-mkDWire(0); + Wire#(Bit#(1)) wr_scan_in_3_out2 <-mkDWire(0); + Wire#(Bit#(1)) wr_scan_in_4_out3 <-mkDWire(0); + Wire#(Bit#(1)) wr_scan_in_5_out4 <-mkDWire(0); + Reg#(Bit#(1)) wr_scan_shift_en[2] <-mkCRegA(2,0); + + Reg#(TapStates) tapstate<-mkRegA(TestLogicReset); + Reg#(Bit#(5)) instruction_shiftreg<-mkRegA(0); + Reg#(Bit#(5)) instruction<-mkRegA(`IDCODE, clocked_by invert_clock, reset_by invert_reset); // clock this by the inverted clock + Reg#(Bit#(1)) bypass_sr<-mkRegA(0); + Reg#(Bit#(1)) scan1_sr <-mkRegA(0); + Reg#(Bit#(1)) scan2_sr <-mkRegA(0); + Reg#(Bit#(1)) scan3_sr <-mkRegA(0); + Reg#(Bit#(1)) scan4_sr <-mkRegA(0); + Reg#(Bit#(1)) scan5_sr <-mkRegA(0); + Reg#(Bit#(1)) scanall_sr<-mkRegA(0); + Reg#(Bit#(1)) scan_en_sr<-mkRegA(0); + Reg#(Bit#(1)) scan_mode_te_sr<-mkRegA(0); + Reg#(Bit#(1)) full_scan_en_sr<-mkRegA(0); + Reg#(Bit#(1)) scan_out_1_sr<-mkRegA(0); + Reg#(Bit#(1)) scan_out_2_sr<-mkRegA(0); + Reg#(Bit#(1)) scan_out_3_sr<-mkRegA(0); + Reg#(Bit#(1)) scan_out_4_sr<-mkRegA(0); + Reg#(Bit#(1)) scan_out_5_sr<-mkRegA(0); + Wire#(Bit#(1)) shiftBscan2Edge_sr<-mkDWire(0); + Wire#(Bit#(1)) selectJtagInput_sr<-mkDWire(0); + Wire#(Bit#(1)) selectJtagOutput_sr<-mkDWire(0); + Wire#(Bit#(1)) updateBscan_sr<-mkDWire(0); + Reg#(Bit#(1)) bs_sr<-mkRegA(0); + Reg#(Bit#(32)) idcode_sr<-mkRegA(`IDCODEVALUE); + + Wire#(Bool) wr_dmihardreset_generated<-mkDWire(False); + Reg#(Bit#(1)) rg_dmihardreset<-mkRegA(0); + Reg#(Bit#(1)) dmihardreset=condwriteSideEffect(rg_dmihardreset,wr_dmihardreset_generated._write(True)); + Wire#(Bool) wr_dmireset_generated<-mkDWire(False); + Reg#(Bit#(1)) rg_dmireset<-mkDReg(0); + Reg#(Bit#(1)) dmireset=condwriteSideEffect(rg_dmireset,wr_dmireset_generated._write(True)); + Reg#(Bit#(3)) idle=readOnlyReg(3'd7); + Reg#(Bit#(2)) dmistat<-mkRegA(0); + Reg#(Bit#(6)) abits =readOnlyReg(6'd6); + Reg#(Bit#(4)) version = readOnlyReg('d1); + Reg#(Bit#(32)) dtmcontrol=concatReg8(readOnlyReg(14'd0), + dmihardreset,dmireset,readOnlyReg(1'd0), + idle,readOnlyReg(dmistat),abits,version); + Reg#(Bit#(32)) dtmcontrol_shiftreg<-mkRegA({17'd0,3'd7,2'd0,6'd6,4'd1}); + + Reg#(Bit#(40)) dmiaccess_shiftreg[2]<-mkCReg(2,'d2); + Reg#(Bit#(2)) response_status<-mkReg(0); + Reg#(Bool) capture_repsonse_from_dm<-mkRegA(False); + Reg#(Bit#(1)) rg_tdo<-mkRegA(0, clocked_by invert_clock, reset_by invert_reset); + + ReadOnly#(TapStates) crossed_tapstate <-mkNullCrossingWire(invert_clock,tapstate); + ReadOnly#(Bit#(5)) crossed_instruction_shiftreg<-mkNullCrossingWire(invert_clock,instruction_shiftreg); + ReadOnly#(Bit#(5)) crossed_instruction <-mkNullCrossingWire(def_clk,instruction); + ReadOnly#(Bit#(1)) crossed_scan_out_1_sr <-mkNullCrossingWire(invert_clock,scan_out_1_sr); + ReadOnly#(Bit#(1)) crossed_scan_out_2_sr <-mkNullCrossingWire(invert_clock,scan_out_2_sr); + ReadOnly#(Bit#(1)) crossed_scan_out_3_sr <-mkNullCrossingWire(invert_clock,scan_out_3_sr); + ReadOnly#(Bit#(1)) crossed_scan_out_4_sr <-mkNullCrossingWire(invert_clock,scan_out_4_sr); + ReadOnly#(Bit#(1)) crossed_scan_out_5_sr <-mkNullCrossingWire(invert_clock,scan_out_5_sr); + ReadOnly#(Bit#(1)) crossed_scan_en_sr <-mkNullCrossingWire(invert_clock,scan_en_sr); + ReadOnly#(Bit#(1)) crossed_scan_mode_te_sr <-mkNullCrossingWire(invert_clock,scan_mode_te_sr); + ReadOnly#(Bit#(1)) crossed_full_scan_en_sr <-mkNullCrossingWire(invert_clock,full_scan_en_sr); + ReadOnly#(Bit#(1)) crossed_bypass_sr <-mkNullCrossingWire(invert_clock,bypass_sr); + ReadOnly#(Bit#(32)) crossed_idcode_sr <-mkNullCrossingWire(invert_clock,idcode_sr); + ReadOnly#(Bit#(1)) crossed_bs_chain_tdo <-mkNullCrossingWire(invert_clock,wr_bs_chain_tdo); + ReadOnly#(Bit#(1)) crossed_debug_tdi <-mkNullCrossingWire(invert_clock,wr_debug_tdi); + ReadOnly#(Bit#(32)) crossed_dtmcontrol_shiftreg<-mkNullCrossingWire(invert_clock,dtmcontrol_shiftreg); + ReadOnly#(Bit#(1)) crossed_output_tdo<-mkNullCrossingWire(def_clk,rg_tdo); + ReadOnly#(Bit#(40)) crossed_dmiaccess_shiftreg<-mkNullCrossingWire(invert_clock,dmiaccess_shiftreg[0]); + + Bit#(1) bypass_sel = crossed_instruction == `BYPASS?1:0; + Bit#(1) scan_en_sel = crossed_instruction == `SCANEN?1:0; + Bit#(1) scan_mode_te_sel = crossed_instruction == `SCANMODE_TE?1:0; + Bit#(1) scan1_sel = crossed_instruction == `SCAN1?1:0; + Bit#(1) scan2_sel = crossed_instruction == `SCAN2?1:0; + Bit#(1) scan3_sel = crossed_instruction == `SCAN3?1:0; + Bit#(1) scan4_sel = crossed_instruction == `SCAN4?1:0; + Bit#(1) scan5_sel = crossed_instruction == `SCAN5?1:0; + Bit#(1) scanall_sel = crossed_instruction == `SCANALL?1:0; + Bit#(1) full_scan_en_sel = crossed_instruction == `FULLSCANEN?1:0; + Bit#(1) idcode_sel = crossed_instruction == `IDCODE?1:0; + Bit#(1) dbg_sel = crossed_instruction == `DEBUG?1:0; + Bit#(1) dtmcontrol_sel = crossed_instruction == `DTMCONTROL?1:0; + Bit#(1) dmi_sel = crossed_instruction == `DMIACCESS?1:0; + Bit#(1) extest_select=crossed_instruction==`EXTEST?1:0; + Bit#(1) sample_preload_select=crossed_instruction==`SAMPLE_PRELOAD?1:0; + + Bit#(1) instruction_tdo=crossed_instruction_shiftreg[0]; + Bit#(1) bypass_tdo=crossed_bypass_sr; + Bit#(1) scan_en_tdo=crossed_scan_en_sr; + Bit#(1) scan_mode_te_tdo=crossed_scan_mode_te_sr; + Bit#(1) full_scan_en_tdo=crossed_full_scan_en_sr; + Bit#(1) scan_out_1_tdo=crossed_scan_out_1_sr; + Bit#(1) scan_out_2_tdo=crossed_scan_out_2_sr; + Bit#(1) scan_out_3_tdo=crossed_scan_out_3_sr; + Bit#(1) scan_out_4_tdo=crossed_scan_out_4_sr; + Bit#(1) scan_out_5_tdo=crossed_scan_out_5_sr; + Bit#(1) idcode_tdo=crossed_idcode_sr[0]; + Bit#(1) dtmcontrol_tdo=crossed_dtmcontrol_shiftreg[0]; + Bit#(1) dmiaccess_tdo=crossed_dmiaccess_shiftreg[0][0]; + + + + /*== This rule implements the TAPs STATE MACHINE====== */ + rule just_display; + `ifdef verbose $display($time,"\tTAPSTATE: ",fshow(tapstate),"\tINSTRUCTION: %h",instruction_shiftreg); `endif + endrule + rule tap_state_machine; + case(tapstate) + TestLogicReset: if(wr_tms==0) tapstate<=RunTestIdle; + RunTestIdle : if(wr_tms==1) tapstate <= SelectDRScan; + SelectDRScan : if(wr_tms==1) tapstate <= SelectIRScan; + else tapstate <= CaptureDR; + CaptureDR : if(wr_tms==0) tapstate <= ShiftDR; + else tapstate <= Exit1DR; + ShiftDR : if(wr_tms==1) tapstate <= Exit1DR; + Exit1DR : if(wr_tms==0) tapstate <= PauseDR; + else tapstate <= UpdateDR; + PauseDR : if(wr_tms==1) tapstate <= Exit2DR; + Exit2DR : if(wr_tms==1) tapstate <= UpdateDR; + else tapstate <= ShiftDR; + UpdateDR : if(wr_tms==1) tapstate <= SelectDRScan; + else tapstate <= RunTestIdle; + SelectIRScan : if(wr_tms==1) tapstate <= TestLogicReset; + else tapstate <= CaptureIR; + CaptureIR : if(wr_tms==0) tapstate <= ShiftIR; + else tapstate <= Exit1IR; + ShiftIR : if(wr_tms==1) tapstate <= Exit1IR; + Exit1IR : if(wr_tms==0) tapstate <= PauseIR; + else tapstate <= UpdateIR; + PauseIR : if(wr_tms==1) tapstate <= Exit2IR; + Exit2IR : if(wr_tms==1) tapstate <= UpdateIR; + else tapstate <= ShiftIR; + UpdateIR : if(wr_tms==1) tapstate <= SelectDRScan; + else tapstate <= RunTestIdle; + default : tapstate <= TestLogicReset; + endcase + endrule + + rule dmireset_generated(wr_dmireset_generated); + `ifdef verbose $display($time,"\tDTM: Received DMIRESET"); `endif + dmiaccess_shiftreg[1][1:0]<='d0; + response_status<=0; + capture_repsonse_from_dm<=False; + endrule + rule dmihardreset_generated(wr_dmihardreset_generated); + request_to_DM.deq; + response_from_DM.deq; + capture_repsonse_from_dm<=False; + endrule + + /*======= perform dtmcontrol shifts ======== */ + rule shift_dtm; + case(tapstate) + TestLogicReset: dtmcontrol<={17'd0,idle,2'b0,abits,version}; + CaptureDR: if(dtmcontrol_sel==1) dtmcontrol_shiftreg<=dtmcontrol; + ShiftDR: if(dtmcontrol_sel==1) dtmcontrol_shiftreg<={wr_tdi,dtmcontrol_shiftreg[31:1]}; + UpdateDR: if(dtmcontrol_sel==1) dtmcontrol<=dtmcontrol_shiftreg; + endcase + endrule + /*========================================== */ + /*======= perform dmiaccess shifts ======== */ + rule shift_dmiaccess(!wr_dmihardreset_generated); + case(tapstate) + TestLogicReset: dmiaccess_shiftreg[0]<='d0; + CaptureDR: if(dmi_sel==1) + if(response_from_DM.notEmpty)begin + let x=response_from_DM.first[33:0]; + `ifdef verbose $display($time,"\tDTM: Getting response: data %h op: %h",x[33:2],x[1:0]); `endif + x[1:0]=x[1:0]|response_status;// keeping the lower 2 bits sticky + dmiaccess_shiftreg[0][33:0]<=x; + response_status<=x[1:0]; + response_from_DM.deq; + `ifdef verbose $display($time,"\tDTM: New DMIACCESS value: %h",x); `endif + capture_repsonse_from_dm<=False; + dmistat<=x[1:0]; + end + else begin + if(capture_repsonse_from_dm) + response_status<=3; + `ifdef verbose $display($time,"\tDTM: RESPONSE NOT AVAILABLE. DMIACCESS: %h",dmiaccess_shiftreg[0]); `endif + end + ShiftDR: if(dmi_sel==1) dmiaccess_shiftreg[0]<={wr_tdi,dmiaccess_shiftreg[0][39:1]}; + UpdateDR: if(dmi_sel==1) + if(request_to_DM.notFull && dmiaccess_shiftreg[0][1:0]!=0 && capture_repsonse_from_dm==False)begin + request_to_DM.enq(dmiaccess_shiftreg[0]); + dmiaccess_shiftreg[0][1:0]<='d3; + capture_repsonse_from_dm<=True; + `ifdef verbose $display($time,"\tDTM: Sending request to Debug: %h",dmiaccess_shiftreg[0]); `endif + end + else begin + `ifdef verbose $display($time,"\tDTM: REQUEST NOT SERVED capture: %b DMIACCESS: %h",capture_repsonse_from_dm,dmiaccess_shiftreg[0]); `endif +// dmistat<=3; +// response_from_DM.enq('d3); + end + endcase + endrule + /*========================================== */ + + /*== perform instruction register shifts === */ + rule shift_reg; + case(tapstate) + CaptureIR: instruction_shiftreg<='b10101; + ShiftIR : instruction_shiftreg<= {wr_tdi,instruction_shiftreg[4:1]}; + endcase + endrule + rule transfer_instruction_on_nedge; // TODO negedge here + case(crossed_tapstate) + TestLogicReset :instruction<=`IDCODE; + UpdateIR :instruction<=crossed_instruction_shiftreg; + endcase + endrule + + /*==== Bypass Section === */ + rule bypass_logic; + case(tapstate) + TestLogicReset: bypass_sr<=1'b0; + CaptureDR : if(bypass_sel==1) bypass_sr<=1'b0; + ShiftDR : if(bypass_sel==1) bypass_sr<=wr_tdi; + endcase + endrule + + /*==== Boundary Scan Section === */ + rule bs_logic; + case(tapstate) + TestLogicReset: bs_sr<=1'b0; + CaptureDR : begin + if(extest_select==1) begin + shiftBscan2Edge_sr <= 1'b0; + selectJtagInput_sr <= 1'b0; + selectJtagOutput_sr <= 1'b0; + updateBscan_sr <= 1'b0; + bs_sr<=1'b0; + end else if (sample_preload_select ==1) begin + shiftBscan2Edge_sr <= 1'b0; + selectJtagInput_sr <= 1'b0; + selectJtagOutput_sr <= 1'b0; + bs_sr<=1'b0; + end + end + ShiftDR : begin + if(extest_select==1) begin + shiftBscan2Edge_sr <= 1'b1; + selectJtagInput_sr <= 1'b0; + selectJtagOutput_sr <= 1'b0; + updateBscan_sr <= 1'b0; + bs_sr<=wr_tdi; + end else if (sample_preload_select ==1) begin + bs_sr<=wr_tdi; + shiftBscan2Edge_sr <= 1'b1; + end + end + UpdateDR : begin + if(extest_select==1) begin + shiftBscan2Edge_sr <= 1'b1; + selectJtagInput_sr <= 1'b1; + selectJtagOutput_sr <= 1'b1; + updateBscan_sr <= 1'b1; + end + end + endcase + endrule + + /*==== Scan Chain Section === */ + rule scan_logic; + case(tapstate) + TestLogicReset: begin + scan_en_sr<=1'b0; + scan_mode_te_sr<=1'b0; + scan1_sr<=1'b0; + scan2_sr<=1'b0; + scan3_sr<=1'b0; + scan4_sr<=1'b0; + scan5_sr<=1'b0; + scanall_sr<=1'b0; + full_scan_en_sr<=1'b0; + wr_scan_shift_en[0]<=1'b0; + end + CaptureDR : begin + if(scan_en_sel==1) scan_en_sr<=1'b0; + else if(scan_mode_te_sel==1) scan_mode_te_sr<=1'b0; + else if(scan1_sel==1) scan1_sr<=1'b0; + else if(scan2_sel==1) scan2_sr<=1'b0; + else if(scan3_sel==1) scan3_sr<=1'b0; + else if(scan4_sel==1) scan4_sr<=1'b0; + else if(scan5_sel==1) scan5_sr<=1'b0; + else if(scanall_sel==1) scanall_sr<=1'b0; + else if(full_scan_en_sel==1) full_scan_en_sr<=1'b0; + wr_scan_shift_en[0]<=1'b0; + end + ShiftDR : begin + if(scan_en_sel==1) scan_en_sr<=wr_tdi; + else if(scan_mode_te_sel==1) scan_mode_te_sr<=wr_tdi; + else if(scan1_sel==1) scan1_sr<=wr_tdi; + else if(scan2_sel==1) scan2_sr<=wr_tdi; + else if(scan3_sel==1) scan3_sr<=wr_tdi; + else if(scan4_sel==1) scan4_sr<=wr_tdi; + else if(scan5_sel==1) scan5_sr<=wr_tdi; + else if(scanall_sel==1) scanall_sr<=wr_tdi; + else if(full_scan_en_sel==1) full_scan_en_sr<=wr_tdi; + if ((scan1_sel == 1'b1 || scan2_sel == 1'b1|| scan3_sel == 1'b1|| scan4_sel == 1'b1|| scan5_sel == 1'b1|| scanall_sel == 1'b1) || (scan_en_sel == 1'b1 && wr_tdi == 1'b0)) wr_scan_shift_en[1] <=1'b1; + end + UpdateDR : wr_scan_shift_en[0] <=1'b0; + endcase + endrule + + rule full_scan_mux_logic; + if (full_scan_en_sr == 1'b1) begin + wr_scan_in_1_all <= scanall_sr; + wr_scan_in_2_out1 <= scan_out_1_sr; + wr_scan_in_3_out2 <= scan_out_2_sr; + wr_scan_in_4_out3 <= scan_out_3_sr; + wr_scan_in_5_out4 <= scan_out_4_sr; + end + else begin + wr_scan_in_1_all <= scan1_sr; + wr_scan_in_2_out1 <= scan2_sr; + wr_scan_in_3_out2 <= scan3_sr; + wr_scan_in_4_out3 <= scan4_sr; + wr_scan_in_5_out4 <= scan5_sr; + end + endrule + + /*======= IDCODE section === */ + rule idcode_logic; + case(tapstate) + TestLogicReset:idcode_sr<=`IDCODEVALUE; + CaptureDR: if(idcode_sel==1) idcode_sr<=`IDCODEVALUE; + ShiftDR : if(idcode_sel==1) idcode_sr<={wr_tdi,idcode_sr[31:1]}; + endcase + endrule + + rule generate_tdo_outputpin; + if(crossed_tapstate==ShiftIR) + rg_tdo<=instruction_tdo; + else + case(instruction) + `IDCODE: rg_tdo<=idcode_tdo; + `DEBUG : rg_tdo<=crossed_debug_tdi; + `EXTEST: rg_tdo<=crossed_bs_chain_tdo; + `SAMPLE_PRELOAD: rg_tdo<=crossed_bs_chain_tdo; + `BYPASS: rg_tdo<=bypass_tdo; + `SCANEN: rg_tdo<=scan_en_tdo; + `SCANMODE_TE: rg_tdo<=scan_mode_te_tdo; + `FULLSCANEN: rg_tdo<=full_scan_en_tdo; + `SCAN1: rg_tdo <= scan_out_1_tdo; + `SCAN2: rg_tdo <= scan_out_2_tdo; + `SCAN3: rg_tdo <= scan_out_3_tdo; + `SCAN4: rg_tdo <= scan_out_4_tdo; + `SCAN5: rg_tdo <= scan_out_5_tdo; + `SCANALL: rg_tdo <= scan_out_5_tdo; + `DTMCONTROL: rg_tdo<=dtmcontrol_tdo; + `DMIACCESS: rg_tdo<=dmiaccess_tdo; + default: rg_tdo<=bypass_tdo; + endcase + endrule + + /*======== SCAN input (scan chain outputs) pins ===== */ + method Action scan_out_1_i(Bit#(1) scan_out_1); + scan_out_1_sr<=scan_out_1; + endmethod + method Action scan_out_2_i(Bit#(1) scan_out_2); + scan_out_2_sr<=scan_out_2; + endmethod + method Action scan_out_3_i(Bit#(1) scan_out_3); + scan_out_3_sr<=scan_out_3; + endmethod + method Action scan_out_4_i(Bit#(1) scan_out_4); + scan_out_4_sr<=scan_out_4; + endmethod + method Action scan_out_5_i(Bit#(1) scan_out_5); + scan_out_5_sr<=scan_out_5; + endmethod + /*======== JTAG input pins ===== */ + method Action tms_i(Bit#(1) tms); + wr_tms<=tms; + endmethod + method Action tdi_i(Bit#(1) tdi); + wr_tdi<=tdi; + endmethod + /*============================= */ + method Action debug_tdi_i(Bit#(1) debug_tdi); + wr_debug_tdi<=debug_tdi; + endmethod + /*======= Boundary Scan Input Pins ====== */ + method Action bs_chain_i(Bit#(1) bs_chain); + wr_bs_chain_tdo<=bs_chain; + endmethod + /*======== TAP States ============= */ + method shift_dr=tapstate==ShiftDR?1:0; + method pause_dr=tapstate==PauseDR?1:0; + method update_dr=tapstate==UpdateDR?1:0; + method capture_dr=tapstate==CaptureDR?1:0; + /*=================================== */ + method debug_select =crossed_instruction==`DEBUG?1:0; + /*================================ */ + /*======= SCAN Output (Scan Chain Inputs) Pins ====== */ + method scan_in_1 = wr_scan_in_1_all; + method scan_in_2 = wr_scan_in_2_out1; + method scan_in_3 = wr_scan_in_3_out2; + method scan_in_4 = wr_scan_in_4_out3; + method scan_in_5 = wr_scan_in_5_out4; + method scan_en = scan_en_sr; + method scan_mode_te = scan_mode_te_sr; + /*======= Boundary Scan Output Pins ====== */ + method shiftBscan2Edge = shiftBscan2Edge_sr; + method selectJtagInput = selectJtagInput_sr; + method selectJtagOutput = selectJtagOutput_sr; + method updateBscan = updateBscan_sr; + method bscan_in = bs_sr; + method scan_shift_en = wr_scan_shift_en[1]; + /*======= JTAG Output Pins ====== */ + method tdo = crossed_output_tdo; + method debug_tdo = wr_tdi; + method Bit#(1) tdo_oe = ((tapstate == ShiftIR) || (tapstate == ShiftDR))?1:0; + method Action response_from_dm(Bit#(34) responsedm) if(response_from_DM.notFull); + if(capture_repsonse_from_dm) + response_from_DM.enq(responsedm); + endmethod + method ActionValue#(Bit#(40)) request_to_dm if(request_to_DM.notEmpty); + request_to_DM.deq; + return request_to_DM.first; + endmethod + endmodule + +endpackage diff --git a/src/peripherals/jtagdtm/jtagdtm_new.bsv b/src/peripherals/jtagdtm/jtagdtm_new.bsv new file mode 100644 index 0000000..ae22304 --- /dev/null +++ b/src/peripherals/jtagdtm/jtagdtm_new.bsv @@ -0,0 +1,337 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +package jtagdtm_new; +/*====== Package imports ======= */ + import ConcatReg::*; + import FIFO::*; + import FIFOF::*; + import SpecialFIFOs::*; +/*======= Project imports ===== */ + `include "jtagdefines.bsv" + import defined_types::*; +/*============================== */ + +interface Ifc_jtagdtm; + /*======== JTAG input pins ===== */ + (*always_enabled,always_ready*) + method Action tms_i(Bit#(1) tms); + (*always_enabled,always_ready*) + method Action tdi_i(Bit#(1) tdi); + (*always_enabled,always_ready*) + method Action tck_i(Bit#(1) tck); + (*always_enabled,always_ready*) + method Action trst_i(Bit#(1) trst); + /*==== inputs from Sub-modules === */ + method Action debug_tdi_i(Bit#(1) debug_tdi); + method Action bs_chain_i(Bit#(1) bs_chain); + /*======= JTAG Output Pins ====== */ + (*always_enabled,always_ready*) + method Bit#(1) tdo; + method Bit#(1) tdo_oe; + /*======== TAP States ============= */ + method Bit#(1) shift_dr; + method Bit#(1) pause_dr; + method Bit#(1) update_dr; + method Bit#(1) capture_dr; + /*=========== Output for BS Chain ==== */ + method Bit#(1) extest_select; + method Bit#(1) sample_preload_select; + method Bit#(1) debug_select; + method Bit#(1) debug_tdo; + /*================================ */ + method Action response_from_dm(Bit#(34) responsedm); + method ActionValue#(Bit#(40)) request_to_dm; + +endinterface + + function Reg#(t) readOnlyReg(t r); + return (interface Reg; + method t _read = r; + method Action _write(t x) = noAction; + endinterface); + endfunction + function Reg#(Bit#(1)) condwriteSideEffect(Reg#(Bit#(1)) r, Action a); + return (interface Reg; + method Bit#(1) _read = r._read; + method Action _write(Bit#(1) x); + r._write(x); + if(x==1) + a; + endmethod + endinterface); + endfunction + + + +typedef enum {TestLogicReset = 4'h0, RunTestIdle = 4'h1, SelectDRScan = 4'h2, + CaptureDR = 4'h3, ShiftDR = 4'h4, Exit1DR = 4'h5, + PauseDR = 4'h6, Exit2DR = 4'h7, UpdateDR = 4'h8, + SelectIRScan = 4'h9, CaptureIR = 4'ha, ShiftIR = 4'hb, + Exit1IR = 4'hc, PauseIR = 4'hd, Exit2IR = 4'he, + UpdateIR = 4'hf } TapStates deriving(Bits,Eq,FShow); + + (*synthesize*) + module mkjtagdtm(Ifc_jtagdtm); + Reg#(Bit#(1)) prv_clk <-mkReg(0); + PulseWire posedge_clk <-mkPulseWire(); + PulseWire negedge_clk <-mkPulseWire(); + /*========= FIFOs to communicate with the DM==== */ + FIFOF#(Bit#(40)) request_to_DM <-mkUGFIFOF1(); + FIFOF#(Bit#(34)) response_from_DM <-mkUGFIFOF1(); + /*================================================ */ + + /*=== Wires to capture the input pins === */ + Wire#(Bit#(1)) wr_tms<-mkDWire(0); + Wire#(Bit#(1)) wr_tdi<-mkDWire(0); + Wire#(Bool) wr_trst<-mkDWire(False); + Wire#(Bit#(1)) wr_debug_tdi<-mkDWire(0); + Wire#(Bit#(1)) wr_bs_chain_tdi<-mkDWire(0); + /*======================================== */ + + Reg#(TapStates) tapstate<-mkRegA(TestLogicReset); + Reg#(Bit#(5)) instruction_shiftreg<-mkRegA(0); + Reg#(Bit#(5)) instruction<-mkRegA(`IDCODE); // clock this by the inverted clock + Reg#(Bit#(1)) bypass_sr<-mkRegA(0); + Reg#(Bit#(32)) idcode_sr<-mkRegA(`IDCODEVALUE); + + Wire#(Bool) wr_dmihardreset_generated<-mkDWire(False); + Reg#(Bit#(1)) rg_dmihardreset<-mkRegA(0); + Reg#(Bit#(1)) dmihardreset=condwriteSideEffect(rg_dmihardreset,wr_dmihardreset_generated._write(True)); + Wire#(Bool) wr_dmireset_generated<-mkDWire(False); + Reg#(Bit#(1)) rg_dmireset<-mkRegA(0); + Reg#(Bit#(1)) dmireset=condwriteSideEffect(rg_dmireset,wr_dmireset_generated._write(True)); + Reg#(Bit#(3)) idle=readOnlyReg(3'd7); + Reg#(Bit#(2)) dmistat<-mkRegA(0); + Reg#(Bit#(6)) abits =readOnlyReg(6'd6); + Reg#(Bit#(4)) version = readOnlyReg('d1); + Reg#(Bit#(32)) dtmcontrol=concatReg8(readOnlyReg(14'd0), + dmihardreset,dmireset,readOnlyReg(1'd0), + idle,dmistat,abits,version); + Reg#(Bit#(32)) dtmcontrol_shiftreg<-mkRegA({17'd0,3'd2,2'd0,6'd6,4'd1}); + + Reg#(Bit#(40)) dmiaccess_shiftreg[2]<-mkCReg(2,'d0); + Reg#(Bit#(2)) response_status<-mkReg(0); + Reg#(Bool) rg_dmibusy<-mkRegA(False); + + + Bit#(1) bypass_sel = instruction == `BYPASS?1:0; + Bit#(1) idcode_sel = instruction == `IDCODE?1:0; + Bit#(1) dbg_sel = instruction == `DEBUG?1:0; + Bit#(1) dtmcontrol_sel = instruction == `DTMCONTROL?1:0; + Bit#(1) dmi_sel = instruction == `DMIACCESS?1:0; + + Bit#(1) instruction_tdo=instruction_shiftreg[0]; + Bit#(1) bypass_tdo=bypass_sr; + Bit#(1) idcode_tdo=idcode_sr[0]; + Bit#(1) dtmcontrol_tdo=dtmcontrol_shiftreg[0]; + Bit#(1) dmiaccess_tdo=dmiaccess_shiftreg[0][0]; + + Reg#(Bit#(1)) rg_tdo<-mkRegA(0); + + /*== This rule implements the TAPs STATE MACHINE====== */ + `ifdef verbose + rule just_display; + $display($time,"\tTAPSTATE: ",fshow(tapstate),"\tINSTRUCTION: %h",instruction_shiftreg, " DMIACCESS: %h",dmiaccess_shiftreg[1]); + endrule + `endif + + rule reset_tap(wr_trst); + tapstate<=TestLogicReset; + instruction<=`IDCODE; + instruction_shiftreg<=0; + dtmcontrol<=0; + rg_dmibusy<=False; + dmiaccess_shiftreg[1]<=0; + dtmcontrol_shiftreg<=({17'd0,3'd2,2'd0,6'd6,4'd1}); + idcode_sr<=`IDCODEVALUE; + bypass_sr<=0; + endrule + rule tap_state_machine(posedge_clk && !wr_trst); + case(tapstate) + TestLogicReset: if(wr_tms==0) tapstate<=RunTestIdle; + RunTestIdle : if(wr_tms==1) tapstate <= SelectDRScan; + SelectDRScan : if(wr_tms==1) tapstate <= SelectIRScan; + else tapstate <= CaptureDR; + CaptureDR : if(wr_tms==0) tapstate <= ShiftDR; + else tapstate <= Exit1DR; + ShiftDR : if(wr_tms==1) tapstate <= Exit1DR; + Exit1DR : if(wr_tms==0) tapstate <= PauseDR; + else tapstate <= UpdateDR; + PauseDR : if(wr_tms==1) tapstate <= Exit2DR; + Exit2DR : if(wr_tms==1) tapstate <= UpdateDR; + else tapstate <= ShiftDR; + UpdateDR : if(wr_tms==1) tapstate <= SelectDRScan; + else tapstate <= RunTestIdle; + SelectIRScan : if(wr_tms==1) tapstate <= TestLogicReset; + else tapstate <= CaptureIR; + CaptureIR : if(wr_tms==0) tapstate <= ShiftIR; + else tapstate <= Exit1IR; + ShiftIR : if(wr_tms==1) tapstate <= Exit1IR; + Exit1IR : if(wr_tms==0) tapstate <= PauseIR; + else tapstate <= UpdateIR; + PauseIR : if(wr_tms==1) tapstate <= Exit2IR; + Exit2IR : if(wr_tms==1) tapstate <= UpdateIR; + else tapstate <= ShiftIR; + UpdateIR : if(wr_tms==1) tapstate <= SelectDRScan; + else tapstate <= RunTestIdle; + default : tapstate <= TestLogicReset; + endcase + endrule + + rule dmireset_generated(wr_dmireset_generated && !wr_trst); + dmiaccess_shiftreg[1][1:0]<='d0; + response_status<=0; + endrule + rule dmihardreset_generated(wr_dmihardreset_generated && !wr_trst); + request_to_DM.deq; + response_from_DM.deq; + rg_dmibusy<=False; + endrule + + /*======= perform dtmcontrol shifts ======== */ + rule shift_dtm(posedge_clk && !wr_trst); + case(tapstate) + TestLogicReset: dtmcontrol<={17'd0,idle,2'b0,abits,version}; + CaptureDR: if(dtmcontrol_sel==1) dtmcontrol_shiftreg<=dtmcontrol; + ShiftDR: if(dtmcontrol_sel==1) dtmcontrol_shiftreg<={wr_tdi,dtmcontrol_shiftreg[31:1]}; + UpdateDR: if(dtmcontrol_sel==1) dtmcontrol<=dtmcontrol_shiftreg; + endcase + endrule + /*========================================== */ + /*======= perform dmiaccess shifts ======== */ + rule shift_dmiaccess(posedge_clk && !wr_dmihardreset_generated && !wr_trst && !wr_dmireset_generated); + case(tapstate) + TestLogicReset: dmiaccess_shiftreg[0]<='d0; + CaptureDR: if(dmi_sel==1) + if(response_from_DM.notEmpty)begin + let x=response_from_DM.first[33:0]; + $display($time,"\tDTM: Getting response: data %h op: %h",x[33:2],x[1:0]); + x[1:0]=x[1:0]|response_status;// keeping the lower 2 bits sticky + dmiaccess_shiftreg[0][33:0]<=x; + response_status<=x[1:0]; + response_from_DM.deq; + $display($time,"\tDTM: New DMIACCESS value: %h",x); + rg_dmibusy<=False; + end + ShiftDR: if(dmi_sel==1) dmiaccess_shiftreg[0]<={wr_tdi,dmiaccess_shiftreg[0][39:1]}; + UpdateDR: if(dmi_sel==1) + if(request_to_DM.notFull && dmiaccess_shiftreg[0][1:0]!=0 && rg_dmibusy==False)begin + request_to_DM.enq(dmiaccess_shiftreg[0]); + rg_dmibusy<=True; + $display($time,"\tDTM: Sending request to Debug: %h",dmiaccess_shiftreg[0]); + end + else if(rg_dmibusy) begin + response_from_DM.enq('d3); + end + endcase + endrule + /*========================================== */ + + /*== perform instruction register shifts === */ + rule shift_reg(posedge_clk && !wr_trst); + case(tapstate) + CaptureIR: instruction_shiftreg<='b10101; + ShiftIR : instruction_shiftreg<= {wr_tdi,instruction_shiftreg[4:1]}; + endcase + endrule + rule transfer_instruction_on_nedge(negedge_clk && !wr_trst); // TODO negedge here + case(tapstate) + TestLogicReset :instruction<=`IDCODE; + UpdateIR :instruction<=instruction_shiftreg; + endcase + endrule + + /*==== Bypass Section === */ + rule bypass_logic(posedge_clk && !wr_trst); + case(tapstate) + TestLogicReset: bypass_sr<=1'b0; + CaptureDR : if(bypass_sel==1) bypass_sr<=1'b0; + ShiftDR : if(bypass_sel==1) bypass_sr<=wr_tdi; + endcase + endrule + + /*======= IDCODE section === */ + rule idcode_logic(posedge_clk && !wr_trst); + case(tapstate) + TestLogicReset:idcode_sr<=`IDCODEVALUE; + CaptureDR: if(idcode_sel==1) idcode_sr<=`IDCODEVALUE; + ShiftDR : if(idcode_sel==1) idcode_sr<={wr_tdi,idcode_sr[31:1]}; + endcase + endrule + + rule generate_tdo_outputpin(negedge_clk && !wr_trst); + if(tapstate==ShiftIR) + rg_tdo<=instruction_tdo; + else + case(instruction) + `IDCODE: rg_tdo<=idcode_tdo; + `DEBUG : rg_tdo<=wr_debug_tdi; + `EXTEST: rg_tdo<=wr_bs_chain_tdi; + `SAMPLE_PRELOAD: rg_tdo<=wr_bs_chain_tdi; + `BYPASS: rg_tdo<=bypass_tdo; + `DTMCONTROL: rg_tdo<=dtmcontrol_tdo; + `DMIACCESS: rg_tdo<=dmiaccess_tdo; + default: rg_tdo<=bypass_tdo; + endcase + endrule + + /*======== JTAG input pins ===== */ + method Action tms_i(Bit#(1) tms); + wr_tms<=tms; + endmethod + method Action tdi_i(Bit#(1) tdi); + wr_tdi<=tdi; + endmethod + method Action tck_i(Bit#(1) tck); + prv_clk<=tck; + if(prv_clk==0 && tck==1) + posedge_clk.send; + else if(prv_clk==1 && tck==0) + negedge_clk.send; + endmethod + method Action trst_i(Bit#(1) trst); + wr_trst<=unpack(trst); + endmethod + /*============================= */ + method Action debug_tdi_i(Bit#(1) debug_tdi); + wr_debug_tdi<=debug_tdi; + endmethod + method Action bs_chain_i(Bit#(1) bs_chain); + wr_bs_chain_tdi<=bs_chain; + endmethod + /*======== TAP States ============= */ + method shift_dr=tapstate==ShiftDR?1:0; + method pause_dr=tapstate==PauseDR?1:0; + method update_dr=tapstate==UpdateDR?1:0; + method capture_dr=tapstate==CaptureDR?1:0; + /*=================================== */ + /*=========== Output for BS Chain ==== */ + method extest_select =instruction==`EXTEST?1:0; + method sample_preload_select =instruction==`SAMPLE_PRELOAD?1:0; + method debug_select =instruction==`DEBUG?1:0; + /*================================ */ + /*======= JTAG Output Pins ====== */ + method tdo = rg_tdo; + method debug_tdo = wr_tdi; + method Bit#(1) tdo_oe = ((tapstate == ShiftIR) || (tapstate == ShiftDR))?1:0; + method Action response_from_dm(Bit#(34) responsedm) if(response_from_DM.notFull); + response_from_DM.enq(responsedm); + endmethod + method ActionValue#(Bit#(40)) request_to_dm if(request_to_DM.notEmpty); + request_to_DM.deq; + return request_to_DM.first; + endmethod + endmodule + +endpackage diff --git a/src/peripherals/sdram/bsvmksdram_model_wrapper.bsv b/src/peripherals/sdram/bsvmksdram_model_wrapper.bsv new file mode 100644 index 0000000..4d31f10 --- /dev/null +++ b/src/peripherals/sdram/bsvmksdram_model_wrapper.bsv @@ -0,0 +1,124 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +// Bluespec wrapper, created by Import BVI Wizard +// Created on: Mon Nov 06 17:30:03 IST 2017 +// Created by: vishvesh +// Bluespec version: 2017.03.beta1 2017-03-16 35049 + + +interface Ifc_sdram_model; + interface Inout#(Bit#(32)) dq; + (*always_ready*) + method Action iAddr (Bit#(11) addr); + (*always_ready*) + method Action iBa (Bit#(2) ba); + (*always_ready*) + method Action iCke (bit cke); + (*always_ready*) + method Action iCs_n (bit cs_n); + (*always_ready*) + method Action iRas_n (bit ras_n); + (*always_ready*) + method Action iCas_n (bit cas_n); + (*always_ready*) + method Action iWe_n (bit we_n); + (*always_ready*) + method Action iDqm (Bit#(4) dqm); +endinterface + +import "BVI" mt48lc2m32b2 = +module mksdram_model_wrapper #(String file) (Ifc_sdram_model); + + parameter FILENAME = file; + parameter addr_bits = 11; + parameter data_bits = 32; + parameter col_bits = 8; + parameter mem_sizes = 524287; + parameter tAC = 5.5; + parameter tHZ = 5.5; + parameter tOH = 2.5; + parameter tMRD = 2.0; + parameter tRAS = 42.0; + parameter tRC = 60.0; + parameter tRCD = 18.0; + parameter tRFC = 60.0; + parameter tRP = 18.0; + parameter tRRD = 12.0; + parameter tWRa = 6.0; + parameter tWRm = 12.0; + + default_clock clk_old_Clk; + default_reset rst; + + input_clock clk_old_Clk (old_Clk) <- exposeCurrentClock; + input_reset rst (/* empty */) clocked_by(clk_old_Clk) <- exposeCurrentReset; + + ifc_inout dq(Dq) clocked_by (clk_old_Clk) reset_by (rst); + + method iAddr (Addr /*addr_bits-1:0*/) + enable((*inhigh*)iAddr_enable) clocked_by(clk_old_Clk) reset_by(rst); + method iBa (Ba /*1:0*/) + enable((*inhigh*)iBa_enable) clocked_by(clk_old_Clk) reset_by(rst); + method iCke (Cke ) + enable((*inhigh*)iCke_enable) clocked_by(clk_old_Clk) reset_by(rst); + method iCs_n (Cs_n ) + enable((*inhigh*)iCs_n_enable) clocked_by(clk_old_Clk) reset_by(rst); + method iRas_n (Ras_n ) + enable((*inhigh*)iRas_n_enable) clocked_by(clk_old_Clk) reset_by(rst); + method iCas_n (Cas_n) + enable((*inhigh*)iCas_n_enable) clocked_by(clk_old_Clk) reset_by(rst); + method iWe_n (We_n ) + enable((*inhigh*)iWe_n_enable) clocked_by(clk_old_Clk) reset_by(rst); + method iDqm (Dqm /*3:0*/) + enable((*inhigh*)iDqm_enable) clocked_by(clk_old_Clk) reset_by(rst); + + schedule iAddr C iAddr; + schedule iAddr CF iBa; + schedule iAddr CF iCke; + schedule iAddr CF iCs_n; + schedule iAddr CF iRas_n; + schedule iAddr CF iCas_n; + schedule iAddr CF iWe_n; + schedule iAddr CF iDqm; + schedule iBa C iBa; + schedule iBa CF iCke; + schedule iBa CF iCs_n; + schedule iBa CF iRas_n; + schedule iBa CF iCas_n; + schedule iBa CF iWe_n; + schedule iBa CF iDqm; + schedule iCke C iCke; + schedule iCke CF iCs_n; + schedule iCke CF iRas_n; + schedule iCke CF iCas_n; + schedule iCke CF iWe_n; + schedule iCke CF iDqm; + schedule iCs_n C iCs_n; + schedule iCs_n CF iRas_n; + schedule iCs_n CF iCas_n; + schedule iCs_n CF iWe_n; + schedule iCs_n CF iDqm; + schedule iRas_n C iRas_n; + schedule iRas_n CF iCas_n; + schedule iRas_n CF iWe_n; + schedule iRas_n CF iDqm; + schedule iCas_n C iCas_n; + schedule iCas_n CF iWe_n; + schedule iCas_n CF iDqm; + schedule iWe_n C iWe_n; + schedule iWe_n CF iDqm; + schedule iDqm C iDqm; +endmodule + + diff --git a/src/peripherals/sdram/bsvmksdrc_top.bsv b/src/peripherals/sdram/bsvmksdrc_top.bsv new file mode 100644 index 0000000..5ff6a79 --- /dev/null +++ b/src/peripherals/sdram/bsvmksdrc_top.bsv @@ -0,0 +1,928 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +// Bluespec wrapper, created by Import BVI Wizard +// Created on: Mon Jul 03 20:03:44 IST 2017 +// Created by: vishvesh +// Bluespec version: 2017.03.beta1 2017-03-16 35049 +`define SDR_RFSH_TIMER_W 12 +`define SDR_RFSH_ROW_CNT_W 3 + +interface Ifc_sdram; + (*always_ready, always_enabled*) + method Action iapp_req (bit app_req); + (*always_ready, always_enabled*) + method Action iapp_req_wrap (bit app_req_wrap); + (*always_ready, always_enabled*) + method Action icfg_sdr_width (Bit#(2) cfg_sdr_width); + (*always_ready, always_enabled*) + method Action icfg_colbits (Bit#(2) cfg_colbits); + (*always_ready, always_enabled*) + method Action icfg_sdr_tras_d (Bit#(4) cfg_sdr_tras_d); + (*always_ready, always_enabled*) + method Action icfg_sdr_trp_d (Bit#(4) cfg_sdr_trp_d); + (*always_ready, always_enabled*) + method Action icfg_sdr_trcd_d (Bit#(4) cfg_sdr_trcd_d); + (*always_ready, always_enabled*) + method Action icfg_sdr_en (bit cfg_sdr_en); + (*always_ready, always_enabled*) + method Action icfg_req_depth (Bit#(2) cfg_req_depth); + (*always_ready, always_enabled*) + method Action icfg_sdr_mode_reg (Bit#(13) cfg_sdr_mode_reg); + (*always_ready, always_enabled*) + method Action icfg_sdr_cas (Bit#(3) cfg_sdr_cas); + (*always_ready, always_enabled*) + method Action icfg_sdr_trcar_d (Bit#(4) cfg_sdr_trcar_d); + (*always_ready, always_enabled*) + method Action icfg_sdr_twr_d (Bit#(4) cfg_sdr_twr_d); + (*always_ready, always_enabled*) + method Action icfg_sdr_rfsh (Bit#(`SDR_RFSH_TIMER_W) cfg_sdr_rfsh); + (*always_ready, always_enabled*) + method Action icfg_sdr_rfmax (Bit#(`SDR_RFSH_ROW_CNT_W) cfg_sdr_rfmax); + (*always_ready, always_enabled*) + method Action iapp_req_addr (Bit#(26) app_req_addr); + (*always_ready, always_enabled*) + method Action iapp_req_len (Bit#(9) app_req_len); + (*always_ready, always_enabled*) + method Action iapp_req_wr_n (bit app_req_wr_n); + (*always_ready, always_enabled*) + method Action iapp_wr_en_n (Bit#(8) app_wr_en_n); + (*always_ready, always_enabled*) + method Action iapp_wr_data (Bit#(64) app_wr_data); + (*always_ready, always_enabled*) + method Action ipad_sdr_din (Bit#(64) pad_sdr_din); + (*always_enabled*) + method Bool osdr_cke (); + (*always_enabled*) + method Bool osdr_cs_n (); + (*always_enabled*) + method Bool osdr_ras_n (); + (*always_enabled*) + method Bool osdr_cas_n (); + (*always_enabled*) + method Bool osdr_we_n (); + (*always_enabled*) + method Bit#(8) osdr_dqm (); + (*always_enabled*) + method Bit#(2) osdr_ba (); + (*always_enabled*) + method Bit#(13) osdr_addr (); + (*always_enabled*) + method Bit#(64) osdr_dout (); + (*always_enabled*) + method Bit#(8) osdr_den_n (); + (*always_enabled*) + method Bool osdr_init_done (); + (*always_enabled*) + method Bool oapp_req_ack (); + (*always_enabled*) + method Bool oapp_wr_next_req (); + (*always_enabled*) + method Bool oapp_rd_valid (); + (*always_enabled*) + method Bool oapp_last_rd (); + (*always_enabled*) + method Bool oapp_last_wr (); + (*always_enabled*) + method Bit#(64) oapp_rd_data (); +endinterface + +import "BVI" sdrc_top = +module mksdrc_top (Ifc_sdram); + + parameter APP_AW = 26; + parameter APP_DW = 64; + parameter APP_BW = 8; + parameter APP_RW = 9; + parameter SDR_DW = 64; + parameter SDR_BW = 8; + parameter dw = 64; + parameter tw = 8; + parameter bl = 9; + + default_clock clk_sdram_clk; + default_reset rst_sdram_resetn; + + input_clock clk_sdram_clk (sdram_clk) <- exposeCurrentClock; + input_reset rst_sdram_resetn (sdram_resetn) clocked_by(clk_sdram_clk) <- exposeCurrentReset; + + + method ipad_sdr_din (pad_sdr_din) + enable((*inhigh*)ipad_sdr_din_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method iapp_req (app_req ) + enable((*inhigh*)iapp_req_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method iapp_req_wrap (app_req_wrap ) + enable((*inhigh*)iapp_req_wrap_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method icfg_sdr_width (cfg_sdr_width /*3:0*/) + enable((*inhigh*)icfg_sdr_width_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method icfg_colbits (cfg_colbits /*3:0*/) + enable((*inhigh*)icfg_colbits_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method icfg_sdr_tras_d (cfg_sdr_tras_d /*3:0*/) + enable((*inhigh*)icfg_sdr_tras_d_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method icfg_sdr_trp_d (cfg_sdr_trp_d /*3:0*/) + enable((*inhigh*)icfg_sdr_trp_d_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method icfg_sdr_trcd_d (cfg_sdr_trcd_d /*3:0*/) + enable((*inhigh*)icfg_sdr_trcd_d_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method icfg_sdr_en (cfg_sdr_en ) + enable((*inhigh*)icfg_sdr_en_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method icfg_req_depth (cfg_req_depth /*1:0*/) + enable((*inhigh*)icfg_req_depth_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method icfg_sdr_mode_reg (cfg_sdr_mode_reg /*12:0*/) + enable((*inhigh*)icfg_sdr_mode_reg_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method icfg_sdr_cas (cfg_sdr_cas /*2:0*/) + enable((*inhigh*)icfg_sdr_cas_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method icfg_sdr_trcar_d (cfg_sdr_trcar_d /*3:0*/) + enable((*inhigh*)icfg_sdr_trcar_d_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method icfg_sdr_twr_d (cfg_sdr_twr_d /*3:0*/) + enable((*inhigh*)icfg_sdr_twr_d_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method icfg_sdr_rfsh (cfg_sdr_rfsh /*`SDR_RFSH_TIMER_W-1:0*/) + enable((*inhigh*)icfg_sdr_rfsh_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method icfg_sdr_rfmax (cfg_sdr_rfmax /*`SDR_RFSH_ROW_CNT_W-1:0*/) + enable((*inhigh*)icfg_sdr_rfmax_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method iapp_req_addr (app_req_addr /*APP_AW-1:0*/) + enable((*inhigh*)iapp_req_addr_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method iapp_req_len (app_req_len /*bl-1:0*/) + enable((*inhigh*)iapp_req_len_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method iapp_req_wr_n (app_req_wr_n ) + enable((*inhigh*)iapp_req_wr_n_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method iapp_wr_en_n (app_wr_en_n /*dw/8-1:0*/) + enable((*inhigh*)iapp_wr_en_n_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method iapp_wr_data (app_wr_data /*dw-1:0*/) + enable((*inhigh*)iapp_wr_data_enable) clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + + method sdr_dout osdr_dout () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method sdr_den_n osdr_den_n () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method sdr_cke osdr_cke () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method sdr_cs_n osdr_cs_n () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method sdr_ras_n osdr_ras_n () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method sdr_cas_n osdr_cas_n () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method sdr_we_n osdr_we_n () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method sdr_dqm /* SDR_BW-1 : 0 */ osdr_dqm () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method sdr_ba /* 1 : 0 */ osdr_ba () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method sdr_addr /* 12 : 0 */ osdr_addr () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method sdr_init_done osdr_init_done () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method app_req_ack oapp_req_ack () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method app_wr_next_req oapp_wr_next_req () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method app_rd_valid oapp_rd_valid () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method app_last_rd oapp_last_rd () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method app_last_wr oapp_last_wr () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + method app_rd_data /* dw-1 : 0 */ oapp_rd_data () + clocked_by(clk_sdram_clk) reset_by(rst_sdram_resetn); + + + schedule icfg_colbits C icfg_colbits; + schedule icfg_colbits CF icfg_sdr_width; + schedule icfg_colbits CF ipad_sdr_din; + schedule icfg_colbits CF iapp_req; + schedule icfg_colbits CF iapp_req_addr; + schedule icfg_colbits CF iapp_req_len; + schedule icfg_colbits CF iapp_req_wr_n; + schedule icfg_colbits CF iapp_wr_en_n; + schedule icfg_colbits CF iapp_wr_data; + schedule icfg_colbits CF icfg_sdr_tras_d; + schedule icfg_colbits CF icfg_sdr_trp_d; + schedule icfg_colbits CF icfg_sdr_trcd_d; + schedule icfg_colbits CF icfg_sdr_en; + schedule icfg_colbits CF icfg_req_depth; + schedule icfg_colbits CF icfg_sdr_mode_reg; + schedule icfg_colbits CF icfg_sdr_cas; + schedule icfg_colbits CF icfg_sdr_trcar_d; + schedule icfg_colbits CF icfg_sdr_twr_d; + schedule icfg_colbits CF icfg_sdr_rfmax; + schedule icfg_colbits CF icfg_sdr_rfsh; + schedule icfg_colbits CF iapp_req_wrap; + schedule osdr_cke CF icfg_colbits; + schedule osdr_cs_n CF icfg_colbits; + schedule osdr_ras_n CF icfg_colbits; + schedule osdr_cas_n CF icfg_colbits; + schedule osdr_we_n CF icfg_colbits; + schedule osdr_dqm CF icfg_colbits; + schedule osdr_ba CF icfg_colbits; + schedule osdr_addr CF icfg_colbits; + schedule osdr_init_done CF icfg_colbits; + schedule oapp_req_ack CF icfg_colbits; + schedule oapp_wr_next_req CF icfg_colbits; + schedule oapp_rd_valid CF icfg_colbits; + schedule oapp_last_rd CF icfg_colbits; + schedule oapp_last_wr CF icfg_colbits; + schedule oapp_rd_data CF icfg_colbits; + + + + schedule icfg_sdr_width C icfg_sdr_width; + schedule icfg_sdr_width CF ipad_sdr_din; + schedule icfg_sdr_width CF iapp_req; + schedule icfg_sdr_width CF iapp_req_addr; + schedule icfg_sdr_width CF iapp_req_len; + schedule icfg_sdr_width CF iapp_req_wr_n; + schedule icfg_sdr_width CF iapp_wr_en_n; + schedule icfg_sdr_width CF iapp_wr_data; + schedule icfg_sdr_width CF icfg_sdr_tras_d; + schedule icfg_sdr_width CF icfg_sdr_trp_d; + schedule icfg_sdr_width CF icfg_sdr_trcd_d; + schedule icfg_sdr_width CF icfg_sdr_en; + schedule icfg_sdr_width CF icfg_req_depth; + schedule icfg_sdr_width CF icfg_sdr_mode_reg; + schedule icfg_sdr_width CF icfg_sdr_cas; + schedule icfg_sdr_width CF icfg_sdr_trcar_d; + schedule icfg_sdr_width CF icfg_sdr_twr_d; + schedule icfg_sdr_width CF icfg_sdr_rfmax; + schedule icfg_sdr_width CF icfg_sdr_rfsh; + schedule icfg_sdr_width CF iapp_req_wrap; + schedule osdr_cke CF icfg_sdr_width; + schedule osdr_cs_n CF icfg_sdr_width; + schedule osdr_ras_n CF icfg_sdr_width; + schedule osdr_cas_n CF icfg_sdr_width; + schedule osdr_we_n CF icfg_sdr_width; + schedule osdr_dqm CF icfg_sdr_width; + schedule osdr_ba CF icfg_sdr_width; + schedule osdr_addr CF icfg_sdr_width; + schedule osdr_init_done CF icfg_sdr_width; + schedule oapp_req_ack CF icfg_sdr_width; + schedule oapp_wr_next_req CF icfg_sdr_width; + schedule oapp_rd_valid CF icfg_sdr_width; + schedule oapp_last_rd CF icfg_sdr_width; + schedule oapp_last_wr CF icfg_sdr_width; + schedule oapp_rd_data CF icfg_sdr_width; + + schedule ipad_sdr_din C ipad_sdr_din; + schedule ipad_sdr_din CF iapp_req; + schedule ipad_sdr_din CF iapp_req_addr; + schedule ipad_sdr_din CF iapp_req_len; + schedule ipad_sdr_din CF iapp_req_wr_n; + schedule ipad_sdr_din CF iapp_wr_en_n; + schedule ipad_sdr_din CF iapp_wr_data; + schedule ipad_sdr_din CF icfg_sdr_tras_d; + schedule ipad_sdr_din CF icfg_sdr_trp_d; + schedule ipad_sdr_din CF icfg_sdr_trcd_d; + schedule ipad_sdr_din CF icfg_sdr_en; + schedule ipad_sdr_din CF icfg_req_depth; + schedule ipad_sdr_din CF icfg_sdr_mode_reg; + schedule ipad_sdr_din CF icfg_sdr_cas; + schedule ipad_sdr_din CF icfg_sdr_trcar_d; + schedule ipad_sdr_din CF icfg_sdr_twr_d; + schedule ipad_sdr_din CF icfg_sdr_rfmax; + schedule ipad_sdr_din CF icfg_sdr_rfsh; + schedule ipad_sdr_din CF iapp_req_wrap; + schedule osdr_cke CF ipad_sdr_din; + schedule osdr_cs_n CF ipad_sdr_din; + schedule osdr_ras_n CF ipad_sdr_din; + schedule osdr_cas_n CF ipad_sdr_din; + schedule osdr_we_n CF ipad_sdr_din; + schedule osdr_dqm CF ipad_sdr_din; + schedule osdr_ba CF ipad_sdr_din; + schedule osdr_addr CF ipad_sdr_din; + schedule osdr_init_done CF ipad_sdr_din; + schedule oapp_req_ack CF ipad_sdr_din; + schedule oapp_wr_next_req CF ipad_sdr_din; + schedule oapp_rd_valid CF ipad_sdr_din; + schedule oapp_last_rd CF ipad_sdr_din; + schedule oapp_last_wr CF ipad_sdr_din; + schedule oapp_rd_data CF ipad_sdr_din; + + schedule iapp_req_wrap C iapp_req_wrap; + schedule iapp_req_wrap CF iapp_req; + schedule iapp_req_wrap CF iapp_req_addr; + schedule iapp_req_wrap CF iapp_req_len; + schedule iapp_req_wrap CF iapp_req_wr_n; + schedule iapp_req_wrap CF iapp_wr_en_n; + schedule iapp_req_wrap CF iapp_wr_data; + schedule iapp_req_wrap CF icfg_sdr_tras_d; + schedule iapp_req_wrap CF icfg_sdr_trp_d; + schedule iapp_req_wrap CF icfg_sdr_trcd_d; + schedule iapp_req_wrap CF icfg_sdr_en; + schedule iapp_req_wrap CF icfg_req_depth; + schedule iapp_req_wrap CF icfg_sdr_mode_reg; + schedule iapp_req_wrap CF icfg_sdr_cas; + schedule iapp_req_wrap CF icfg_sdr_trcar_d; + schedule iapp_req_wrap CF icfg_sdr_twr_d; + schedule iapp_req_wrap CF icfg_sdr_rfmax; + schedule iapp_req_wrap CF icfg_sdr_rfsh; + schedule osdr_cke CF iapp_req_wrap; + schedule osdr_cs_n CF iapp_req_wrap; + schedule osdr_ras_n CF iapp_req_wrap; + schedule osdr_cas_n CF iapp_req_wrap; + schedule osdr_we_n CF iapp_req_wrap; + schedule osdr_dqm CF iapp_req_wrap; + schedule osdr_ba CF iapp_req_wrap; + schedule osdr_addr CF iapp_req_wrap; + schedule osdr_init_done CF iapp_req_wrap; + schedule oapp_req_ack CF iapp_req_wrap; + schedule oapp_wr_next_req CF iapp_req_wrap; + schedule oapp_rd_valid CF iapp_req_wrap; + schedule oapp_last_rd CF iapp_req_wrap; + schedule oapp_last_wr CF iapp_req_wrap; + schedule oapp_rd_data CF iapp_req_wrap; + schedule osdr_dout CF iapp_req_wrap; + schedule osdr_den_n CF iapp_req_wrap; + + schedule iapp_req C iapp_req; + schedule iapp_req CF iapp_req_addr; + schedule iapp_req CF iapp_req_len; + schedule iapp_req CF iapp_req_wr_n; + schedule iapp_req CF iapp_wr_en_n; + schedule iapp_req CF iapp_wr_data; + schedule iapp_req CF icfg_sdr_tras_d; + schedule iapp_req CF icfg_sdr_trp_d; + schedule iapp_req CF icfg_sdr_trcd_d; + schedule iapp_req CF icfg_sdr_en; + schedule iapp_req CF icfg_req_depth; + schedule iapp_req CF icfg_sdr_mode_reg; + schedule iapp_req CF icfg_sdr_cas; + schedule iapp_req CF icfg_sdr_trcar_d; + schedule iapp_req CF icfg_sdr_twr_d; + schedule iapp_req CF icfg_sdr_rfmax; + schedule iapp_req CF icfg_sdr_rfsh; + schedule osdr_cke CF iapp_req; + schedule osdr_cs_n CF iapp_req; + schedule osdr_ras_n CF iapp_req; + schedule osdr_cas_n CF iapp_req; + schedule osdr_we_n CF iapp_req; + schedule osdr_dqm CF iapp_req; + schedule osdr_ba CF iapp_req; + schedule osdr_addr CF iapp_req; + schedule osdr_init_done CF iapp_req; + schedule oapp_req_ack CF iapp_req; + schedule oapp_wr_next_req CF iapp_req; + schedule oapp_rd_valid CF iapp_req; + schedule oapp_last_rd CF iapp_req; + schedule oapp_last_wr CF iapp_req; + schedule oapp_rd_data CF iapp_req; + schedule osdr_dout CF iapp_req; + schedule osdr_den_n CF iapp_req; + + schedule icfg_sdr_tras_d C icfg_sdr_tras_d; + schedule icfg_sdr_tras_d CF icfg_sdr_trp_d; + schedule icfg_sdr_tras_d CF icfg_sdr_trcd_d; + schedule icfg_sdr_tras_d CF icfg_sdr_en; + schedule icfg_sdr_tras_d CF icfg_req_depth; + schedule icfg_sdr_tras_d CF icfg_sdr_mode_reg; + schedule icfg_sdr_tras_d CF icfg_sdr_cas; + schedule icfg_sdr_tras_d CF icfg_sdr_trcar_d; + schedule icfg_sdr_tras_d CF icfg_sdr_twr_d; + schedule icfg_sdr_tras_d CF icfg_sdr_rfsh; + schedule icfg_sdr_tras_d CF icfg_sdr_rfmax; + schedule icfg_sdr_tras_d CF iapp_req_addr; + schedule icfg_sdr_tras_d CF iapp_req_len; + schedule icfg_sdr_tras_d CF iapp_req_wr_n; + schedule icfg_sdr_tras_d CF iapp_wr_en_n; + schedule icfg_sdr_tras_d CF iapp_wr_data; + schedule osdr_cke CF icfg_sdr_tras_d; + schedule osdr_cs_n CF icfg_sdr_tras_d; + schedule osdr_ras_n CF icfg_sdr_tras_d; + schedule osdr_cas_n CF icfg_sdr_tras_d; + schedule osdr_we_n CF icfg_sdr_tras_d; + schedule osdr_dqm CF icfg_sdr_tras_d; + schedule osdr_ba CF icfg_sdr_tras_d; + schedule osdr_addr CF icfg_sdr_tras_d; + schedule osdr_init_done CF icfg_sdr_tras_d; + schedule oapp_req_ack CF icfg_sdr_tras_d; + schedule oapp_wr_next_req CF icfg_sdr_tras_d; + schedule oapp_rd_valid CF icfg_sdr_tras_d; + schedule oapp_last_rd CF icfg_sdr_tras_d; + schedule oapp_last_wr CF icfg_sdr_tras_d; + schedule oapp_rd_data CF icfg_sdr_tras_d; + schedule osdr_dout CF icfg_sdr_tras_d; + schedule osdr_den_n CF icfg_sdr_tras_d; + + + schedule icfg_sdr_trp_d C icfg_sdr_trp_d; + schedule icfg_sdr_trp_d CF icfg_sdr_trcd_d; + schedule icfg_sdr_trp_d CF icfg_sdr_en; + schedule icfg_sdr_trp_d CF icfg_req_depth; + schedule icfg_sdr_trp_d CF icfg_sdr_mode_reg; + schedule icfg_sdr_trp_d CF icfg_sdr_cas; + schedule icfg_sdr_trp_d CF icfg_sdr_trcar_d; + schedule icfg_sdr_trp_d CF icfg_sdr_twr_d; + schedule icfg_sdr_trp_d CF icfg_sdr_rfsh; + schedule icfg_sdr_trp_d CF icfg_sdr_rfmax; + schedule icfg_sdr_trp_d CF iapp_req_addr; + schedule icfg_sdr_trp_d CF iapp_req_len; + schedule icfg_sdr_trp_d CF iapp_req_wr_n; + schedule icfg_sdr_trp_d CF iapp_wr_en_n; + schedule icfg_sdr_trp_d CF iapp_wr_data; + schedule osdr_cke CF icfg_sdr_trp_d; + schedule osdr_cs_n CF icfg_sdr_trp_d; + schedule osdr_ras_n CF icfg_sdr_trp_d; + schedule osdr_cas_n CF icfg_sdr_trp_d; + schedule osdr_we_n CF icfg_sdr_trp_d; + schedule osdr_dqm CF icfg_sdr_trp_d; + schedule osdr_ba CF icfg_sdr_trp_d; + schedule osdr_addr CF icfg_sdr_trp_d; + schedule osdr_init_done CF icfg_sdr_trp_d; + schedule oapp_req_ack CF icfg_sdr_trp_d; + schedule oapp_wr_next_req CF icfg_sdr_trp_d; + schedule oapp_rd_valid CF icfg_sdr_trp_d; + schedule oapp_last_rd CF icfg_sdr_trp_d; + schedule oapp_last_wr CF icfg_sdr_trp_d; + schedule oapp_rd_data CF icfg_sdr_trp_d; + schedule osdr_dout CF icfg_sdr_trp_d; + schedule osdr_den_n CF icfg_sdr_trp_d; + + + + schedule icfg_sdr_trcd_d C icfg_sdr_trcd_d; + schedule icfg_sdr_trcd_d CF icfg_sdr_en; + schedule icfg_sdr_trcd_d CF icfg_req_depth; + schedule icfg_sdr_trcd_d CF icfg_sdr_mode_reg; + schedule icfg_sdr_trcd_d CF icfg_sdr_cas; + schedule icfg_sdr_trcd_d CF icfg_sdr_trcar_d; + schedule icfg_sdr_trcd_d CF icfg_sdr_twr_d; + schedule icfg_sdr_trcd_d CF icfg_sdr_rfsh; + schedule icfg_sdr_trcd_d CF icfg_sdr_rfmax; + schedule icfg_sdr_trcd_d CF iapp_req_addr; + schedule icfg_sdr_trcd_d CF iapp_req_len; + schedule icfg_sdr_trcd_d CF iapp_req_wr_n; + schedule icfg_sdr_trcd_d CF iapp_wr_en_n; + schedule icfg_sdr_trcd_d CF iapp_wr_data; + schedule osdr_cke CF icfg_sdr_trcd_d; + schedule osdr_cs_n CF icfg_sdr_trcd_d; + schedule osdr_ras_n CF icfg_sdr_trcd_d; + schedule osdr_cas_n CF icfg_sdr_trcd_d; + schedule osdr_we_n CF icfg_sdr_trcd_d; + schedule osdr_dqm CF icfg_sdr_trcd_d; + schedule osdr_ba CF icfg_sdr_trcd_d; + schedule osdr_addr CF icfg_sdr_trcd_d; + schedule osdr_init_done CF icfg_sdr_trcd_d; + schedule oapp_req_ack CF icfg_sdr_trcd_d; + schedule oapp_wr_next_req CF icfg_sdr_trcd_d; + schedule oapp_rd_valid CF icfg_sdr_trcd_d; + schedule oapp_last_rd CF icfg_sdr_trcd_d; + schedule oapp_last_wr CF icfg_sdr_trcd_d; + schedule oapp_rd_data CF icfg_sdr_trcd_d; + schedule osdr_dout CF icfg_sdr_trcd_d; + schedule osdr_den_n CF icfg_sdr_trcd_d; + + schedule icfg_sdr_en C icfg_sdr_en; + schedule icfg_sdr_en CF icfg_req_depth; + schedule icfg_sdr_en CF icfg_sdr_mode_reg; + schedule icfg_sdr_en CF icfg_sdr_cas; + schedule icfg_sdr_en CF icfg_sdr_trcar_d; + schedule icfg_sdr_en CF icfg_sdr_twr_d; + schedule icfg_sdr_en CF icfg_sdr_rfsh; + schedule icfg_sdr_en CF icfg_sdr_rfmax; + schedule icfg_sdr_en CF iapp_req_addr; + schedule icfg_sdr_en CF iapp_req_len; + schedule icfg_sdr_en CF iapp_req_wr_n; + schedule icfg_sdr_en CF iapp_wr_en_n; + schedule icfg_sdr_en CF iapp_wr_data; + schedule osdr_cke CF icfg_sdr_en; + schedule osdr_cs_n CF icfg_sdr_en; + schedule osdr_ras_n CF icfg_sdr_en; + schedule osdr_cas_n CF icfg_sdr_en; + schedule osdr_we_n CF icfg_sdr_en; + schedule osdr_dqm CF icfg_sdr_en; + schedule osdr_ba CF icfg_sdr_en; + schedule osdr_addr CF icfg_sdr_en; + schedule osdr_init_done CF icfg_sdr_en; + schedule oapp_req_ack CF icfg_sdr_en; + schedule oapp_wr_next_req CF icfg_sdr_en; + schedule oapp_rd_valid CF icfg_sdr_en; + schedule oapp_last_rd CF icfg_sdr_en; + schedule oapp_last_wr CF icfg_sdr_en; + schedule oapp_rd_data CF icfg_sdr_en; + schedule osdr_dout CF icfg_sdr_en; + schedule osdr_den_n CF icfg_sdr_en; + + schedule icfg_req_depth C icfg_req_depth; + schedule icfg_req_depth CF icfg_sdr_mode_reg; + schedule icfg_req_depth CF icfg_sdr_cas; + schedule icfg_req_depth CF icfg_sdr_trcar_d; + schedule icfg_req_depth CF icfg_sdr_twr_d; + schedule icfg_req_depth CF icfg_sdr_rfsh; + schedule icfg_req_depth CF icfg_sdr_rfmax; + schedule icfg_req_depth CF iapp_req_addr; + schedule icfg_req_depth CF iapp_req_len; + schedule icfg_req_depth CF iapp_req_wr_n; + schedule icfg_req_depth CF iapp_wr_en_n; + schedule icfg_req_depth CF iapp_wr_data; + schedule osdr_cke CF icfg_req_depth; + schedule osdr_cs_n CF icfg_req_depth; + schedule osdr_ras_n CF icfg_req_depth; + schedule osdr_cas_n CF icfg_req_depth; + schedule osdr_we_n CF icfg_req_depth; + schedule osdr_dqm CF icfg_req_depth; + schedule osdr_ba CF icfg_req_depth; + schedule osdr_addr CF icfg_req_depth; + schedule osdr_init_done CF icfg_req_depth; + schedule oapp_req_ack CF icfg_req_depth; + schedule oapp_wr_next_req CF icfg_req_depth; + schedule oapp_rd_valid CF icfg_req_depth; + schedule oapp_last_rd CF icfg_req_depth; + schedule oapp_last_wr CF icfg_req_depth; + schedule oapp_rd_data CF icfg_req_depth; + schedule osdr_dout CF icfg_req_depth; + schedule osdr_den_n CF icfg_req_depth; + + schedule icfg_sdr_mode_reg C icfg_sdr_mode_reg; + schedule icfg_sdr_mode_reg CF icfg_sdr_cas; + schedule icfg_sdr_mode_reg CF icfg_sdr_trcar_d; + schedule icfg_sdr_mode_reg CF icfg_sdr_twr_d; + schedule icfg_sdr_mode_reg CF icfg_sdr_rfsh; + schedule icfg_sdr_mode_reg CF icfg_sdr_rfmax; + schedule icfg_sdr_mode_reg CF iapp_req_addr; + schedule icfg_sdr_mode_reg CF iapp_req_len; + schedule icfg_sdr_mode_reg CF iapp_req_wr_n; + schedule icfg_sdr_mode_reg CF iapp_wr_en_n; + schedule icfg_sdr_mode_reg CF iapp_wr_data; + schedule osdr_cke CF icfg_sdr_mode_reg; + schedule osdr_cs_n CF icfg_sdr_mode_reg; + schedule osdr_ras_n CF icfg_sdr_mode_reg; + schedule osdr_cas_n CF icfg_sdr_mode_reg; + schedule osdr_we_n CF icfg_sdr_mode_reg; + schedule osdr_dqm CF icfg_sdr_mode_reg; + schedule osdr_ba CF icfg_sdr_mode_reg; + schedule osdr_addr CF icfg_sdr_mode_reg; + schedule osdr_init_done CF icfg_sdr_mode_reg; + schedule oapp_req_ack CF icfg_sdr_mode_reg; + schedule oapp_wr_next_req CF icfg_sdr_mode_reg; + schedule oapp_rd_valid CF icfg_sdr_mode_reg; + schedule oapp_last_rd CF icfg_sdr_mode_reg; + schedule oapp_last_wr CF icfg_sdr_mode_reg; + schedule oapp_rd_data CF icfg_sdr_mode_reg; + schedule osdr_dout CF icfg_sdr_mode_reg; + schedule osdr_den_n CF icfg_sdr_mode_reg; + + schedule icfg_sdr_cas C icfg_sdr_cas; + schedule icfg_sdr_cas CF icfg_sdr_trcar_d; + schedule icfg_sdr_cas CF icfg_sdr_twr_d; + schedule icfg_sdr_cas CF icfg_sdr_rfsh; + schedule icfg_sdr_cas CF icfg_sdr_rfmax; + schedule icfg_sdr_cas CF iapp_req_addr; + schedule icfg_sdr_cas CF iapp_req_len; + schedule icfg_sdr_cas CF iapp_req_wr_n; + schedule icfg_sdr_cas CF iapp_wr_en_n; + schedule icfg_sdr_cas CF iapp_wr_data; + schedule osdr_cke CF icfg_sdr_cas; + schedule osdr_cs_n CF icfg_sdr_cas; + schedule osdr_ras_n CF icfg_sdr_cas; + schedule osdr_cas_n CF icfg_sdr_cas; + schedule osdr_we_n CF icfg_sdr_cas; + schedule osdr_dqm CF icfg_sdr_cas; + schedule osdr_ba CF icfg_sdr_cas; + schedule osdr_addr CF icfg_sdr_cas; + schedule osdr_init_done CF icfg_sdr_cas; + schedule oapp_req_ack CF icfg_sdr_cas; + schedule oapp_wr_next_req CF icfg_sdr_cas; + schedule oapp_rd_valid CF icfg_sdr_cas; + schedule oapp_last_rd CF icfg_sdr_cas; + schedule oapp_last_wr CF icfg_sdr_cas; + schedule oapp_rd_data CF icfg_sdr_cas; + schedule osdr_dout CF icfg_sdr_cas; + schedule osdr_den_n CF icfg_sdr_cas; + + schedule icfg_sdr_trcar_d C icfg_sdr_trcar_d; + schedule icfg_sdr_trcar_d CF icfg_sdr_twr_d; + schedule icfg_sdr_trcar_d CF icfg_sdr_rfsh; + schedule icfg_sdr_trcar_d CF icfg_sdr_rfmax; + schedule icfg_sdr_trcar_d CF iapp_req_addr; + schedule icfg_sdr_trcar_d CF iapp_req_len; + schedule icfg_sdr_trcar_d CF iapp_req_wr_n; + schedule icfg_sdr_trcar_d CF iapp_wr_en_n; + schedule icfg_sdr_trcar_d CF iapp_wr_data; + schedule osdr_cke CF icfg_sdr_trcar_d; + schedule osdr_cs_n CF icfg_sdr_trcar_d; + schedule osdr_ras_n CF icfg_sdr_trcar_d; + schedule osdr_cas_n CF icfg_sdr_trcar_d; + schedule osdr_we_n CF icfg_sdr_trcar_d; + schedule osdr_dqm CF icfg_sdr_trcar_d; + schedule osdr_ba CF icfg_sdr_trcar_d; + schedule osdr_addr CF icfg_sdr_trcar_d; + schedule osdr_init_done CF icfg_sdr_trcar_d; + schedule oapp_req_ack CF icfg_sdr_trcar_d; + schedule oapp_wr_next_req CF icfg_sdr_trcar_d; + schedule oapp_rd_valid CF icfg_sdr_trcar_d; + schedule oapp_last_rd CF icfg_sdr_trcar_d; + schedule oapp_last_wr CF icfg_sdr_trcar_d; + schedule oapp_rd_data CF icfg_sdr_trcar_d; + schedule osdr_dout CF icfg_sdr_trcar_d; + schedule osdr_den_n CF icfg_sdr_trcar_d; + + schedule icfg_sdr_twr_d C icfg_sdr_twr_d; + schedule icfg_sdr_twr_d CF icfg_sdr_rfsh; + schedule icfg_sdr_twr_d CF icfg_sdr_rfmax; + schedule icfg_sdr_twr_d CF iapp_req_addr; + schedule icfg_sdr_twr_d CF iapp_req_len; + schedule icfg_sdr_twr_d CF iapp_req_wr_n; + schedule icfg_sdr_twr_d CF iapp_wr_en_n; + schedule icfg_sdr_twr_d CF iapp_wr_data; + schedule osdr_cke CF icfg_sdr_twr_d; + schedule osdr_cs_n CF icfg_sdr_twr_d; + schedule osdr_ras_n CF icfg_sdr_twr_d; + schedule osdr_cas_n CF icfg_sdr_twr_d; + schedule osdr_we_n CF icfg_sdr_twr_d; + schedule osdr_dqm CF icfg_sdr_twr_d; + schedule osdr_ba CF icfg_sdr_twr_d; + schedule osdr_addr CF icfg_sdr_twr_d; + schedule osdr_init_done CF icfg_sdr_twr_d; + schedule oapp_req_ack CF icfg_sdr_twr_d; + schedule oapp_wr_next_req CF icfg_sdr_twr_d; + schedule oapp_rd_valid CF icfg_sdr_twr_d; + schedule oapp_last_rd CF icfg_sdr_twr_d; + schedule oapp_last_wr CF icfg_sdr_twr_d; + schedule oapp_rd_data CF icfg_sdr_twr_d; + schedule osdr_dout CF icfg_sdr_twr_d; + schedule osdr_den_n CF icfg_sdr_twr_d; + + schedule icfg_sdr_rfsh C icfg_sdr_rfsh; + schedule icfg_sdr_rfsh CF icfg_sdr_rfmax; + schedule icfg_sdr_rfsh CF iapp_req_addr; + schedule icfg_sdr_rfsh CF iapp_req_len; + schedule icfg_sdr_rfsh CF iapp_req_wr_n; + schedule icfg_sdr_rfsh CF iapp_wr_en_n; + schedule icfg_sdr_rfsh CF iapp_wr_data; + schedule osdr_cke CF icfg_sdr_rfsh; + schedule osdr_cs_n CF icfg_sdr_rfsh; + schedule osdr_ras_n CF icfg_sdr_rfsh; + schedule osdr_cas_n CF icfg_sdr_rfsh; + schedule osdr_we_n CF icfg_sdr_rfsh; + schedule osdr_dqm CF icfg_sdr_rfsh; + schedule osdr_ba CF icfg_sdr_rfsh; + schedule osdr_addr CF icfg_sdr_rfsh; + schedule osdr_init_done CF icfg_sdr_rfsh; + schedule oapp_req_ack CF icfg_sdr_rfsh; + schedule oapp_wr_next_req CF icfg_sdr_rfsh; + schedule oapp_rd_valid CF icfg_sdr_rfsh; + schedule oapp_last_rd CF icfg_sdr_rfsh; + schedule oapp_last_wr CF icfg_sdr_rfsh; + schedule oapp_rd_data CF icfg_sdr_rfsh; + schedule osdr_dout CF icfg_sdr_rfsh; + schedule osdr_den_n CF icfg_sdr_rfsh; + + schedule icfg_sdr_rfmax C icfg_sdr_rfmax; + schedule icfg_sdr_rfmax CF iapp_req_addr; + schedule icfg_sdr_rfmax CF iapp_req_len; + schedule icfg_sdr_rfmax CF iapp_req_wr_n; + schedule icfg_sdr_rfmax CF iapp_wr_en_n; + schedule icfg_sdr_rfmax CF iapp_wr_data; + schedule osdr_cke CF icfg_sdr_rfmax; + schedule osdr_cs_n CF icfg_sdr_rfmax; + schedule osdr_ras_n CF icfg_sdr_rfmax; + schedule osdr_cas_n CF icfg_sdr_rfmax; + schedule osdr_we_n CF icfg_sdr_rfmax; + schedule osdr_dqm CF icfg_sdr_rfmax; + schedule osdr_ba CF icfg_sdr_rfmax; + schedule osdr_addr CF icfg_sdr_rfmax; + schedule osdr_init_done CF icfg_sdr_rfmax; + schedule oapp_req_ack CF icfg_sdr_rfmax; + schedule oapp_wr_next_req CF icfg_sdr_rfmax; + schedule oapp_rd_valid CF icfg_sdr_rfmax; + schedule oapp_last_rd CF icfg_sdr_rfmax; + schedule oapp_last_wr CF icfg_sdr_rfmax; + schedule oapp_rd_data CF icfg_sdr_rfmax; + schedule osdr_dout CF icfg_sdr_rfmax; + schedule osdr_den_n CF icfg_sdr_rfmax; + + schedule iapp_req_addr C iapp_req_addr; + schedule iapp_req_addr CF iapp_req_len; + schedule iapp_req_addr CF iapp_req_wr_n; + schedule iapp_req_addr CF iapp_wr_en_n; + schedule iapp_req_addr CF iapp_wr_data; + schedule osdr_cke CF iapp_req_addr; + schedule osdr_cs_n CF iapp_req_addr; + schedule osdr_ras_n CF iapp_req_addr; + schedule osdr_cas_n CF iapp_req_addr; + schedule osdr_we_n CF iapp_req_addr; + schedule osdr_dqm CF iapp_req_addr; + schedule osdr_ba CF iapp_req_addr; + schedule osdr_addr CF iapp_req_addr; + schedule osdr_init_done CF iapp_req_addr; + schedule oapp_req_ack CF iapp_req_addr; + schedule oapp_wr_next_req CF iapp_req_addr; + schedule oapp_rd_valid CF iapp_req_addr; + schedule oapp_last_rd CF iapp_req_addr; + schedule oapp_last_wr CF iapp_req_addr; + schedule oapp_rd_data CF iapp_req_addr; + schedule osdr_dout CF iapp_req_addr; + schedule osdr_den_n CF iapp_req_addr; + + schedule iapp_req_len C iapp_req_len; + schedule iapp_req_len CF iapp_req_wr_n; + schedule iapp_req_len CF iapp_wr_en_n; + schedule iapp_req_len CF iapp_wr_data; + schedule osdr_cke CF iapp_req_len; + schedule osdr_cs_n CF iapp_req_len; + schedule osdr_ras_n CF iapp_req_len; + schedule osdr_cas_n CF iapp_req_len; + schedule osdr_we_n CF iapp_req_len; + schedule osdr_dqm CF iapp_req_len; + schedule osdr_ba CF iapp_req_len; + schedule osdr_addr CF iapp_req_len; + schedule osdr_init_done CF iapp_req_len; + schedule oapp_req_ack CF iapp_req_len; + schedule oapp_wr_next_req CF iapp_req_len; + schedule oapp_rd_valid CF iapp_req_len; + schedule oapp_last_rd CF iapp_req_len; + schedule oapp_last_wr CF iapp_req_len; + schedule oapp_rd_data CF iapp_req_len; + schedule osdr_dout CF iapp_req_len; + schedule osdr_den_n CF iapp_req_len; + + schedule iapp_req_wr_n C iapp_req_wr_n; + schedule iapp_req_wr_n CF iapp_wr_en_n; + schedule iapp_req_wr_n CF iapp_wr_data; + schedule osdr_cke CF iapp_req_wr_n; + schedule osdr_cs_n CF iapp_req_wr_n; + schedule osdr_ras_n CF iapp_req_wr_n; + schedule osdr_cas_n CF iapp_req_wr_n; + schedule osdr_we_n CF iapp_req_wr_n; + schedule osdr_dqm CF iapp_req_wr_n; + schedule osdr_ba CF iapp_req_wr_n; + schedule osdr_addr CF iapp_req_wr_n; + schedule osdr_init_done CF iapp_req_wr_n; + schedule oapp_req_ack CF iapp_req_wr_n; + schedule oapp_wr_next_req CF iapp_req_wr_n; + schedule oapp_rd_valid CF iapp_req_wr_n; + schedule oapp_last_rd CF iapp_req_wr_n; + schedule oapp_last_wr CF iapp_req_wr_n; + schedule oapp_rd_data CF iapp_req_wr_n; + schedule osdr_dout CF iapp_req_wr_n; + schedule osdr_den_n CF iapp_req_wr_n; + + schedule iapp_wr_en_n C iapp_wr_en_n; + schedule iapp_wr_en_n CF iapp_wr_data; + schedule osdr_cke CF iapp_wr_en_n; + schedule osdr_cs_n CF iapp_wr_en_n; + schedule osdr_ras_n CF iapp_wr_en_n; + schedule osdr_cas_n CF iapp_wr_en_n; + schedule osdr_we_n CF iapp_wr_en_n; + schedule osdr_dqm CF iapp_wr_en_n; + schedule osdr_ba CF iapp_wr_en_n; + schedule osdr_addr CF iapp_wr_en_n; + schedule osdr_init_done CF iapp_wr_en_n; + schedule oapp_req_ack CF iapp_wr_en_n; + schedule oapp_wr_next_req CF iapp_wr_en_n; + schedule oapp_rd_valid CF iapp_wr_en_n; + schedule oapp_last_rd CF iapp_wr_en_n; + schedule oapp_last_wr CF iapp_wr_en_n; + schedule oapp_rd_data CF iapp_wr_en_n; + schedule osdr_dout CF iapp_wr_en_n; + schedule osdr_den_n CF iapp_wr_en_n; + + schedule iapp_wr_data C iapp_wr_data; + schedule osdr_cke CF iapp_wr_data; + schedule osdr_cs_n CF iapp_wr_data; + schedule osdr_ras_n CF iapp_wr_data; + schedule osdr_cas_n CF iapp_wr_data; + schedule osdr_we_n CF iapp_wr_data; + schedule osdr_dqm CF iapp_wr_data; + schedule osdr_ba CF iapp_wr_data; + schedule osdr_addr CF iapp_wr_data; + schedule osdr_init_done CF iapp_wr_data; + schedule oapp_req_ack CF iapp_wr_data; + schedule oapp_wr_next_req CF iapp_wr_data; + schedule oapp_rd_valid CF iapp_wr_data; + schedule oapp_last_rd CF iapp_wr_data; + schedule oapp_last_wr CF iapp_wr_data; + schedule oapp_rd_data CF iapp_wr_data; + schedule osdr_dout CF iapp_wr_data; + schedule osdr_den_n CF iapp_wr_data; + + schedule osdr_cke CF osdr_cke; + schedule osdr_cke CF osdr_cs_n; + schedule osdr_cke CF osdr_ras_n; + schedule osdr_cke CF osdr_cas_n; + schedule osdr_cke CF osdr_we_n; + schedule osdr_cke CF osdr_dqm; + schedule osdr_cke CF osdr_ba; + schedule osdr_cke CF osdr_addr; + schedule osdr_cke CF osdr_init_done; + schedule osdr_cke CF oapp_req_ack; + schedule osdr_cke CF oapp_wr_next_req; + schedule osdr_cke CF oapp_rd_valid; + schedule osdr_cke CF oapp_last_rd; + schedule osdr_cke CF oapp_last_wr; + schedule osdr_cke CF oapp_rd_data; + schedule osdr_cs_n CF osdr_cs_n; + schedule osdr_cs_n CF osdr_ras_n; + schedule osdr_cs_n CF osdr_cas_n; + schedule osdr_cs_n CF osdr_we_n; + schedule osdr_cs_n CF osdr_dqm; + schedule osdr_cs_n CF osdr_ba; + schedule osdr_cs_n CF osdr_addr; + schedule osdr_cs_n CF osdr_init_done; + schedule osdr_cs_n CF oapp_req_ack; + schedule osdr_cs_n CF oapp_wr_next_req; + schedule osdr_cs_n CF oapp_rd_valid; + schedule osdr_cs_n CF oapp_last_rd; + schedule osdr_cs_n CF oapp_last_wr; + schedule osdr_cs_n CF oapp_rd_data; + schedule osdr_ras_n CF osdr_ras_n; + schedule osdr_ras_n CF osdr_cas_n; + schedule osdr_ras_n CF osdr_we_n; + schedule osdr_ras_n CF osdr_dqm; + schedule osdr_ras_n CF osdr_ba; + schedule osdr_ras_n CF osdr_addr; + schedule osdr_ras_n CF osdr_init_done; + schedule osdr_ras_n CF oapp_req_ack; + schedule osdr_ras_n CF oapp_wr_next_req; + schedule osdr_ras_n CF oapp_rd_valid; + schedule osdr_ras_n CF oapp_last_rd; + schedule osdr_ras_n CF oapp_last_wr; + schedule osdr_ras_n CF oapp_rd_data; + schedule osdr_cas_n CF osdr_cas_n; + schedule osdr_cas_n CF osdr_we_n; + schedule osdr_cas_n CF osdr_dqm; + schedule osdr_cas_n CF osdr_ba; + schedule osdr_cas_n CF osdr_addr; + schedule osdr_cas_n CF osdr_init_done; + schedule osdr_cas_n CF oapp_req_ack; + schedule osdr_cas_n CF oapp_wr_next_req; + schedule osdr_cas_n CF oapp_rd_valid; + schedule osdr_cas_n CF oapp_last_rd; + schedule osdr_cas_n CF oapp_last_wr; + schedule osdr_cas_n CF oapp_rd_data; + schedule osdr_we_n CF osdr_we_n; + schedule osdr_we_n CF osdr_dqm; + schedule osdr_we_n CF osdr_ba; + schedule osdr_we_n CF osdr_addr; + schedule osdr_we_n CF osdr_init_done; + schedule osdr_we_n CF oapp_req_ack; + schedule osdr_we_n CF oapp_wr_next_req; + schedule osdr_we_n CF oapp_rd_valid; + schedule osdr_we_n CF oapp_last_rd; + schedule osdr_we_n CF oapp_last_wr; + schedule osdr_we_n CF oapp_rd_data; + schedule osdr_dqm CF osdr_dqm; + schedule osdr_dqm CF osdr_ba; + schedule osdr_dqm CF osdr_addr; + schedule osdr_dqm CF osdr_init_done; + schedule osdr_dqm CF oapp_req_ack; + schedule osdr_dqm CF oapp_wr_next_req; + schedule osdr_dqm CF oapp_rd_valid; + schedule osdr_dqm CF oapp_last_rd; + schedule osdr_dqm CF oapp_last_wr; + schedule osdr_dqm CF oapp_rd_data; + schedule osdr_ba CF osdr_ba; + schedule osdr_ba CF osdr_addr; + schedule osdr_ba CF osdr_init_done; + schedule osdr_ba CF oapp_req_ack; + schedule osdr_ba CF oapp_wr_next_req; + schedule osdr_ba CF oapp_rd_valid; + schedule osdr_ba CF oapp_last_rd; + schedule osdr_ba CF oapp_last_wr; + schedule osdr_ba CF oapp_rd_data; + schedule osdr_addr CF osdr_addr; + schedule osdr_addr CF osdr_init_done; + schedule osdr_addr CF oapp_req_ack; + schedule osdr_addr CF oapp_wr_next_req; + schedule osdr_addr CF oapp_rd_valid; + schedule osdr_addr CF oapp_last_rd; + schedule osdr_addr CF oapp_last_wr; + schedule osdr_addr CF oapp_rd_data; + schedule osdr_init_done CF osdr_init_done; + schedule osdr_init_done CF oapp_req_ack; + schedule osdr_init_done CF oapp_wr_next_req; + schedule osdr_init_done CF oapp_rd_valid; + schedule osdr_init_done CF oapp_last_rd; + schedule osdr_init_done CF oapp_last_wr; + schedule osdr_init_done CF oapp_rd_data; + schedule oapp_req_ack CF oapp_req_ack; + schedule oapp_req_ack CF oapp_wr_next_req; + schedule oapp_req_ack CF oapp_rd_valid; + schedule oapp_req_ack CF oapp_last_rd; + schedule oapp_req_ack CF oapp_last_wr; + schedule oapp_req_ack CF oapp_rd_data; + schedule oapp_wr_next_req CF oapp_wr_next_req; + schedule oapp_wr_next_req CF oapp_rd_valid; + schedule oapp_wr_next_req CF oapp_last_rd; + schedule oapp_wr_next_req CF oapp_last_wr; + schedule oapp_wr_next_req CF oapp_rd_data; + schedule oapp_rd_valid CF oapp_rd_valid; + schedule oapp_rd_valid CF oapp_last_rd; + schedule oapp_rd_valid CF oapp_last_wr; + schedule oapp_rd_valid CF oapp_rd_data; + schedule oapp_last_rd CF oapp_last_rd; + schedule oapp_last_rd CF oapp_last_wr; + schedule oapp_last_rd CF oapp_rd_data; + schedule oapp_last_wr CF oapp_last_wr; + schedule oapp_last_wr CF oapp_rd_data; + schedule oapp_rd_data CF oapp_rd_data; +endmodule + diff --git a/src/peripherals/sdram/controller/parallel_prog_delay_cell.v b/src/peripherals/sdram/controller/parallel_prog_delay_cell.v new file mode 100755 index 0000000..068b66b --- /dev/null +++ b/src/peripherals/sdram/controller/parallel_prog_delay_cell.v @@ -0,0 +1,42 @@ + +module parallel_prog_delay_cell ( in_clk, delay_config_reg, delayed_clk); + input in_clk; + input [3:0] delay_config_reg; + output delayed_clk; + + wire [7:0] wr_temp_delayed_clk; + wire xor_outp_clk; + + xor(xor_outp_clk, delay_config_reg[3], in_clk); + + assign wr_temp_delayed_clk[0]= xor_outp_clk; + delay_chain#(3) chain1 (.out(wr_temp_delayed_clk[1]),.in(xor_outp_clk)); + delay_chain#(6) chain2 (.out(wr_temp_delayed_clk[2]),.in(xor_outp_clk)); + delay_chain#(12) chain3 (.out(wr_temp_delayed_clk[3]),.in(xor_outp_clk)); + delay_chain#(18) chain4 (.out(wr_temp_delayed_clk[4]),.in(xor_outp_clk)); + delay_chain#(26) chain5 (.out(wr_temp_delayed_clk[5]),.in(xor_outp_clk)); + delay_chain#(38) chain6 (.out(wr_temp_delayed_clk[6]),.in(xor_outp_clk)); + delay_chain#(50) chain7 (.out(wr_temp_delayed_clk[7]),.in(xor_outp_clk)); + + assign delayed_clk= wr_temp_delayed_clk[delay_config_reg[2:0]]; + +endmodule + +module delay_chain (in, out); + parameter Depth=0; + input in; + output out; + wire [Depth-1:0] wr_inter; + + buf(wr_inter[0],in); // replace this with the buffer from the ASIC library + genvar i; + generate + for(i=1; i<= Depth-1; i=i+1) + begin: gen_delay_buffer_chains + buf(wr_inter[i],wr_inter[i-1]); // replace this with the buffer form the ASIC library. + end + endgenerate + + assign out= wr_inter[Depth-1]; +endmodule + diff --git a/src/peripherals/sdram/controller/sdrc_bank_ctl.v b/src/peripherals/sdram/controller/sdrc_bank_ctl.v new file mode 100755 index 0000000..96fe94b --- /dev/null +++ b/src/peripherals/sdram/controller/sdrc_bank_ctl.v @@ -0,0 +1,602 @@ +/********************************************************************* + + SDRAM Controller Bank Controller + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: + This module takes requests from sdrc_req_gen, checks for page hit/miss and + issues precharge/activate commands and then passes the request to sdrc_xfr_ctl. + + To Do: + nothing + + Author(s): + - Dinesh Annayya, dinesha@opencores.org + Version : 1.0 - 8th Jan 2012 + + + + Copyright (C) 2000 Authors and OPENCORES.ORG + + This source file may be used and distributed without + restriction provided that this copyright statement is not + removed from the file and that any derivative work contains + the original copyright notice and the associated disclaimer. + + This source file is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General + Public License as published by the Free Software Foundation; + either version 2.1 of the License, or (at your option) any +later version. + + This source 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General + Public License along with this source; if not, download it + from http://www.opencores.org/lgpl.shtml + +*******************************************************************/ + + + + +module sdrc_bank_ctl (clk, + reset_n, + a2b_req_depth, // Number of requests we can buffer + + /* Req from req_gen */ + r2b_req, // request + r2b_req_id, // ID + r2b_start, // First chunk of burst + r2b_last, // Last chunk of burst + r2b_wrap, + r2b_ba, // bank address + r2b_raddr, // row address + r2b_caddr, // col address + r2b_len, // length + r2b_write, // write request + b2r_arb_ok, // OK to arbitrate for next xfr + b2r_ack, + + /* Transfer request to xfr_ctl */ + b2x_idle, // All banks are idle + b2x_req, // Request to xfr_ctl + b2x_start, // first chunk of transfer + b2x_last, // last chunk of transfer + b2x_wrap, + b2x_id, // Transfer ID + b2x_ba, // bank address + b2x_addr, // row/col address + b2x_len, // transfer length + b2x_cmd, // transfer command + x2b_ack, // command accepted + + /* Status to/from xfr_ctl */ + b2x_tras_ok, // TRAS OK for all banks + x2b_refresh, // We did a refresh + x2b_pre_ok, // OK to do a precharge (per bank) + x2b_act_ok, // OK to do an activate + x2b_rdok, // OK to do a read + x2b_wrok, // OK to do a write + + /* xfr msb address */ + xfr_bank_sel, + sdr_req_norm_dma_last, + + /* SDRAM Timing */ + tras_delay, // Active to precharge delay + trp_delay, // Precharge to active delay + trcd_delay); // Active to R/W delay + +`define SDR_REQ_ID_W 4 + +`define SDR_RFSH_TIMER_W 12 +`define SDR_RFSH_ROW_CNT_W 3 + +// B2X Command + +`define OP_PRE 2'b00 +`define OP_ACT 2'b01 +`define OP_RD 2'b10 +`define OP_WR 2'b11 + +// SDRAM Commands (CS_N, RAS_N, CAS_N, WE_N) + +`define SDR_DESEL 4'b1111 +`define SDR_NOOP 4'b0111 +`define SDR_ACTIVATE 4'b0011 +`define SDR_READ 4'b0101 +`define SDR_WRITE 4'b0100 +`define SDR_BT 4'b0110 +`define SDR_PRECHARGE 4'b0010 +`define SDR_REFRESH 4'b0001 +`define SDR_MODE 4'b0000 + +`define ASIC 1'b1 +`define FPGA 1'b0 +`define TARGET_DESIGN `ASIC +// 12 bit subtractor is not feasibile for FPGA, so changed to 6 bits +`define REQ_BW (`TARGET_DESIGN == `FPGA) ? 6 : 12 // Request Width + + +parameter SDR_DW = 64; // SDR Data Width +parameter SDR_BW = 8; // SDR Byte Width + input clk, reset_n; + + input [1:0] a2b_req_depth; + + /* Req from bank_ctl */ + input r2b_req, r2b_start, r2b_last, + r2b_write, r2b_wrap; + input [`SDR_REQ_ID_W-1:0] r2b_req_id; + input [1:0] r2b_ba; + input [12:0] r2b_raddr; + input [12:0] r2b_caddr; + input [`REQ_BW-1:0] r2b_len; + output b2r_arb_ok, b2r_ack; + input sdr_req_norm_dma_last; + + /* Req to xfr_ctl */ + output b2x_idle, b2x_req, b2x_start, b2x_last, + b2x_tras_ok, b2x_wrap; + output [`SDR_REQ_ID_W-1:0] b2x_id; + output [1:0] b2x_ba; + output [12:0] b2x_addr; + output [`REQ_BW-1:0] b2x_len; + output [1:0] b2x_cmd; + input x2b_ack; + + /* Status from xfr_ctl */ + input [3:0] x2b_pre_ok; + input x2b_refresh, x2b_act_ok, x2b_rdok, + x2b_wrok; + + input [3:0] tras_delay, trp_delay, trcd_delay; + + input [1:0] xfr_bank_sel; + + /****************************************************************************/ + // Internal Nets + + wire [3:0] r2i_req, i2r_ack, i2x_req, + i2x_start, i2x_last, i2x_wrap, tras_ok; + wire [12:0] i2x_addr0, i2x_addr1, i2x_addr2, i2x_addr3; + wire [`REQ_BW-1:0] i2x_len0, i2x_len1, i2x_len2, i2x_len3; + wire [1:0] i2x_cmd0, i2x_cmd1, i2x_cmd2, i2x_cmd3; + wire [`SDR_REQ_ID_W-1:0] i2x_id0, i2x_id1, i2x_id2, i2x_id3; + + reg b2x_req; + wire b2x_idle, b2x_start, b2x_last, b2x_wrap; + wire [`SDR_REQ_ID_W-1:0] b2x_id; + wire [12:0] b2x_addr; + wire [`REQ_BW-1:0] b2x_len; + wire [1:0] b2x_cmd; + wire [3:0] x2i_ack; + reg [1:0] b2x_ba; + + reg [`SDR_REQ_ID_W-1:0] curr_id; + + wire [1:0] xfr_ba; + wire xfr_ba_last; + wire [3:0] xfr_ok; + + // This 8 bit register stores the bank addresses for upto 4 requests. + reg [7:0] rank_ba; + reg [3:0] rank_ba_last; + // This 3 bit counter counts the number of requests we have + // buffered so far, legal values are 0, 1, 2, 3, or 4. + reg [2:0] rank_cnt; + wire [3:0] rank_req, rank_wr_sel; + wire rank_fifo_wr, rank_fifo_rd; + wire rank_fifo_full, rank_fifo_mt; + + wire [12:0] bank0_row, bank1_row, bank2_row, bank3_row; + + assign b2x_tras_ok = &tras_ok; + + + // Distribute the request from req_gen + + assign r2i_req[0] = (r2b_ba == 2'b00) ? r2b_req & ~rank_fifo_full : 1'b0; + assign r2i_req[1] = (r2b_ba == 2'b01) ? r2b_req & ~rank_fifo_full : 1'b0; + assign r2i_req[2] = (r2b_ba == 2'b10) ? r2b_req & ~rank_fifo_full : 1'b0; + assign r2i_req[3] = (r2b_ba == 2'b11) ? r2b_req & ~rank_fifo_full : 1'b0; + + /****************** + Modified the Better FPGA Timing Purpose + assign b2r_ack = (r2b_ba == 2'b00) ? i2r_ack[0] : + (r2b_ba == 2'b01) ? i2r_ack[1] : + (r2b_ba == 2'b10) ? i2r_ack[2] : + (r2b_ba == 2'b11) ? i2r_ack[3] : 1'b0; + ********************/ + // Assumption: Only one Ack Will be asserted at a time. + assign b2r_ack =|i2r_ack; + + assign b2r_arb_ok = ~rank_fifo_full; + + // Put the requests from the 4 bank_fsms into a 4 deep shift + // register file. The earliest request is prioritized over the + // later requests. Also the number of requests we are allowed to + // buffer is limited by a 2 bit external input + + // Mux the req/cmd to xfr_ctl. Allow RD/WR commands from the request in + // rank0, allow only PR/ACT commands from the requests in other ranks + // If the rank_fifo is empty, send the request from the bank addressed by + // r2b_ba + + // In FPGA Mode, to improve the timing, also send the rank_ba + assign xfr_ba = (`TARGET_DESIGN == `FPGA) ? rank_ba[1:0]: + ((rank_fifo_mt) ? r2b_ba : rank_ba[1:0]); + assign xfr_ba_last = (`TARGET_DESIGN == `FPGA) ? rank_ba_last[0]: + ((rank_fifo_mt) ? sdr_req_norm_dma_last : rank_ba_last[0]); + + assign rank_req[0] = i2x_req[xfr_ba]; // each rank generates requests + + assign rank_req[1] = (rank_cnt < 3'h2) ? 1'b0 : + (rank_ba[3:2] == 2'b00) ? i2x_req[0] & ~i2x_cmd0[1] : + (rank_ba[3:2] == 2'b01) ? i2x_req[1] & ~i2x_cmd1[1] : + (rank_ba[3:2] == 2'b10) ? i2x_req[2] & ~i2x_cmd2[1] : + i2x_req[3] & ~i2x_cmd3[1]; + + assign rank_req[2] = (rank_cnt < 3'h3) ? 1'b0 : + (rank_ba[5:4] == 2'b00) ? i2x_req[0] & ~i2x_cmd0[1] : + (rank_ba[5:4] == 2'b01) ? i2x_req[1] & ~i2x_cmd1[1] : + (rank_ba[5:4] == 2'b10) ? i2x_req[2] & ~i2x_cmd2[1] : + i2x_req[3] & ~i2x_cmd3[1]; + + assign rank_req[3] = (rank_cnt < 3'h4) ? 1'b0 : + (rank_ba[7:6] == 2'b00) ? i2x_req[0] & ~i2x_cmd0[1] : + (rank_ba[7:6] == 2'b01) ? i2x_req[1] & ~i2x_cmd1[1] : + (rank_ba[7:6] == 2'b10) ? i2x_req[2] & ~i2x_cmd2[1] : + i2x_req[3] & ~i2x_cmd3[1]; + + always @ (*) begin + b2x_req = 1'b0; + b2x_ba = xfr_ba; + + if(`TARGET_DESIGN == `ASIC) begin // Support Multiple Rank request only on ASIC + if (rank_req[0]) begin + b2x_req = 1'b1; + b2x_ba = xfr_ba; + end // if (rank_req[0]) + else if (rank_req[1]) begin + b2x_req = 1'b1; + b2x_ba = rank_ba[3:2]; + end // if (rank_req[1]) + else if (rank_req[2]) begin + b2x_req = 1'b1; + b2x_ba = rank_ba[5:4]; + end // if (rank_req[2]) + else if (rank_req[3]) begin + b2x_req = 1'b1; + b2x_ba = rank_ba[7:6]; + end // if (rank_req[3]) + end else begin // If FPGA + if (rank_req[0]) begin + b2x_req = 1'b1; + end + end + end // always @ (rank_req or rank_fifo_mt or r2b_ba or rank_ba) + + assign b2x_idle = rank_fifo_mt; + assign b2x_start = i2x_start[b2x_ba]; + assign b2x_last = i2x_last[b2x_ba]; + assign b2x_wrap = i2x_wrap[b2x_ba]; + + assign b2x_addr = (b2x_ba == 2'b11) ? i2x_addr3 : + (b2x_ba == 2'b10) ? i2x_addr2 : + (b2x_ba == 2'b01) ? i2x_addr1 : i2x_addr0; + + assign b2x_len = (b2x_ba == 2'b11) ? i2x_len3 : + (b2x_ba == 2'b10) ? i2x_len2 : + (b2x_ba == 2'b01) ? i2x_len1 : i2x_len0; + + assign b2x_cmd = (b2x_ba == 2'b11) ? i2x_cmd3 : + (b2x_ba == 2'b10) ? i2x_cmd2 : + (b2x_ba == 2'b01) ? i2x_cmd1 : i2x_cmd0; + + assign b2x_id = (b2x_ba == 2'b11) ? i2x_id3 : + (b2x_ba == 2'b10) ? i2x_id2 : + (b2x_ba == 2'b01) ? i2x_id1 : i2x_id0; + + assign x2i_ack[0] = (b2x_ba == 2'b00) ? x2b_ack : 1'b0; + assign x2i_ack[1] = (b2x_ba == 2'b01) ? x2b_ack : 1'b0; + assign x2i_ack[2] = (b2x_ba == 2'b10) ? x2b_ack : 1'b0; + assign x2i_ack[3] = (b2x_ba == 2'b11) ? x2b_ack : 1'b0; + + // Rank Fifo + // On a write write to selected rank and increment rank_cnt + // On a read shift rank_ba right 2 bits and decrement rank_cnt + + assign rank_fifo_wr = b2r_ack; + + assign rank_fifo_rd = b2x_req & b2x_cmd[1] & x2b_ack; + + assign rank_wr_sel[0] = (rank_cnt == 3'h0) ? rank_fifo_wr : + (rank_cnt == 3'h1) ? rank_fifo_wr & rank_fifo_rd : + 1'b0; + + assign rank_wr_sel[1] = (rank_cnt == 3'h1) ? rank_fifo_wr & ~rank_fifo_rd : + (rank_cnt == 3'h2) ? rank_fifo_wr & rank_fifo_rd : + 1'b0; + + assign rank_wr_sel[2] = (rank_cnt == 3'h2) ? rank_fifo_wr & ~rank_fifo_rd : + (rank_cnt == 3'h3) ? rank_fifo_wr & rank_fifo_rd : + 1'b0; + + assign rank_wr_sel[3] = (rank_cnt == 3'h3) ? rank_fifo_wr & ~rank_fifo_rd : + (rank_cnt == 3'h4) ? rank_fifo_wr & rank_fifo_rd : + 1'b0; + + assign rank_fifo_mt = (rank_cnt == 3'b0) ? 1'b1 : 1'b0; + + assign rank_fifo_full = (rank_cnt[2]) ? 1'b1 : + (rank_cnt[1:0] == a2b_req_depth) ? 1'b1 : 1'b0; + + // FIFO Check + + // synopsys translate_off + + always @ (posedge clk) begin + + if (~rank_fifo_wr & rank_fifo_rd && rank_cnt == 3'h0) begin + $display ("%t: %m: ERROR!!! Read from empty Fifo", $time); + $stop; + end // if (rank_fifo_rd && rank_cnt == 3'h0) + + if (rank_fifo_wr && ~rank_fifo_rd && rank_cnt == 3'h4) begin + $display ("%t: %m: ERROR!!! Write to full Fifo", $time); + $stop; + end // if (rank_fifo_wr && ~rank_fifo_rd && rank_cnt == 3'h4) + + end // always @ (posedge clk) + + // synopsys translate_on + + always @ (posedge clk) + if (~reset_n) begin + rank_cnt <= 3'b0; + rank_ba <= 8'b0; + rank_ba_last <= 4'b0; + + end // if (~reset_n) + else begin + + rank_cnt <= (rank_fifo_wr & ~rank_fifo_rd) ? rank_cnt + 3'b1 : + (~rank_fifo_wr & rank_fifo_rd) ? rank_cnt - 3'b1 : + rank_cnt; + + rank_ba[1:0] <= (rank_wr_sel[0]) ? r2b_ba : + (rank_fifo_rd) ? rank_ba[3:2] : rank_ba[1:0]; + + rank_ba[3:2] <= (rank_wr_sel[1]) ? r2b_ba : + (rank_fifo_rd) ? rank_ba[5:4] : rank_ba[3:2]; + + rank_ba[5:4] <= (rank_wr_sel[2]) ? r2b_ba : + (rank_fifo_rd) ? rank_ba[7:6] : rank_ba[5:4]; + + rank_ba[7:6] <= (rank_wr_sel[3]) ? r2b_ba : + (rank_fifo_rd) ? 2'b00 : rank_ba[7:6]; + + if(`TARGET_DESIGN == `ASIC) begin // This Logic is implemented for ASIC Only + // Note: Currenly top-level does not generate the + // sdr_req_norm_dma_last signal and can be tied zero at top-level + rank_ba_last[0] <= (rank_wr_sel[0]) ? sdr_req_norm_dma_last : + (rank_fifo_rd) ? rank_ba_last[1] : rank_ba_last[0]; + + rank_ba_last[1] <= (rank_wr_sel[1]) ? sdr_req_norm_dma_last : + (rank_fifo_rd) ? rank_ba_last[2] : rank_ba_last[1]; + + rank_ba_last[2] <= (rank_wr_sel[2]) ? sdr_req_norm_dma_last : + (rank_fifo_rd) ? rank_ba_last[3] : rank_ba_last[2]; + + rank_ba_last[3] <= (rank_wr_sel[3]) ? sdr_req_norm_dma_last : + (rank_fifo_rd) ? 1'b0 : rank_ba_last[3]; + end + + end // else: !if(~reset_n) + + assign xfr_ok[0] = (xfr_ba == 2'b00) ? 1'b1 : 1'b0; + assign xfr_ok[1] = (xfr_ba == 2'b01) ? 1'b1 : 1'b0; + assign xfr_ok[2] = (xfr_ba == 2'b10) ? 1'b1 : 1'b0; + assign xfr_ok[3] = (xfr_ba == 2'b11) ? 1'b1 : 1'b0; + + /****************************************************************************/ + // Instantiate Bank Ctl FSM 0 + + sdrc_bank_fsm bank0_fsm (.clk (clk), + .reset_n (reset_n), + + /* Req from req_gen */ + .r2b_req (r2i_req[0]), + .r2b_req_id (r2b_req_id), + .r2b_start (r2b_start), + .r2b_last (r2b_last), + .r2b_wrap (r2b_wrap), + .r2b_raddr (r2b_raddr), + .r2b_caddr (r2b_caddr), + .r2b_len (r2b_len), + .r2b_write (r2b_write), + .b2r_ack (i2r_ack[0]), + .sdr_dma_last(rank_ba_last[0]), + + /* Transfer request to xfr_ctl */ + .b2x_req (i2x_req[0]), + .b2x_start (i2x_start[0]), + .b2x_last (i2x_last[0]), + .b2x_wrap (i2x_wrap[0]), + .b2x_id (i2x_id0), + .b2x_addr (i2x_addr0), + .b2x_len (i2x_len0), + .b2x_cmd (i2x_cmd0), + .x2b_ack (x2i_ack[0]), + + /* Status to/from xfr_ctl */ + .tras_ok (tras_ok[0]), + .xfr_ok (xfr_ok[0]), + .x2b_refresh (x2b_refresh), + .x2b_pre_ok (x2b_pre_ok[0]), + .x2b_act_ok (x2b_act_ok), + .x2b_rdok (x2b_rdok), + .x2b_wrok (x2b_wrok), + + .bank_row(bank0_row), + + /* SDRAM Timing */ + .tras_delay (tras_delay), + .trp_delay (trp_delay), + .trcd_delay (trcd_delay)); + + /****************************************************************************/ + // Instantiate Bank Ctl FSM 1 + + sdrc_bank_fsm bank1_fsm (.clk (clk), + .reset_n (reset_n), + + /* Req from req_gen */ + .r2b_req (r2i_req[1]), + .r2b_req_id (r2b_req_id), + .r2b_start (r2b_start), + .r2b_last (r2b_last), + .r2b_wrap (r2b_wrap), + .r2b_raddr (r2b_raddr), + .r2b_caddr (r2b_caddr), + .r2b_len (r2b_len), + .r2b_write (r2b_write), + .b2r_ack (i2r_ack[1]), + .sdr_dma_last(rank_ba_last[1]), + + /* Transfer request to xfr_ctl */ + .b2x_req (i2x_req[1]), + .b2x_start (i2x_start[1]), + .b2x_last (i2x_last[1]), + .b2x_wrap (i2x_wrap[1]), + .b2x_id (i2x_id1), + .b2x_addr (i2x_addr1), + .b2x_len (i2x_len1), + .b2x_cmd (i2x_cmd1), + .x2b_ack (x2i_ack[1]), + + /* Status to/from xfr_ctl */ + .tras_ok (tras_ok[1]), + .xfr_ok (xfr_ok[1]), + .x2b_refresh (x2b_refresh), + .x2b_pre_ok (x2b_pre_ok[1]), + .x2b_act_ok (x2b_act_ok), + .x2b_rdok (x2b_rdok), + .x2b_wrok (x2b_wrok), + + .bank_row(bank1_row), + + /* SDRAM Timing */ + .tras_delay (tras_delay), + .trp_delay (trp_delay), + .trcd_delay (trcd_delay)); + + /****************************************************************************/ + // Instantiate Bank Ctl FSM 2 + + sdrc_bank_fsm bank2_fsm (.clk (clk), + .reset_n (reset_n), + + /* Req from req_gen */ + .r2b_req (r2i_req[2]), + .r2b_req_id (r2b_req_id), + .r2b_start (r2b_start), + .r2b_last (r2b_last), + .r2b_wrap (r2b_wrap), + .r2b_raddr (r2b_raddr), + .r2b_caddr (r2b_caddr), + .r2b_len (r2b_len), + .r2b_write (r2b_write), + .b2r_ack (i2r_ack[2]), + .sdr_dma_last(rank_ba_last[2]), + + /* Transfer request to xfr_ctl */ + .b2x_req (i2x_req[2]), + .b2x_start (i2x_start[2]), + .b2x_last (i2x_last[2]), + .b2x_wrap (i2x_wrap[2]), + .b2x_id (i2x_id2), + .b2x_addr (i2x_addr2), + .b2x_len (i2x_len2), + .b2x_cmd (i2x_cmd2), + .x2b_ack (x2i_ack[2]), + + /* Status to/from xfr_ctl */ + .tras_ok (tras_ok[2]), + .xfr_ok (xfr_ok[2]), + .x2b_refresh (x2b_refresh), + .x2b_pre_ok (x2b_pre_ok[2]), + .x2b_act_ok (x2b_act_ok), + .x2b_rdok (x2b_rdok), + .x2b_wrok (x2b_wrok), + + .bank_row(bank2_row), + + /* SDRAM Timing */ + .tras_delay (tras_delay), + .trp_delay (trp_delay), + .trcd_delay (trcd_delay)); + + /****************************************************************************/ + // Instantiate Bank Ctl FSM 3 + + sdrc_bank_fsm bank3_fsm (.clk (clk), + .reset_n (reset_n), + + /* Req from req_gen */ + .r2b_req (r2i_req[3]), + .r2b_req_id (r2b_req_id), + .r2b_start (r2b_start), + .r2b_last (r2b_last), + .r2b_wrap (r2b_wrap), + .r2b_raddr (r2b_raddr), + .r2b_caddr (r2b_caddr), + .r2b_len (r2b_len), + .r2b_write (r2b_write), + .b2r_ack (i2r_ack[3]), + .sdr_dma_last(rank_ba_last[3]), + + /* Transfer request to xfr_ctl */ + .b2x_req (i2x_req[3]), + .b2x_start (i2x_start[3]), + .b2x_last (i2x_last[3]), + .b2x_wrap (i2x_wrap[3]), + .b2x_id (i2x_id3), + .b2x_addr (i2x_addr3), + .b2x_len (i2x_len3), + .b2x_cmd (i2x_cmd3), + .x2b_ack (x2i_ack[3]), + + /* Status to/from xfr_ctl */ + .tras_ok (tras_ok[3]), + .xfr_ok (xfr_ok[3]), + .x2b_refresh (x2b_refresh), + .x2b_pre_ok (x2b_pre_ok[3]), + .x2b_act_ok (x2b_act_ok), + .x2b_rdok (x2b_rdok), + .x2b_wrok (x2b_wrok), + + .bank_row(bank3_row), + + /* SDRAM Timing */ + .tras_delay (tras_delay), + .trp_delay (trp_delay), + .trcd_delay (trcd_delay)); + + +/* address for current xfr, debug only */ +wire [12:0] cur_row = (xfr_bank_sel==3) ? bank3_row: + (xfr_bank_sel==2) ? bank2_row: + (xfr_bank_sel==1) ? bank1_row: bank0_row; + + + +endmodule // sdr_bank_ctl diff --git a/src/peripherals/sdram/controller/sdrc_bank_fsm.v b/src/peripherals/sdram/controller/sdrc_bank_fsm.v new file mode 100755 index 0000000..7ac177d --- /dev/null +++ b/src/peripherals/sdram/controller/sdrc_bank_fsm.v @@ -0,0 +1,401 @@ +/********************************************************************* + + SDRAM Controller Bank Controller + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: + This module takes requests from sdrc_req_gen, checks for page hit/miss and + issues precharge/activate commands and then passes the request to sdrc_xfr_ctl. + + To Do: + nothing + + Author(s): + - Dinesh Annayya, dinesha@opencores.org + Version : 1.0 - 8th Jan 2012 + + + + Copyright (C) 2000 Authors and OPENCORES.ORG + + This source file may be used and distributed without + restriction provided that this copyright statement is not + removed from the file and that any derivative work contains + the original copyright notice and the associated disclaimer. + + This source file is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General + Public License as published by the Free Software Foundation; + either version 2.1 of the License, or (at your option) any +later version. + + This source 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General + Public License along with this source; if not, download it + from http://www.opencores.org/lgpl.shtml + +*******************************************************************/ + + +//`include "sdrc_define.v" + +module sdrc_bank_fsm (clk, + reset_n, + + /* Req from req_gen */ + r2b_req, // request + r2b_req_id, // ID + r2b_start, // First chunk of burst + r2b_last, // Last chunk of burst + r2b_wrap, + r2b_raddr, // row address + r2b_caddr, // col address + r2b_len, // length + r2b_write, // write request + b2r_ack, + sdr_dma_last, + + /* Transfer request to xfr_ctl */ + b2x_req, // Request to xfr_ctl + b2x_start, // first chunk of transfer + b2x_last, // last chunk of transfer + b2x_wrap, + b2x_id, // Transfer ID + b2x_addr, // row/col address + b2x_len, // transfer length + b2x_cmd, // transfer command + x2b_ack, // command accepted + + /* Status to/from xfr_ctl */ + tras_ok, // TRAS OK for this bank + xfr_ok, + x2b_refresh, // We did a refresh + x2b_pre_ok, // OK to do a precharge (per bank) + x2b_act_ok, // OK to do an activate + x2b_rdok, // OK to do a read + x2b_wrok, // OK to do a write + + /* current xfr row address of the bank */ + bank_row, + + /* SDRAM Timing */ + tras_delay, // Active to precharge delay + trp_delay, // Precharge to active delay + trcd_delay); // Active to R/W delay + + +`define SDR_REQ_ID_W 4 + +`define SDR_RFSH_TIMER_W 12 +`define SDR_RFSH_ROW_CNT_W 3 + +// B2X Command + +`define OP_PRE 2'b00 +`define OP_ACT 2'b01 +`define OP_RD 2'b10 +`define OP_WR 2'b11 + +// SDRAM Commands (CS_N, RAS_N, CAS_N, WE_N) + +`define SDR_DESEL 4'b1111 +`define SDR_NOOP 4'b0111 +`define SDR_ACTIVATE 4'b0011 +`define SDR_READ 4'b0101 +`define SDR_WRITE 4'b0100 +`define SDR_BT 4'b0110 +`define SDR_PRECHARGE 4'b0010 +`define SDR_REFRESH 4'b0001 +`define SDR_MODE 4'b0000 + +`define ASIC 1'b1 +`define FPGA 1'b0 +`define TARGET_DESIGN `ASIC +// 12 bit subtractor is not feasibile for FPGA, so changed to 6 bits +`define REQ_BW (`TARGET_DESIGN == `FPGA) ? 6 : 12 // Request Width + +parameter SDR_DW = 64; // SDR Data Width +parameter SDR_BW = 8; // SDR Byte Width + + input clk, reset_n; + + /* Req from bank_ctl */ + input r2b_req, r2b_start, r2b_last, + r2b_write, r2b_wrap; + input [`SDR_REQ_ID_W-1:0] r2b_req_id; + input [12:0] r2b_raddr; + input [12:0] r2b_caddr; + input [`REQ_BW-1:0] r2b_len; + output b2r_ack; + input sdr_dma_last; + + /* Req to xfr_ctl */ + output b2x_req, b2x_start, b2x_last, + tras_ok, b2x_wrap; + output [`SDR_REQ_ID_W-1:0] b2x_id; + output [12:0] b2x_addr; + output [`REQ_BW-1:0] b2x_len; + output [1:0] b2x_cmd; + input x2b_ack; + + /* Status from xfr_ctl */ + input x2b_refresh, x2b_act_ok, x2b_rdok, + x2b_wrok, x2b_pre_ok, xfr_ok; + + input [3:0] tras_delay, trp_delay, trcd_delay; + + output [12:0] bank_row; + + /****************************************************************************/ + // Internal Nets + + `define BANK_IDLE 3'b000 + `define BANK_PRE 3'b001 + `define BANK_ACT 3'b010 + `define BANK_XFR 3'b011 + `define BANK_DMA_LAST_PRE 3'b100 + + reg [2:0] bank_st, next_bank_st; + wire b2x_start, b2x_last; + reg l_start, l_last; + reg b2x_req, b2r_ack; + wire [`SDR_REQ_ID_W-1:0] b2x_id; + reg [`SDR_REQ_ID_W-1:0] l_id; + reg [12:0] b2x_addr; + reg [`REQ_BW-1:0] l_len; + wire [`REQ_BW-1:0] b2x_len; + reg [1:0] b2x_cmd_t; + reg bank_valid; + reg [12:0] bank_row; + reg [3:0] tras_cntr, timer0; + reg l_wrap, l_write; + wire b2x_wrap; + reg [12:0] l_raddr; + reg [12:0] l_caddr; + reg l_sdr_dma_last; + reg bank_prech_page_closed; + + wire tras_ok_internal, tras_ok, activate_bank; + + wire page_hit, timer0_tc_t, ld_trp, ld_trcd; + + /*** Timing Break Logic Added for FPGA - Start ****/ + reg x2b_wrok_r, xfr_ok_r , x2b_rdok_r; + reg [1:0] b2x_cmd_r,timer0_tc_r,tras_ok_r,x2b_pre_ok_r,x2b_act_ok_r; + always @ (posedge clk) + if (~reset_n) begin + x2b_wrok_r <= 1'b0; + xfr_ok_r <= 1'b0; + x2b_rdok_r <= 1'b0; + b2x_cmd_r <= 2'b0; + timer0_tc_r <= 1'b0; + tras_ok_r <= 1'b0; + x2b_pre_ok_r <= 1'b0; + x2b_act_ok_r <= 1'b0; + end + else begin + x2b_wrok_r <= x2b_wrok; + xfr_ok_r <= xfr_ok; + x2b_rdok_r <= x2b_rdok; + b2x_cmd_r <= b2x_cmd_t; + timer0_tc_r <= (ld_trp | ld_trcd) ? 1'b0 : timer0_tc_t; + tras_ok_r <= tras_ok_internal; + x2b_pre_ok_r <= x2b_pre_ok; + x2b_act_ok_r <= x2b_act_ok; + end + + wire x2b_wrok_t = (`TARGET_DESIGN == `FPGA) ? x2b_wrok_r : x2b_wrok; + wire xfr_ok_t = (`TARGET_DESIGN == `FPGA) ? xfr_ok_r : xfr_ok; + wire x2b_rdok_t = (`TARGET_DESIGN == `FPGA) ? x2b_rdok_r : x2b_rdok; + wire [1:0] b2x_cmd = (`TARGET_DESIGN == `FPGA) ? b2x_cmd_r : b2x_cmd_t; + wire timer0_tc = (`TARGET_DESIGN == `FPGA) ? timer0_tc_r : timer0_tc_t; + assign tras_ok = (`TARGET_DESIGN == `FPGA) ? tras_ok_r : tras_ok_internal; + wire x2b_pre_ok_t = (`TARGET_DESIGN == `FPGA) ? x2b_pre_ok_r : x2b_pre_ok; + wire x2b_act_ok_t = (`TARGET_DESIGN == `FPGA) ? x2b_act_ok_r : x2b_act_ok; + + /*** Timing Break Logic Added for FPGA - End****/ + + + always @ (posedge clk) + if (~reset_n) begin + bank_valid <= 1'b0; + tras_cntr <= 4'b0; + timer0 <= 4'b0; + bank_st <= `BANK_IDLE; + end // if (~reset_n) + + else begin + + bank_valid <= (x2b_refresh || bank_prech_page_closed) ? 1'b0 : // force the bank status to be invalid + (activate_bank) ? 1'b1 : bank_valid; + + tras_cntr <= (activate_bank) ? tras_delay : + (~tras_ok_internal) ? tras_cntr - 4'b1 : 4'b0; + + timer0 <= (ld_trp) ? trp_delay : + (ld_trcd) ? trcd_delay : + (timer0 != 'h0) ? timer0 - 4'b1 : timer0; + + bank_st <= next_bank_st; + + end // else: !if(~reset_n) + + always @ (posedge clk) begin + + bank_row <= (bank_st == `BANK_ACT) ? b2x_addr : bank_row; + + if (~reset_n) begin + l_start <= 1'b0; + l_last <= 1'b0; + l_id <= 1'b0; + l_len <= 1'b0; + l_wrap <= 1'b0; + l_write <= 1'b0; + l_raddr <= 1'b0; + l_caddr <= 1'b0; + l_sdr_dma_last <= 1'b0; + end + else begin + if (b2r_ack) begin + l_start <= r2b_start; + l_last <= r2b_last; + l_id <= r2b_req_id; + l_len <= r2b_len; + l_wrap <= r2b_wrap; + l_write <= r2b_write; + l_raddr <= r2b_raddr; + l_caddr <= r2b_caddr; + l_sdr_dma_last <= sdr_dma_last; + end // if (b2r_ack) + end + + end // always @ (posedge clk) + + assign tras_ok_internal = ~|tras_cntr; + + assign activate_bank = (b2x_cmd == `OP_ACT) & x2b_ack; + + assign page_hit = (r2b_raddr == bank_row) ? bank_valid : 1'b0; // its a hit only if bank is valid + + assign timer0_tc_t = ~|timer0; + + assign ld_trp = (b2x_cmd == `OP_PRE) ? x2b_ack : 1'b0; + + assign ld_trcd = (b2x_cmd == `OP_ACT) ? x2b_ack : 1'b0; + + + + always @ (*) begin + + bank_prech_page_closed = 1'b0; + b2x_req = 1'b0; + b2x_cmd_t = 2'bx; + b2r_ack = 1'b0; + b2x_addr = 13'bx; + next_bank_st = bank_st; + + case (bank_st) + + `BANK_IDLE : begin + if(`TARGET_DESIGN == `FPGA) begin // To break the timing, b2x request are generated delayed + if (~r2b_req) begin + next_bank_st = `BANK_IDLE; + end // if (~r2b_req) + else if (page_hit) begin + b2r_ack = 1'b1; + b2x_cmd_t = (r2b_write) ? `OP_WR : `OP_RD; + next_bank_st = `BANK_XFR; + end // if (page_hit) + else begin // page_miss + b2r_ack = 1'b1; + b2x_cmd_t = `OP_PRE; + next_bank_st = `BANK_PRE; // bank was precharged on l_sdr_dma_last + end // else: !if(page_hit) + end else begin // ASIC + if (~r2b_req) begin + bank_prech_page_closed = 1'b0; + b2x_req = 1'b0; + b2x_cmd_t = 2'bx; + b2r_ack = 1'b0; + b2x_addr = 13'bx; + next_bank_st = `BANK_IDLE; + end // if (~r2b_req) + else if (page_hit) begin + b2x_req = (r2b_write) ? x2b_wrok_t & xfr_ok_t : + x2b_rdok_t & xfr_ok_t; + b2x_cmd_t = (r2b_write) ? `OP_WR : `OP_RD; + b2r_ack = 1'b1; + b2x_addr = r2b_caddr; + next_bank_st = (x2b_ack) ? `BANK_IDLE : `BANK_XFR; // in case of hit, stay here till xfr sm acks + end // if (page_hit) + else begin // page_miss + b2x_req = tras_ok & x2b_pre_ok_t; + b2x_cmd_t = `OP_PRE; + b2r_ack = 1'b1; + b2x_addr = r2b_raddr & 13'hBFF; // Dont want to pre all banks! + next_bank_st = (l_sdr_dma_last) ? `BANK_PRE : (x2b_ack) ? `BANK_ACT : `BANK_PRE; // bank was precharged on l_sdr_dma_last + end // else: !if(page_hit) + end + end // case: `BANK_IDLE + + `BANK_PRE : begin + b2x_req = tras_ok & x2b_pre_ok_t; + b2x_cmd_t = `OP_PRE; + b2r_ack = 1'b0; + b2x_addr = l_raddr & 13'hBFF; // Dont want to pre all banks! + bank_prech_page_closed = 1'b0; + next_bank_st = (x2b_ack) ? `BANK_ACT : `BANK_PRE; + end // case: `BANK_PRE + + `BANK_ACT : begin + b2x_req = timer0_tc & x2b_act_ok_t; + b2x_cmd_t = `OP_ACT; + b2r_ack = 1'b0; + b2x_addr = l_raddr; + bank_prech_page_closed = 1'b0; + next_bank_st = (x2b_ack) ? `BANK_XFR : `BANK_ACT; + end // case: `BANK_ACT + + `BANK_XFR : begin + b2x_req = (l_write) ? timer0_tc & x2b_wrok_t & xfr_ok_t : + timer0_tc & x2b_rdok_t & xfr_ok_t; + b2x_cmd_t = (l_write) ? `OP_WR : `OP_RD; + b2r_ack = 1'b0; + b2x_addr = l_caddr; + bank_prech_page_closed = 1'b0; + next_bank_st = (x2b_refresh) ? `BANK_ACT : + (x2b_ack & l_sdr_dma_last) ? `BANK_DMA_LAST_PRE : + (x2b_ack) ? `BANK_IDLE : `BANK_XFR; + end // case: `BANK_XFR + + `BANK_DMA_LAST_PRE : begin + b2x_req = tras_ok & x2b_pre_ok_t; + b2x_cmd_t = `OP_PRE; + b2r_ack = 1'b0; + b2x_addr = l_raddr & 13'hBFF; // Dont want to pre all banks! + bank_prech_page_closed = 1'b1; + next_bank_st = (x2b_ack) ? `BANK_IDLE : `BANK_DMA_LAST_PRE; + end // case: `BANK_DMA_LAST_PRE + + endcase // case(bank_st) + + end // always @ (bank_st or ...) + + assign b2x_start = (bank_st == `BANK_IDLE) ? r2b_start : l_start; + + assign b2x_last = (bank_st == `BANK_IDLE) ? r2b_last : l_last; + + assign b2x_id = (bank_st == `BANK_IDLE) ? r2b_req_id : l_id; + + assign b2x_len = (bank_st == `BANK_IDLE) ? r2b_len : l_len; + + assign b2x_wrap = (bank_st == `BANK_IDLE) ? r2b_wrap : l_wrap; + +endmodule // sdr_bank_fsm diff --git a/src/peripherals/sdram/controller/sdrc_bs_convert.v b/src/peripherals/sdram/controller/sdrc_bs_convert.v new file mode 100755 index 0000000..dad6cf1 --- /dev/null +++ b/src/peripherals/sdram/controller/sdrc_bs_convert.v @@ -0,0 +1,258 @@ +/********************************************************************* + + SDRAM Controller buswidth converter + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: SDRAM Controller Buswidth converter + + This module does write/read data transalation between + application data to SDRAM bus width + + To Do: + nothing + + Author(s): + - Dinesh Annayya, dinesha@opencores.org + Version : 0.0 - 8th Jan 2012 - Initial structure + 0.2 - 2nd Feb 2012 + Improved the command pipe structure to accept up-to 4 command of different bank. + 0.3 - 6th Feb 2012 + Bug fix on read valid generation + + + + Copyright (C) 2000 Authors and OPENCORES.ORG + + This source file may be used and distributed without + restriction provided that this copyright statement is not + removed from the file and that any derivative work contains + the original copyright notice and the associated disclaimer. + + This source file is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General + Public License as published by the Free Software Foundation; + either version 2.1 of the License, or (at your option) any +later version. + + This source 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General + Public License along with this source; if not, download it + from http://www.opencores.org/lgpl.shtml + +*******************************************************************/ + +//`include "sdrc_define.v" +module sdrc_bs_convert ( + clk , + reset_n , + sdr_width , + + /* Control Signal from xfr ctrl */ + x2a_rdstart , + x2a_wrstart , + x2a_rdlast , + x2a_wrlast , + x2a_rddt , + x2a_rdok , + a2x_wrdt , + a2x_wren_n , + x2a_wrnext , + + /* Control Signal from/to to application i/f */ + app_wr_data , + app_wr_en_n , + app_wr_next , + app_last_wr , + app_rd_data , + app_rd_valid , + app_last_rd + ); + + +`define SDR_REQ_ID_W 4 + +`define SDR_RFSH_TIMER_W 12 +`define SDR_RFSH_ROW_CNT_W 3 + +// B2X Command + +`define OP_PRE 2'b00 +`define OP_ACT 2'b01 +`define OP_RD 2'b10 +`define OP_WR 2'b11 + +// SDRAM Commands (CS_N, RAS_N, CAS_N, WE_N) + +`define SDR_DESEL 4'b1111 +`define SDR_NOOP 4'b0111 +`define SDR_ACTIVATE 4'b0011 +`define SDR_READ 4'b0101 +`define SDR_WRITE 4'b0100 +`define SDR_BT 4'b0110 +`define SDR_PRECHARGE 4'b0010 +`define SDR_REFRESH 4'b0001 +`define SDR_MODE 4'b0000 + +`define ASIC 1'b1 +`define FPGA 1'b0 +`define TARGET_DESIGN `ASIC +// 12 bit subtractor is not feasibile for FPGA, so changed to 6 bits +`define REQ_BW (`TARGET_DESIGN == `FPGA) ? 6 : 12 // Request Width + +parameter APP_AW = 30; // Application Address Width +parameter APP_DW = 64; // Application Data Width +parameter APP_BW = 8; // Application Byte Width + +parameter SDR_DW = 64; // SDR Data Width +parameter SDR_BW = 8; // SDR Byte Width + +input clk ; +input reset_n ; +input [1:0] sdr_width ; // 2'b00 - 32 Bit SDR, 2'b01 - 16 Bit SDR, 2'b1x - 8 Bit + +/* Control Signal from xfr ctrl Read Transaction*/ +input x2a_rdstart ; // read start indication +input x2a_rdlast ; // read last burst access +input [SDR_DW-1:0] x2a_rddt ; +input x2a_rdok ; + +/* Control Signal from xfr ctrl Write Transaction*/ +input x2a_wrstart ; // writ start indication +input x2a_wrlast ; // write last transfer +input x2a_wrnext ; +output [SDR_DW-1:0] a2x_wrdt ; +output [SDR_BW-1:0] a2x_wren_n ; + +// Application Write Transaction +input [APP_DW-1:0] app_wr_data ; +input [APP_BW-1:0] app_wr_en_n ; +output app_wr_next ; +output app_last_wr ; // Indicate last Write Transfer for a given burst size + +// Application Read Transaction +output [APP_DW-1:0] app_rd_data ; +output app_rd_valid ; +output app_last_rd ; // Indicate last Read Transfer for a given burst size + +//---------------------------------------------- +// Local Decleration +// ---------------------------------------- + +reg [APP_DW-1:0] app_rd_data ; +reg app_rd_valid ; +reg [SDR_DW-1:0] a2x_wrdt ; +reg [SDR_BW-1:0] a2x_wren_n ; +reg app_wr_next ; + +reg [23:0] saved_rd_data ; +reg [1:0] rd_xfr_count ; +reg [1:0] wr_xfr_count ; + + +assign app_last_wr = x2a_wrlast; +assign app_last_rd = x2a_rdlast; + +always @(*) begin + if(sdr_width == 2'b00) // 32 Bit SDR Mode + begin + a2x_wrdt = app_wr_data; + a2x_wren_n = app_wr_en_n; + app_wr_next = x2a_wrnext; + app_rd_data = x2a_rddt; + app_rd_valid = x2a_rdok; + end + else if(sdr_width == 2'b01) // 16 Bit SDR Mode + begin + // Changed the address and length to match the 16 bit SDR Mode + app_wr_next = (x2a_wrnext & wr_xfr_count[0]); + app_rd_valid = (x2a_rdok & rd_xfr_count[0]); + if(wr_xfr_count[0] == 1'b1) + begin + a2x_wren_n = app_wr_en_n[3:2]; + a2x_wrdt = app_wr_data[31:16]; + end + else + begin + a2x_wren_n = app_wr_en_n[1:0]; + a2x_wrdt = app_wr_data[15:0]; + end + + app_rd_data = {x2a_rddt,saved_rd_data[15:0]}; + end else // 8 Bit SDR Mode + begin + // Changed the address and length to match the 16 bit SDR Mode + app_wr_next = (x2a_wrnext & (wr_xfr_count[1:0]== 2'b11)); + app_rd_valid = (x2a_rdok & (rd_xfr_count[1:0]== 2'b11)); + if(wr_xfr_count[1:0] == 2'b11) + begin + a2x_wren_n = app_wr_en_n[3]; + a2x_wrdt = app_wr_data[31:24]; + end + else if(wr_xfr_count[1:0] == 2'b10) + begin + a2x_wren_n = app_wr_en_n[2]; + a2x_wrdt = app_wr_data[23:16]; + end + else if(wr_xfr_count[1:0] == 2'b01) + begin + a2x_wren_n = app_wr_en_n[1]; + a2x_wrdt = app_wr_data[15:8]; + end + else begin + a2x_wren_n = app_wr_en_n[0]; + a2x_wrdt = app_wr_data[7:0]; + end + + app_rd_data = {x2a_rddt,saved_rd_data[23:0]}; + end + end + + + +always @(posedge clk) + begin + if(!reset_n) + begin + rd_xfr_count <= 8'b0; + wr_xfr_count <= 8'b0; + saved_rd_data <= 24'h0; + end + else begin + + // During Write Phase + if(x2a_wrlast) begin + wr_xfr_count <= 0; + end + else if(x2a_wrnext) begin + wr_xfr_count <= wr_xfr_count + 1'b1; + end + + // During Read Phase + if(x2a_rdlast) begin + rd_xfr_count <= 0; + end + else if(x2a_rdok) begin + rd_xfr_count <= rd_xfr_count + 1'b1; + end + + // Save Previous Data + if(x2a_rdok) begin + if(sdr_width == 2'b01) // 16 Bit SDR Mode + saved_rd_data[15:0] <= x2a_rddt; + else begin// 8 bit SDR Mode - + if(rd_xfr_count[1:0] == 2'b00) saved_rd_data[7:0] <= x2a_rddt[7:0]; + else if(rd_xfr_count[1:0] == 2'b01) saved_rd_data[15:8] <= x2a_rddt[7:0]; + else if(rd_xfr_count[1:0] == 2'b10) saved_rd_data[23:16] <= x2a_rddt[7:0]; + end + end + end +end + +endmodule // sdr_bs_convert diff --git a/src/peripherals/sdram/controller/sdrc_core.v b/src/peripherals/sdram/controller/sdrc_core.v new file mode 100755 index 0000000..8a0e495 --- /dev/null +++ b/src/peripherals/sdram/controller/sdrc_core.v @@ -0,0 +1,508 @@ +/********************************************************************* + + SDRAM Controller Core File + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: SDRAM Controller Core Module + 2 types of SDRAMs are supported, 1Mx16 2 bank, or 4Mx16 4 bank. + This block integrate following sub modules + + sdrc_bs_convert + convert the system side 32 bit into equvailent 8/16/32 SDR format + sdrc_req_gen + This module takes requests from the app, chops them to burst booundaries + if wrap=0, decodes the bank and passe the request to bank_ctl + sdrc_xfr_ctl + This module takes requests from sdr_bank_ctl, runs the transfer and + controls data flow to/from the app. At the end of the transfer it issues a + burst terminate if not at the end of a burst and another command to this + bank is not available. + + sdrc_bank_ctl + This module takes requests from sdr_req_gen, checks for page hit/miss and + issues precharge/activate commands and then passes the request to + sdr_xfr_ctl. + + + Assumption: SDRAM Pads should be placed near to this module. else + user should add a FF near the pads + + To Do: + nothing + + Author(s): + - Dinesh Annayya, dinesha@opencores.org + Version : 0.0 - 8th Jan 2012 + Initial version with 16/32 Bit SDRAM Support + : 0.1 - 24th Jan 2012 + 8 Bit SDRAM Support is added + 0.2 - 2nd Feb 2012 + Improved the command pipe structure to accept up-to + 4 command of different bank. + 0.3 - 7th Feb 2012 + Bug fix for parameter defination for request length has changed from 9 to 12 + 0.4 - 26th April 2013 + SDRAM Address Bit is Extended by 12 bit to 13 bit to support higher SDRAM + + + Copyright (C) 2000 Authors and OPENCORES.ORG + + This source file may be used and distributed without + restriction provided that this copyright statement is not + removed from the file and that any derivative work contains + the original copyright notice and the associated disclaimer. + + This source file is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General + Public License as published by the Free Software Foundation; + either version 2.1 of the License, or (at your option) any +later version. + + This source 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General + Public License along with this source; if not, download it + from http://www.opencores.org/lgpl.shtml + +*******************************************************************/ + + + +module sdrc_core + ( + clk, + pad_clk, + reset_n, + sdr_width, + cfg_colbits, + + /* Request from app */ + app_req, // Transfer Request + app_req_addr, // SDRAM Address + app_req_len, // Burst Length (in 16 bit words) + app_req_wrap, // Wrap mode request (xfr_len = 4) + app_req_wr_n, // 0 => Write request, 1 => read req + app_req_ack, // Request has been accepted + cfg_req_depth, //how many req. buffer should hold + + app_wr_data, + app_wr_en_n, + app_last_wr, + + app_rd_data, + app_rd_valid, + app_last_rd, + app_wr_next_req, + sdr_init_done, + app_req_dma_last, + + /* Interface to SDRAMs */ + sdr_cs_n, + sdr_cke, + sdr_ras_n, + sdr_cas_n, + sdr_we_n, + sdr_dqm, + sdr_ba, + sdr_addr, + pad_sdr_din, + sdr_dout, + sdr_den_n, + + /* Parameters */ + cfg_sdr_en, + cfg_sdr_mode_reg, + cfg_sdr_tras_d, + cfg_sdr_trp_d, + cfg_sdr_trcd_d, + cfg_sdr_cas, + cfg_sdr_trcar_d, + cfg_sdr_twr_d, + cfg_sdr_rfsh, + cfg_sdr_rfmax); + + +`define SDR_REQ_ID_W 4 + +`define SDR_RFSH_TIMER_W 12 +`define SDR_RFSH_ROW_CNT_W 3 + +// B2X Command + +`define OP_PRE 2'b00 +`define OP_ACT 2'b01 +`define OP_RD 2'b10 +`define OP_WR 2'b11 + +// SDRAM Commands (CS_N, RAS_N, CAS_N, WE_N) + +`define SDR_DESEL 4'b1111 +`define SDR_NOOP 4'b0111 +`define SDR_ACTIVATE 4'b0011 +`define SDR_READ 4'b0101 +`define SDR_WRITE 4'b0100 +`define SDR_BT 4'b0110 +`define SDR_PRECHARGE 4'b0010 +`define SDR_REFRESH 4'b0001 +`define SDR_MODE 4'b0000 + +`define ASIC 1'b1 +`define FPGA 1'b0 +`define TARGET_DESIGN `ASIC +// 12 bit subtractor is not feasibile for FPGA, so changed to 6 bits +`define REQ_BW (`TARGET_DESIGN == `FPGA) ? 6 : 12 // Request Width + +parameter APP_AW = 26; // Application Address Width +parameter APP_DW = 64; // Application Data Width +parameter APP_BW = 8; // Application Byte Width +parameter APP_RW = 9; // Application Request Width + +parameter SDR_DW = 64; // SDR Data Width +parameter SDR_BW = 8; // SDR Byte Width + + +//----------------------------------------------- +// Global Variable +// ---------------------------------------------- +input clk ; // SDRAM Clock +input pad_clk ; // SDRAM Clock from Pad, used for registering Read Data +input reset_n ; // Reset Signal +input [1:0] sdr_width ; // 2'b00 - 32 Bit SDR, 2'b01 - 16 Bit SDR, 2'b1x - 8 Bit +input [1:0] cfg_colbits ; // 2'b00 - 8 Bit column address, 2'b01 - 9 Bit, 10 - 10 bit, 11 - 11Bits + + +//------------------------------------------------ +// Request from app +//------------------------------------------------ +input app_req ; // Application Request +input [APP_AW-1:0] app_req_addr ; // Address +input app_req_wr_n ; // 0 - Write, 1 - Read +input app_req_wrap ; // Address Wrap +output app_req_ack ; // Application Request Ack + +input [APP_DW-1:0] app_wr_data ; // Write Data +output app_wr_next_req ; // Next Write Data Request +input [APP_BW-1:0] app_wr_en_n ; // Byte wise Write Enable +output app_last_wr ; // Last Write trannsfer of a given Burst +output [APP_DW-1:0] app_rd_data ; // Read Data +output app_rd_valid ; // Read Valid +output app_last_rd ; // Last Read Transfer of a given Burst + +//------------------------------------------------ +// Interface to SDRAMs +//------------------------------------------------ +output sdr_cke ; // SDRAM CKE +output sdr_cs_n ; // SDRAM Chip Select +output sdr_ras_n ; // SDRAM ras +output sdr_cas_n ; // SDRAM cas +output sdr_we_n ; // SDRAM write enable +output [SDR_BW-1:0] sdr_dqm ; // SDRAM Data Mask +output [1:0] sdr_ba ; // SDRAM Bank Enable +output [12:0] sdr_addr ; // SDRAM Address +input [SDR_DW-1:0] pad_sdr_din ; // SDRA Data Input +output [SDR_DW-1:0] sdr_dout ; // SDRAM Data Output +output [SDR_BW-1:0] sdr_den_n ; // SDRAM Data Output enable + +//------------------------------------------------ +// Configuration Parameter +//------------------------------------------------ +output sdr_init_done ; // Indicate SDRAM Initialisation Done +input [3:0] cfg_sdr_tras_d ; // Active to precharge delay +input [3:0] cfg_sdr_trp_d ; // Precharge to active delay +input [3:0] cfg_sdr_trcd_d ; // Active to R/W delay +input cfg_sdr_en ; // Enable SDRAM controller +input [1:0] cfg_req_depth ; // Maximum Request accepted by SDRAM controller +input [APP_RW-1:0] app_req_len ; // Application Burst Request length in 32 bit +input [12:0] cfg_sdr_mode_reg ; +input [2:0] cfg_sdr_cas ; // SDRAM CAS Latency +input [3:0] cfg_sdr_trcar_d ; // Auto-refresh period +input [3:0] cfg_sdr_twr_d ; // Write recovery delay +input [`SDR_RFSH_TIMER_W-1 : 0] cfg_sdr_rfsh; +input [`SDR_RFSH_ROW_CNT_W -1 : 0] cfg_sdr_rfmax; +input app_req_dma_last; // this signal should close the bank + +/****************************************************************************/ +// Internal Nets + +// SDR_REQ_GEN +wire [`SDR_REQ_ID_W-1:0]r2b_req_id; +wire [1:0] r2b_ba; +wire [12:0] r2b_raddr; +wire [12:0] r2b_caddr; +wire [`REQ_BW-1:0] r2b_len; + +// SDR BANK CTL +wire [`SDR_REQ_ID_W-1:0]b2x_id; +wire [1:0] b2x_ba; +wire [12:0] b2x_addr; +wire [`REQ_BW-1:0] b2x_len; +wire [1:0] b2x_cmd; + +// SDR_XFR_CTL +wire [3:0] x2b_pre_ok; +wire [`SDR_REQ_ID_W-1:0]xfr_id; +wire [APP_DW-1:0] app_rd_data; +wire sdr_cs_n, sdr_cke, sdr_ras_n, sdr_cas_n, sdr_we_n; +wire [SDR_BW-1:0] sdr_dqm; +wire [1:0] sdr_ba; +wire [12:0] sdr_addr; +wire [SDR_DW-1:0] sdr_dout; +wire [SDR_DW-1:0] sdr_dout_int; +wire [SDR_BW-1:0] sdr_den_n; +wire [SDR_BW-1:0] sdr_den_n_int; + +wire [1:0] xfr_bank_sel; + +wire [APP_AW-1:0] app_req_addr; +wire [APP_RW-1:0] app_req_len; + +wire [APP_DW-1:0] app_wr_data; +wire [SDR_DW-1:0] a2x_wrdt ; +wire [APP_BW-1:0] app_wr_en_n; +wire [SDR_BW-1:0] a2x_wren_n; + +//wire [31:0] app_rd_data; +wire [SDR_DW-1:0] x2a_rddt; + + +// synopsys translate_off + wire [3:0] sdr_cmd; + assign sdr_cmd = {sdr_cs_n, sdr_ras_n, sdr_cas_n, sdr_we_n}; +// synopsys translate_on + +assign sdr_den_n = sdr_den_n_int ; +assign sdr_dout = sdr_dout_int ; + + +// To meet the timing at read path, read data is registered w.r.t pad_sdram_clock and register back to sdram_clk +// assumption, pad_sdram_clk is synhronous and delayed clock of sdram_clk. +// register w.r.t pad sdram clk +reg [SDR_DW-1:0] pad_sdr_din1; +reg [SDR_DW-1:0] pad_sdr_din2; +always@(posedge pad_clk) begin + pad_sdr_din1 <= pad_sdr_din; +end + +always@(posedge clk) begin + pad_sdr_din2 <= pad_sdr_din1; +end + + + /****************************************************************************/ + // Instantiate sdr_req_gen + // This module takes requests from the app, chops them to burst booundaries + // if wrap=0, decodes the bank and passe the request to bank_ctl + +sdrc_req_gen #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_req_gen ( + .clk (clk ), + .reset_n (reset_n ), + .cfg_colbits (cfg_colbits ), + .sdr_width (sdr_width ), + + /* Req to xfr_ctl */ + .r2x_idle (r2x_idle ), + + /* Request from app */ + .req (app_req ), + .req_id (4'b0 ), + .req_addr (app_req_addr ), + .req_len (app_req_len ), + .req_wrap (app_req_wrap ), + .req_wr_n (app_req_wr_n ), + .req_ack (app_req_ack ), + + /* Req to bank_ctl */ + .r2b_req (r2b_req ), + .r2b_req_id (r2b_req_id ), + .r2b_start (r2b_start ), + .r2b_last (r2b_last ), + .r2b_wrap (r2b_wrap ), + .r2b_ba (r2b_ba ), + .r2b_raddr (r2b_raddr ), + .r2b_caddr (r2b_caddr ), + .r2b_len (r2b_len ), + .r2b_write (r2b_write ), + .b2r_ack (b2r_ack ), + .b2r_arb_ok (b2r_arb_ok ) + ); + + /****************************************************************************/ + // Instantiate sdr_bank_ctl + // This module takes requests from sdr_req_gen, checks for page hit/miss and + // issues precharge/activate commands and then passes the request to + // sdr_xfr_ctl. + +sdrc_bank_ctl #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_bank_ctl ( + .clk (clk ), + .reset_n (reset_n ), + .a2b_req_depth (cfg_req_depth ), + + /* Req from req_gen */ + .r2b_req (r2b_req ), + .r2b_req_id (r2b_req_id ), + .r2b_start (r2b_start ), + .r2b_last (r2b_last ), + .r2b_wrap (r2b_wrap ), + .r2b_ba (r2b_ba ), + .r2b_raddr (r2b_raddr ), + .r2b_caddr (r2b_caddr ), + .r2b_len (r2b_len ), + .r2b_write (r2b_write ), + .b2r_arb_ok (b2r_arb_ok ), + .b2r_ack (b2r_ack ), + + /* Transfer request to xfr_ctl */ + .b2x_idle (b2x_idle ), + .b2x_req (b2x_req ), + .b2x_start (b2x_start ), + .b2x_last (b2x_last ), + .b2x_wrap (b2x_wrap ), + .b2x_id (b2x_id ), + .b2x_ba (b2x_ba ), + .b2x_addr (b2x_addr ), + .b2x_len (b2x_len ), + .b2x_cmd (b2x_cmd ), + .x2b_ack (x2b_ack ), + + /* Status from xfr_ctl */ + .b2x_tras_ok (b2x_tras_ok ), + .x2b_refresh (x2b_refresh ), + .x2b_pre_ok (x2b_pre_ok ), + .x2b_act_ok (x2b_act_ok ), + .x2b_rdok (x2b_rdok ), + .x2b_wrok (x2b_wrok ), + + /* for generate cuurent xfr address msb */ + .sdr_req_norm_dma_last(app_req_dma_last), + .xfr_bank_sel (xfr_bank_sel ), + + /* SDRAM Timing */ + .tras_delay (cfg_sdr_tras_d ), + .trp_delay (cfg_sdr_trp_d ), + .trcd_delay (cfg_sdr_trcd_d ) + ); + + /****************************************************************************/ + // Instantiate sdr_xfr_ctl + // This module takes requests from sdr_bank_ctl, runs the transfer and + // controls data flow to/from the app. At the end of the transfer it issues a + // burst terminate if not at the end of a burst and another command to this + // bank is not available. + +sdrc_xfr_ctl #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_xfr_ctl ( + .clk (clk ), + .reset_n (reset_n ), + + /* Transfer request from bank_ctl */ + .r2x_idle (r2x_idle ), + .b2x_idle (b2x_idle ), + .b2x_req (b2x_req ), + .b2x_start (b2x_start ), + .b2x_last (b2x_last ), + .b2x_wrap (b2x_wrap ), + .b2x_id (b2x_id ), + .b2x_ba (b2x_ba ), + .b2x_addr (b2x_addr ), + .b2x_len (b2x_len ), + .b2x_cmd (b2x_cmd ), + .x2b_ack (x2b_ack ), + + /* Status to bank_ctl, req_gen */ + .b2x_tras_ok (b2x_tras_ok ), + .x2b_refresh (x2b_refresh ), + .x2b_pre_ok (x2b_pre_ok ), + .x2b_act_ok (x2b_act_ok ), + .x2b_rdok (x2b_rdok ), + .x2b_wrok (x2b_wrok ), + + /* SDRAM I/O */ + .sdr_cs_n (sdr_cs_n ), + .sdr_cke (sdr_cke ), + .sdr_ras_n (sdr_ras_n ), + .sdr_cas_n (sdr_cas_n ), + .sdr_we_n (sdr_we_n ), + .sdr_dqm (sdr_dqm ), + .sdr_ba (sdr_ba ), + .sdr_addr (sdr_addr ), + .sdr_din (pad_sdr_din2 ), + .sdr_dout (sdr_dout_int ), + .sdr_den_n (sdr_den_n_int ), + /* Data Flow to the app */ + .x2a_rdstart (x2a_rdstart ), + .x2a_wrstart (x2a_wrstart ), + .x2a_id (xfr_id ), + .x2a_rdlast (x2a_rdlast ), + .x2a_wrlast (x2a_wrlast ), + .a2x_wrdt (a2x_wrdt ), + .a2x_wren_n (a2x_wren_n ), + .x2a_wrnext (x2a_wrnext ), + .x2a_rddt (x2a_rddt ), + .x2a_rdok (x2a_rdok ), + .sdr_init_done (sdr_init_done ), + + /* SDRAM Parameters */ + .sdram_enable (cfg_sdr_en ), + .sdram_mode_reg (cfg_sdr_mode_reg ), + + /* current xfr bank */ + .xfr_bank_sel (xfr_bank_sel ), + + /* SDRAM Timing */ + .cas_latency (cfg_sdr_cas ), + .trp_delay (cfg_sdr_trp_d ), + .trcar_delay (cfg_sdr_trcar_d ), + .twr_delay (cfg_sdr_twr_d ), + .rfsh_time (cfg_sdr_rfsh ), + .rfsh_rmax (cfg_sdr_rfmax ) + ); + + /****************************************************************************/ + // Instantiate sdr_bs_convert + // This model handle the bus with transaltion from application layer to + // 8/16/32 SDRAM Memory format + // During Write Phase, this block split the data as per SDRAM Width + // During Read Phase, This block does the re-packing based on SDRAM + // Width + //--------------------------------------------------------------------------- +sdrc_bs_convert #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_bs_convert ( + .clk (clk ), + .reset_n (reset_n ), + .sdr_width (sdr_width ), + + /* Control Signal from xfr ctrl */ + // Read Interface Inputs + .x2a_rdstart (x2a_rdstart ), + .x2a_rdlast (x2a_rdlast ), + .x2a_rdok (x2a_rdok ), + // Read Interface outputs + .x2a_rddt (x2a_rddt ), + + // Write Interface, Inputs + .x2a_wrstart (x2a_wrstart ), + .x2a_wrlast (x2a_wrlast ), + .x2a_wrnext (x2a_wrnext ), + + // Write Interface, Outputs + .a2x_wrdt (a2x_wrdt ), + .a2x_wren_n (a2x_wren_n ), + + /* Control Signal from sdrc_bank_ctl */ + + /* Control Signal from/to to application i/f */ + .app_wr_data (app_wr_data ), + .app_wr_en_n (app_wr_en_n ), + .app_wr_next (app_wr_next_req ), + .app_last_wr (app_last_wr ), + .app_rd_data (app_rd_data ), + .app_rd_valid (app_rd_valid ), + .app_last_rd (app_last_rd ) + + ); + +endmodule // sdrc_core diff --git a/src/peripherals/sdram/controller/sdrc_req_gen.v b/src/peripherals/sdram/controller/sdrc_req_gen.v new file mode 100755 index 0000000..9ca80db --- /dev/null +++ b/src/peripherals/sdram/controller/sdrc_req_gen.v @@ -0,0 +1,371 @@ +/********************************************************************* + + SDRAM Controller Request Generation + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: SDRAM Controller Reguest Generation + + Address Generation Based on cfg_colbits + cfg_colbits= 2'b00 + Address[7:0] - Column Address + Address[9:8] - Bank Address + Address[22:10] - Row Address + cfg_colbits= 2'b01 + Address[8:0] - Column Address + Address[10:9] - Bank Address + Address[23:11] - Row Address + cfg_colbits= 2'b10 + Address[9:0] - Column Address + Address[11:10] - Bank Address + Address[24:12] - Row Address + cfg_colbits= 2'b11 + Address[10:0] - Column Address + Address[12:11] - Bank Address + Address[25:13] - Row Address + + The SDRAMs are operated in 4 beat burst mode. + + If Wrap = 0; + If the current burst cross the page boundary, then this block split the request + into two coressponding change in address and request length + + if the current burst cross the page boundar. + This module takes requests from the memory controller, + chops them to page boundaries if wrap=0, + and passes the request to bank_ctl + + Note: With Wrap = 0, each request from Application layer will be splited into two request, + if the current burst cross the page boundary. + + To Do: + nothing + + Author(s): + - Dinesh Annayya, dinesha@opencores.org + Version : 0.0 - 8th Jan 2012 + 0.1 - 5th Feb 2012, column/row/bank address are register to improve the timing issue in FPGA synthesis + + + + Copyright (C) 2000 Authors and OPENCORES.ORG + + This source file may be used and distributed without + restriction provided that this copyright statement is not + removed from the file and that any derivative work contains + the original copyright notice and the associated disclaimer. + + This source file is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General + Public License as published by the Free Software Foundation; + either version 2.1 of the License, or (at your option) any +later version. + + This source 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General + Public License along with this source; if not, download it + from http://www.opencores.org/lgpl.shtml + +*******************************************************************/ + + + +module sdrc_req_gen (clk, + reset_n, + cfg_colbits, + sdr_width, + + /* Request from app */ + req, // Transfer Request + req_id, // ID for this transfer + req_addr, // SDRAM Address + req_len, // Burst Length (in 32 bit words) + req_wrap, // Wrap mode request (xfr_len = 4) + req_wr_n, // 0 => Write request, 1 => read req + req_ack, // Request has been accepted + + /* Req to xfr_ctl */ + r2x_idle, + + /* Req to bank_ctl */ + r2b_req, // request + r2b_req_id, // ID + r2b_start, // First chunk of burst + r2b_last, // Last chunk of burst + r2b_wrap, // Wrap Mode + r2b_ba, // bank address + r2b_raddr, // row address + r2b_caddr, // col address + r2b_len, // length + r2b_write, // write request + b2r_ack, + b2r_arb_ok + ); + + +`define SDR_REQ_ID_W 4 + +`define SDR_RFSH_TIMER_W 12 +`define SDR_RFSH_ROW_CNT_W 3 + +// B2X Command + +`define OP_PRE 2'b00 +`define OP_ACT 2'b01 +`define OP_RD 2'b10 +`define OP_WR 2'b11 + +// SDRAM Commands (CS_N, RAS_N, CAS_N, WE_N) + +`define SDR_DESEL 4'b1111 +`define SDR_NOOP 4'b0111 +`define SDR_ACTIVATE 4'b0011 +`define SDR_READ 4'b0101 +`define SDR_WRITE 4'b0100 +`define SDR_BT 4'b0110 +`define SDR_PRECHARGE 4'b0010 +`define SDR_REFRESH 4'b0001 +`define SDR_MODE 4'b0000 + +`define ASIC 1'b1 +`define FPGA 1'b0 +`define TARGET_DESIGN `ASIC +// 12 bit subtractor is not feasibile for FPGA, so changed to 6 bits +`define REQ_BW (`TARGET_DESIGN == `FPGA) ? 6 : 12 // Request Width + +parameter APP_AW = 26; // Application Address Width +parameter APP_DW = 64; // Application Data Width +parameter APP_BW = 8; // Application Byte Width +parameter APP_RW = 9; // Application Request Width + +parameter SDR_DW = 64; // SDR Data Width +parameter SDR_BW = 8; // SDR Byte Width + + +input clk ; +input reset_n ; +input [1:0] cfg_colbits ; // 2'b00 - 8 Bit column address, 2'b01 - 9 Bit, 10 - 10 bit, 11 - 11Bits + +/* Request from app */ +input req ; // Request +input [`SDR_REQ_ID_W-1:0] req_id ; // Request ID +input [APP_AW-1:0] req_addr ; // Request Address +input [APP_RW-1:0] req_len ; // Request length +input req_wr_n ; // 0 -Write, 1 - Read +input req_wrap ; // 1 - Wrap the Address on page boundary +output req_ack ; // Request Ack + +/* Req to bank_ctl */ +output r2x_idle ; +output r2b_req ; // Request +output r2b_start ; // First Junk of the Burst Access +output r2b_last ; // Last Junk of the Burst Access +output r2b_write ; // 1 - Write, 0 - Read +output r2b_wrap ; // 1 - Wrap the Address at the page boundary. +output [`SDR_REQ_ID_W-1:0] r2b_req_id; +output [1:0] r2b_ba ; // Bank Address +output [12:0] r2b_raddr ; // Row Address +output [12:0] r2b_caddr ; // Column Address +output [`REQ_BW-1:0] r2b_len ; // Burst Length +input b2r_ack ; // Request Ack +input b2r_arb_ok ; // Bank controller fifo is not full and ready to accept the command +// +input [1:0] sdr_width; // 2'b00 - 32 Bit, 2'b01 - 16 Bit, 2'b1x - 8Bit + + + /****************************************************************************/ + // Internal Nets + + `define REQ_IDLE 2'b00 + `define REQ_ACTIVE 2'b01 + `define REQ_PAGE_WRAP 2'b10 + + reg [1:0] req_st, next_req_st; + reg r2x_idle, req_ack, r2b_req, r2b_start, + r2b_write, req_idle, req_ld, lcl_wrap; + reg [`SDR_REQ_ID_W-1:0] r2b_req_id; + reg [`REQ_BW-1:0] lcl_req_len; + + wire r2b_last, page_ovflw; + reg page_ovflw_r; + wire [`REQ_BW-1:0] r2b_len, next_req_len; + wire [12:0] max_r2b_len; + reg [12:0] max_r2b_len_r; + + reg [1:0] r2b_ba; + reg [12:0] r2b_raddr; + reg [12:0] r2b_caddr; + + reg [APP_AW-1:0] curr_sdr_addr ; + wire [APP_AW-1:0] next_sdr_addr ; + + +//-------------------------------------------------------------------- +// Generate the internal Adress and Burst length Based on sdram width +//-------------------------------------------------------------------- +reg [APP_AW:0] req_addr_int; +reg [APP_RW-1:0] req_len_int; + +always @(*) begin + if(sdr_width == 2'b00) begin // 32 Bit SDR Mode + req_addr_int = {1'b0,req_addr}; + req_len_int = req_len; + end else if(sdr_width == 2'b01) begin // 16 Bit SDR Mode + // Changed the address and length to match the 16 bit SDR Mode + req_addr_int = {req_addr,1'b0}; + req_len_int = {req_len,1'b0}; + end else begin // 8 Bit SDR Mode + // Changed the address and length to match the 16 bit SDR Mode + req_addr_int = {req_addr,2'b0}; + req_len_int = {req_len,2'b0}; + end +end + + // + // Identify the page over flow. + // Find the Maximum Burst length allowed from the selected column + // address, If the requested burst length is more than the allowed Maximum + // burst length, then we need to handle the bank cross over case and we + // need to split the reuest. + // + assign max_r2b_len = (cfg_colbits == 2'b00) ? (12'h100 - {4'b0, req_addr_int[7:0]}) : + (cfg_colbits == 2'b01) ? (12'h200 - {3'b0, req_addr_int[8:0]}) : + (cfg_colbits == 2'b10) ? (12'h400 - {2'b0, req_addr_int[9:0]}) : (12'h800 - {1'b0, req_addr_int[10:0]}); + + + // If the wrap = 0 and current application burst length is crossing the page boundary, + // then request will be split into two with corresponding change in request address and request length. + // + // If the wrap = 0 and current burst length is not crossing the page boundary, + // then request from application layer will be transparently passed on the bank control block. + + // + // if the wrap = 1, then this block will not modify the request address and length. + // The wrapping functionality will be handle by the bank control module and + // column address will rewind back as follows XX -> FF ? 00 ? 1 + // + // Note: With Wrap = 0, each request from Application layer will be spilited into two request, + // if the current burst cross the page boundary. + assign page_ovflw = ({1'b0, req_len_int} > max_r2b_len) ? (req_ack && ~req_wrap) : 1'b0; // vish change + + assign r2b_len = r2b_start ? ((page_ovflw_r) ? max_r2b_len_r : lcl_req_len) : + lcl_req_len; + + assign next_req_len = lcl_req_len - r2b_len; + + assign next_sdr_addr = curr_sdr_addr + r2b_len; + + + assign r2b_wrap = lcl_wrap; + + assign r2b_last = (r2b_start & !page_ovflw_r) | (req_st == `REQ_PAGE_WRAP); +// +// +// + always @ (posedge clk) begin + + page_ovflw_r <= (req_ack) ? page_ovflw: 'h0; + + max_r2b_len_r <= (req_ack) ? max_r2b_len: 'h0; + r2b_start <= (req_ack) ? 1'b1 : + (b2r_ack) ? 1'b0 : r2b_start; + + r2b_write <= (req_ack) ? ~req_wr_n : r2b_write; + + r2b_req_id <= (req_ack) ? req_id : r2b_req_id; + + lcl_wrap <= (req_ack) ? req_wrap : lcl_wrap; + + lcl_req_len <= (req_ack) ? req_len_int : + (req_ld) ? next_req_len : lcl_req_len; + + curr_sdr_addr <= (req_ack) ? req_addr_int : + (req_ld) ? next_sdr_addr : curr_sdr_addr; + + end // always @ (posedge clk) + + always @ (*) begin + r2x_idle = 1'b0; + req_idle = 1'b0; + req_ack = 1'b0; + req_ld = 1'b0; + r2b_req = 1'b0; + next_req_st = `REQ_IDLE; + + case (req_st) // synopsys full_case parallel_case + + `REQ_IDLE : begin + r2x_idle = ~req; + req_idle = 1'b1; + req_ack = req & b2r_arb_ok; + req_ld = 1'b0; + r2b_req = 1'b0; + next_req_st = (req & b2r_arb_ok) ? `REQ_ACTIVE : `REQ_IDLE; + end // case: `REQ_IDLE + + `REQ_ACTIVE : begin + r2x_idle = 1'b0; + req_idle = 1'b0; + req_ack = 1'b0; + req_ld = b2r_ack; + r2b_req = 1'b1; // req_gen to bank_req + next_req_st = (b2r_ack ) ? ((page_ovflw_r) ? `REQ_PAGE_WRAP :`REQ_IDLE) : `REQ_ACTIVE; + end // case: `REQ_ACTIVE + `REQ_PAGE_WRAP : begin + r2x_idle = 1'b0; + req_idle = 1'b0; + req_ack = 1'b0; + req_ld = b2r_ack; + r2b_req = 1'b1; // req_gen to bank_req + next_req_st = (b2r_ack) ? `REQ_IDLE : `REQ_PAGE_WRAP; + end // case: `REQ_ACTIVE + + endcase // case(req_st) + + end // always @ (req_st or ....) + + always @ (posedge clk) + if (~reset_n) begin + req_st <= `REQ_IDLE; + end // if (~reset_n) + else begin + req_st <= next_req_st; + end // else: !if(~reset_n) +// +// addrs bits for the bank, row and column +// +// Register row/column/bank to improve fpga timing issue +wire [APP_AW-1:0] map_address ; + +assign map_address = (req_ack) ? req_addr_int : + (req_ld) ? next_sdr_addr : curr_sdr_addr; + +always @ (posedge clk) begin +// Bank Bits are always - 2 Bits + r2b_ba <= (cfg_colbits == 2'b00) ? {map_address[9:8]} : + (cfg_colbits == 2'b01) ? {map_address[10:9]} : + (cfg_colbits == 2'b10) ? {map_address[11:10]} : map_address[12:11]; + +/******************** +* Colbits Mapping: +* 2'b00 - 8 Bit +* 2'b01 - 16 Bit +* 2'b10 - 10 Bit +* 2'b11 - 11 Bits +************************/ + r2b_caddr <= (cfg_colbits == 2'b00) ? {5'b0, map_address[7:0]} : + (cfg_colbits == 2'b01) ? {4'b0, map_address[8:0]} : + (cfg_colbits == 2'b10) ? {3'b0, map_address[9:0]} : {2'b0, map_address[10:0]}; + + r2b_raddr <= (cfg_colbits == 2'b00) ? map_address[22:10] : + (cfg_colbits == 2'b01) ? map_address[23:11] : + (cfg_colbits == 2'b10) ? map_address[24:12] : map_address[25:13]; +end + +endmodule // sdr_req_gen diff --git a/src/peripherals/sdram/controller/sdrc_top.v b/src/peripherals/sdram/controller/sdrc_top.v new file mode 100755 index 0000000..fc2e032 --- /dev/null +++ b/src/peripherals/sdram/controller/sdrc_top.v @@ -0,0 +1,325 @@ +/********************************************************************* + + SDRAM Controller top File + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: SDRAM Controller Top Module. + Support 81/6/32 Bit SDRAM. + Column Address is Programmable + Bank Bit are 2 Bit + Row Bits are 12 Bits + + This block integrate following sub modules + + sdrc_core + SDRAM Controller file + wb2sdrc + This module transalate the bus protocl from wishbone to custome + sdram controller + + To Do: + nothing + + Author(s): Dinesh Annayya, dinesha@opencores.org + Version : 0.0 - 8th Jan 2012 + Initial version with 16/32 Bit SDRAM Support + : 0.1 - 24th Jan 2012 + 8 Bit SDRAM Support is added + 0.2 - 31st Jan 2012 + sdram_dq and sdram_pad_clk are internally generated + 0.3 - 26th April 2013 + Sdram Address witdh is increased from 12 to 13bits + + + Copyright (C) 2000 Authors and OPENCORES.ORG + + This source file may be used and distributed without + restriction provided that this copyright statement is not + removed from the file and that any derivative work contains + the original copyright notice and the associated disclaimer. + + This source file is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General + Public License as published by the Free Software Foundation; + either version 2.1 of the License, or (at your option) any +later version. + + This source 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General + Public License along with this source; if not, download it + from http://www.opencores.org/lgpl.shtml + +*******************************************************************/ + + +`timescale 1ns/1ps +module sdrc_top + ( + cfg_sdr_width , + cfg_colbits , + + // Input to sdram ctrl + app_req , + app_req_addr , + app_req_len , + app_req_wr_n , + app_req_wrap , + app_req_ack , +// app_busy_n , + app_wr_en_n , + app_wr_next_req, + app_rd_valid , + app_last_rd , + app_last_wr, + app_wr_data , + app_rd_data , + delay_config_reg2, + + /* Interface to SDRAMs */ + sdram_clk , + sdram_resetn , + sdr_cs_n , + sdr_cke , + sdr_ras_n , + sdr_cas_n , + sdr_we_n , + sdr_dqm , + sdr_ba , + sdr_addr , + pad_sdr_din , // SDRA Data Input + sdr_dout , // SDRAM Data Output + sdr_den_n , // SDRAM Data Output enable + + /* Parameters */ + sdr_init_done , + cfg_req_depth , //how many req. buffer should hold + cfg_sdr_en , + cfg_sdr_mode_reg , + cfg_sdr_tras_d , + cfg_sdr_trp_d , + cfg_sdr_trcd_d , + cfg_sdr_cas , + cfg_sdr_trcar_d , + cfg_sdr_twr_d , + cfg_sdr_rfsh , + cfg_sdr_rfmax + ); + + `define SDR_REQ_ID_W 4 + +`define SDR_RFSH_TIMER_W 12 +`define SDR_RFSH_ROW_CNT_W 3 + +// B2X Command + +`define OP_PRE 2'b00 +`define OP_ACT 2'b01 +`define OP_RD 2'b10 +`define OP_WR 2'b11 + +// SDRAM Commands (CS_N, RAS_N, CAS_N, WE_N) + +`define SDR_DESEL 4'b1111 +`define SDR_NOOP 4'b0111 +`define SDR_ACTIVATE 4'b0011 +`define SDR_READ 4'b0101 +`define SDR_WRITE 4'b0100 +`define SDR_BT 4'b0110 +`define SDR_PRECHARGE 4'b0010 +`define SDR_REFRESH 4'b0001 +`define SDR_MODE 4'b0000 + +`define ASIC 1'b1 +`define FPGA 1'b0 +`define TARGET_DESIGN `ASIC +// 12 bit subtractor is not feasibile for FPGA, so changed to 6 bits +`define REQ_BW (`TARGET_DESIGN == `FPGA) ? 6 : 12 // Request Width + +parameter APP_AW = 26; // Application Address Width +parameter APP_DW = 64; // Application Data Width +parameter APP_BW = 8; // Application Byte Width +parameter APP_RW = 9; // Application Request Width + +parameter SDR_DW = 64; // SDR Data Width +parameter SDR_BW = 8; // SDR Byte Width + +parameter dw = 64; // data width +parameter tw = 8; // tag id width +parameter bl = 9; // burst_lenght_width + +//----------------------------------------------- +// Global Variable +// ---------------------------------------------- +input sdram_clk ; // SDRAM Clock +input sdram_resetn ; // Reset Signal +input [1:0] cfg_sdr_width ; // 2'b00 - 32 Bit SDR, 2'b01 - 16 Bit SDR, 2'b1x - 8 Bit +input [1:0] cfg_colbits ; // 2'b00 - 8 Bit column address, + // 2'b01 - 9 Bit, 10 - 10 bit, 11 - 11Bits + +//-------------------------------------- +// Wish Bone Interface +// ------------------------------------- +//input wb_rst_i ; +//input wb_clk_i ; +// +//input wb_stb_i ; +//output wb_ack_o ; +//input [APP_AW-1:0] wb_addr_i ; +//input wb_we_i ; // 1 - Write, 0 - Read +//input [dw-1:0] wb_dat_i ; +//input [dw/8-1:0] wb_sel_i ; // Byte enable +//output [dw-1:0] wb_dat_o ; +//input wb_cyc_i ; +//input [2:0] wb_cti_i ; + +//------------------------------------------------ +// Interface to SDRAMs +//------------------------------------------------ +output sdr_cke ; // SDRAM CKE +output sdr_cs_n ; // SDRAM Chip Select +output sdr_ras_n ; // SDRAM ras +output sdr_cas_n ; // SDRAM cas +output sdr_we_n ; // SDRAM write enable +output [SDR_BW-1:0] sdr_dqm ; // SDRAM Data Mask +output [1:0] sdr_ba ; // SDRAM Bank Enable +output [12:0] sdr_addr ; // SDRAM Address +input [SDR_DW-1:0] pad_sdr_din ; // SDRA Data Input +output [SDR_DW-1:0] sdr_dout ; // SDRAM Data Output +output [SDR_BW-1:0] sdr_den_n ; // SDRAM Data Output enable +//------------------------------------------------ +// Configuration Parameter // vis: changed input and output pins to wire +//------------------------------------------------ + +output sdr_init_done ; // Indicate SDRAM Initialisation Done +input [3:0] cfg_sdr_tras_d ; // Active to precharge delay +input [3:0] cfg_sdr_trp_d ; // Precharge to active delay +input [3:0] cfg_sdr_trcd_d ; // Active to R/W delay +input cfg_sdr_en ; // Enable SDRAM controller +input [1:0] cfg_req_depth ; // Maximum Request accepted by SDRAM controller +input [12:0] cfg_sdr_mode_reg ; +input [2:0] cfg_sdr_cas ; // SDRAM CAS Latency +input [3:0] cfg_sdr_trcar_d ; // Auto-refresh period +input [3:0] cfg_sdr_twr_d ; // Write recovery delay +input [`SDR_RFSH_TIMER_W-1 : 0] cfg_sdr_rfsh; +input [`SDR_RFSH_ROW_CNT_W -1 : 0] cfg_sdr_rfmax; + + +/* +assign cfg_req_depth = 2'h3; //how many req. buffer should hold +assign cfg_sdr_en = 1'b1; +assign cfg_sdr_mode_reg = 13'h033; +assign cfg_sdr_tras_d = 4'h4; +assign cfg_sdr_trp_d = 4'h2; +assign cfg_sdr_trcd_d = 4'h2; +assign cfg_sdr_cas = 3'h3; +assign cfg_sdr_trcar_d = 4'h7; +assign cfg_sdr_twr_d = 4'h1; +assign cfg_sdr_rfsh = 12'h100; // reduced from 12'hC35 +assign cfg_sdr_rfmax = 3'h6;*/ +//assign cfg_colbits = 2'b00; +//assign cfg_sdr_width = 2'b00; + +//-------------------------------------------- +// SDRAM controller Interface +//-------------------------------------------- +input app_req ; // SDRAM request +input app_req_wrap ; // SDRAM wrap +input [APP_AW-1:0] app_req_addr ; // SDRAM Request Address +input [bl-1:0] app_req_len ; +input app_req_wr_n ; // 0 - Write, 1 -> Read +output app_req_ack ; // SDRAM request Accepted +wire app_busy_n ; // 0 -> sdr busy +input [dw/8-1:0] app_wr_en_n ; // Active low sdr byte-wise write data valid +output app_wr_next_req ; // Ready to accept the next write +output app_rd_valid ; // sdr read valid +output app_last_rd ; // Indicate last Read of Burst Transfer +output app_last_wr ; // Indicate last Write of Burst Transfer +input [dw-1:0] app_wr_data ; // sdr write data +output [dw-1:0] app_rd_data ; // sdr read data + +input [3:0] delay_config_reg2; + +/**************************************** +* These logic has to be implemented using Pads +* **************************************/ +/*wire [SDR_DW-1:0] pad_sdr_din ; // SDRA Data Input +wire [SDR_DW-1:0] sdr_dout ; // SDRAM Data Output +wire [SDR_BW-1:0] sdr_den_n ; // SDRAM Data Output enable +wire [SDR_DW-1:0] sdr_dq ; // SDRA Data Input/output*/ + +/*assign sdr_dq0 = sdr_dq[31:0]; +assign sdr_dq1 = sdr_dq[63:32]; + + +assign sdr_dq = (&sdr_den_n == 1'b0) ? sdr_dout : {SDR_DW{1'bz}}; +assign pad_sdr_din = {sdr_dq1, sdr_dq0};*/ + + + +// sdram pad clock is routed back through pad +// SDRAM Clock from Pad, used for registering Read Data +wire sdram_pad_clk; +parallel_prog_delay_cell delay_inst_for_sdram_clk_pad(.in_clk(sdram_clk), .delay_config_reg(delay_config_reg2), .delayed_clk(sdram_pad_clk)); + + + +sdrc_core #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_sdrc_core ( + .clk (sdram_clk ) , + .pad_clk (sdram_pad_clk ) , + .reset_n (sdram_resetn ) , + .sdr_width (cfg_sdr_width ) , + .cfg_colbits (cfg_colbits ) , + + /* Request from app */ + .app_req (app_req ) ,// Transfer Request + .app_req_addr (app_req_addr ) ,// SDRAM Address + .app_req_len (app_req_len ) ,// Burst Length (in 16 bit words) + .app_req_wrap (app_req_wrap ) ,// Wrap mode request + .app_req_wr_n (app_req_wr_n ) ,// 0 => Write request, 1 => read req + .app_req_ack (app_req_ack ) ,// Request has been accepted + .cfg_req_depth (cfg_req_depth ) ,//how many req. buffer should hold + + .app_wr_data (app_wr_data ) , + .app_wr_en_n (app_wr_en_n ) , + .app_rd_data (app_rd_data ) , + .app_rd_valid (app_rd_valid ) , + .app_last_rd (app_last_rd ) , + .app_last_wr (app_last_wr ) , + .app_wr_next_req (app_wr_next_req ) , + .sdr_init_done (sdr_init_done ) , + .app_req_dma_last (app_req ) , + + /* Interface to SDRAMs */ + .sdr_cs_n (sdr_cs_n ) , + .sdr_cke (sdr_cke ) , + .sdr_ras_n (sdr_ras_n ) , + .sdr_cas_n (sdr_cas_n ) , + .sdr_we_n (sdr_we_n ) , + .sdr_dqm (sdr_dqm ) , + .sdr_ba (sdr_ba ) , + .sdr_addr (sdr_addr ) , + .pad_sdr_din (pad_sdr_din ) , + .sdr_dout (sdr_dout ) , + .sdr_den_n (sdr_den_n ) , + + /* Parameters */ + .cfg_sdr_en (cfg_sdr_en ) , + .cfg_sdr_mode_reg (cfg_sdr_mode_reg ) , + .cfg_sdr_tras_d (cfg_sdr_tras_d ) , + .cfg_sdr_trp_d (cfg_sdr_trp_d ) , + .cfg_sdr_trcd_d (cfg_sdr_trcd_d ) , + .cfg_sdr_cas (cfg_sdr_cas ) , + .cfg_sdr_trcar_d (cfg_sdr_trcar_d ) , + .cfg_sdr_twr_d (cfg_sdr_twr_d ) , + .cfg_sdr_rfsh (cfg_sdr_rfsh ) , + .cfg_sdr_rfmax (cfg_sdr_rfmax ) + ); + +endmodule // sdrc_core diff --git a/src/peripherals/sdram/controller/sdrc_xfr_ctl.v b/src/peripherals/sdram/controller/sdrc_xfr_ctl.v new file mode 100755 index 0000000..8acd980 --- /dev/null +++ b/src/peripherals/sdram/controller/sdrc_xfr_ctl.v @@ -0,0 +1,939 @@ +/********************************************************************* + + SDRAM Controller Transfer control + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: SDRAM Controller Transfer control + + This module takes requests from sdrc_bank_ctl and runs the + transfer. The input request is guaranteed to be in a bank that is + precharged and activated. This block runs the transfer until a + burst boundary is reached, then issues another read/write command + to sequentially step thru memory if wrap=0, until the transfer is + completed. + + if a read transfer finishes and the caddr is not at a burst boundary + a burst terminate command is issued unless another read/write or + precharge to the same bank is pending. + + if a write transfer finishes and the caddr is not at a burst boundary + a burst terminate command is issued unless a read/write is pending. + + If a refresh request is made, the bank_ctl will be held off until + the number of refreshes requested are completed. + + This block also handles SDRAM initialization. + + + To Do: + nothing + + Author(s): + - Dinesh Annayya, dinesha@opencores.org + Version : 1.0 - 8th Jan 2012 + + + + Copyright (C) 2000 Authors and OPENCORES.ORG + + This source file may be used and distributed without + restriction provided that this copyright statement is not + removed from the file and that any derivative work contains + the original copyright notice and the associated disclaimer. + + This source file is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General + Public License as published by the Free Software Foundation; + either version 2.1 of the License, or (at your option) any +later version. + + This source 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General + Public License along with this source; if not, download it + from http://www.opencores.org/lgpl.shtml + +*******************************************************************/ + + + +module sdrc_xfr_ctl (clk, + reset_n, + + /* Transfer request from bank_ctl */ + r2x_idle, // Req is idle + b2x_idle, // All banks are idle + b2x_req, // Req from bank_ctl + b2x_start, // first chunk of transfer + b2x_last, // last chunk of transfer + b2x_id, // Transfer ID + b2x_ba, // bank address + b2x_addr, // row/col address + b2x_len, // transfer length + b2x_cmd, // transfer command + b2x_wrap, // Wrap mode transfer + x2b_ack, // command accepted + + /* Status to bank_ctl, req_gen */ + b2x_tras_ok, // Tras for all banks expired + x2b_refresh, // We did a refresh + x2b_pre_ok, // OK to do a precharge (per bank) + x2b_act_ok, // OK to do an activate + x2b_rdok, // OK to do a read + x2b_wrok, // OK to do a write + + /* SDRAM I/O */ + sdr_cs_n, + sdr_cke, + sdr_ras_n, + sdr_cas_n, + sdr_we_n, + sdr_dqm, + sdr_ba, + sdr_addr, + sdr_din, + sdr_dout, + sdr_den_n, + + /* Data Flow to the app */ + x2a_rdstart, + x2a_wrstart, + x2a_rdlast, + x2a_wrlast, + x2a_id, + a2x_wrdt, + a2x_wren_n, + x2a_wrnext, + x2a_rddt, + x2a_rdok, + sdr_init_done, + + /* SDRAM Parameters */ + sdram_enable, + sdram_mode_reg, + + /* output for generate row address of the transfer */ + xfr_bank_sel, + + /* SDRAM Timing */ + cas_latency, + trp_delay, // Precharge to refresh delay + trcar_delay, // Auto-refresh period + twr_delay, // Write recovery delay + rfsh_time, // time per row (31.25 or 15.6125 uS) + rfsh_rmax); // Number of rows to rfsh at a time (<120uS) + + +`define SDR_REQ_ID_W 4 + +`define SDR_RFSH_TIMER_W 12 +`define SDR_RFSH_ROW_CNT_W 3 + +// B2X Command + +`define OP_PRE 2'b00 +`define OP_ACT 2'b01 +`define OP_RD 2'b10 +`define OP_WR 2'b11 + +// SDRAM Commands (CS_N, RAS_N, CAS_N, WE_N) + +`define SDR_DESEL 4'b1111 +`define SDR_NOOP 4'b0111 +`define SDR_ACTIVATE 4'b0011 +`define SDR_READ 4'b0101 +`define SDR_WRITE 4'b0100 +`define SDR_BT 4'b0110 +`define SDR_PRECHARGE 4'b0010 +`define SDR_REFRESH 4'b0001 +`define SDR_MODE 4'b0000 + +`define ASIC 1'b1 +`define FPGA 1'b0 +`define TARGET_DESIGN `ASIC +// 12 bit subtractor is not feasibile for FPGA, so changed to 6 bits +`define REQ_BW (`TARGET_DESIGN == `FPGA) ? 6 : 12 // Request Width + +parameter SDR_DW = 64; // SDR Data Width +parameter SDR_BW = 8; // SDR Byte Width + + +input clk, reset_n; + + /* Req from bank_ctl */ +input b2x_req, b2x_start, b2x_last, b2x_tras_ok, + b2x_wrap, r2x_idle, b2x_idle; +input [`SDR_REQ_ID_W-1:0] b2x_id; +input [1:0] b2x_ba; +input [12:0] b2x_addr; +input [`REQ_BW-1:0] b2x_len; +input [1:0] b2x_cmd; +output x2b_ack; + +/* Status to bank_ctl */ +output [3:0] x2b_pre_ok; +output x2b_refresh, x2b_act_ok, x2b_rdok, + x2b_wrok; +/* Data Flow to the app */ +output x2a_rdstart, x2a_wrstart, x2a_rdlast, x2a_wrlast; +output [`SDR_REQ_ID_W-1:0] x2a_id; + +input [SDR_DW-1:0] a2x_wrdt; +input [SDR_BW-1:0] a2x_wren_n; +output [SDR_DW-1:0] x2a_rddt; +output x2a_wrnext, x2a_rdok, sdr_init_done; + +/* Interface to SDRAMs */ +output sdr_cs_n, sdr_cke, sdr_ras_n, sdr_cas_n, + sdr_we_n; +output [SDR_BW-1:0] sdr_dqm; +output [1:0] sdr_ba; +output [12:0] sdr_addr; +input [SDR_DW-1:0] sdr_din; +output [SDR_DW-1:0] sdr_dout; +output [SDR_BW-1:0] sdr_den_n; + + output [1:0] xfr_bank_sel; + + input sdram_enable; + input [12:0] sdram_mode_reg; + input [2:0] cas_latency; + input [3:0] trp_delay, trcar_delay, twr_delay; + input [`SDR_RFSH_TIMER_W-1 : 0] rfsh_time; + input [`SDR_RFSH_ROW_CNT_W-1:0] rfsh_rmax; + +// vish change mode reg ext + //reg [12:0] sdram_mode_ext_reg; + reg init_delay_done; // winbond initial delay done flag : vish change + reg mode_set; + reg wr_mode_set; + + /************************************************************************/ + // Internal Nets + + `define XFR_IDLE 2'b00 + `define XFR_WRITE 2'b01 + `define XFR_READ 2'b10 + `define XFR_RDWT 2'b11 + + reg [1:0] xfr_st, next_xfr_st; + reg [12:0] xfr_caddr; + wire last_burst; + wire x2a_rdstart, x2a_wrstart, x2a_rdlast, x2a_wrlast; + reg l_start, l_last, l_wrap; + wire [`SDR_REQ_ID_W-1:0] x2a_id; + reg [`SDR_REQ_ID_W-1:0] l_id; + wire [1:0] xfr_ba; + reg [1:0] l_ba; + wire [12:0] xfr_addr; + wire [`REQ_BW-1:0] xfr_len, next_xfr_len; + reg [`REQ_BW-1:0] l_len; + + reg mgmt_idle, mgmt_req; + reg [3:0] mgmt_cmd; + reg [12:0] mgmt_addr; + reg [1:0] mgmt_ba; + + reg sel_mgmt, sel_b2x; + reg cb_pre_ok, rdok, wrok, wr_next, + rd_next, sdr_init_done, act_cmd, d_act_cmd; + wire [3:0] b2x_sdr_cmd, xfr_cmd; + reg [3:0] i_xfr_cmd; + wire mgmt_ack, x2b_ack, b2x_read, b2x_write, + b2x_prechg, d_rd_next, dt_next, xfr_end, + rd_pipe_mt, ld_xfr, rd_last, d_rd_last, + wr_last, l_xfr_end, rd_start, d_rd_start, + wr_start, page_hit, burst_bdry, xfr_wrap, + b2x_prechg_hit; + reg [6:0] l_rd_next, l_rd_start, l_rd_last; + +//vish change + reg[11:0] rg_initial_delay; + + + assign b2x_read = (b2x_cmd == `OP_RD) ? 1'b1 : 1'b0; + + assign b2x_write = (b2x_cmd == `OP_WR) ? 1'b1 : 1'b0; + + assign b2x_prechg = (b2x_cmd == `OP_PRE) ? 1'b1 : 1'b0; + + assign b2x_sdr_cmd = (b2x_cmd == `OP_PRE) ? `SDR_PRECHARGE : + (b2x_cmd == `OP_ACT) ? `SDR_ACTIVATE : + (b2x_cmd == `OP_RD) ? `SDR_READ : + (b2x_cmd == `OP_WR) ? `SDR_WRITE : `SDR_DESEL; + + assign page_hit = (b2x_ba == l_ba) ? 1'b1 : 1'b0; + + assign b2x_prechg_hit = b2x_prechg & page_hit; + + assign xfr_cmd = (sel_mgmt) ? mgmt_cmd : + (sel_b2x) ? b2x_sdr_cmd : i_xfr_cmd; + + assign xfr_addr = (sel_mgmt) ? mgmt_addr : + (sel_b2x) ? b2x_addr : xfr_caddr+1; + + assign mgmt_ack = sel_mgmt; + + assign x2b_ack = sel_b2x; + + assign ld_xfr = sel_b2x & (b2x_read | b2x_write); + + assign xfr_len = (ld_xfr) ? b2x_len : l_len; + + //assign next_xfr_len = (l_xfr_end && !ld_xfr) ? l_len : xfr_len - 1; + assign next_xfr_len = (ld_xfr) ? b2x_len : + (l_xfr_end) ? l_len: l_len - 1; + + assign d_rd_next = (cas_latency == 3'b001) ? l_rd_next[2] : + (cas_latency == 3'b010) ? l_rd_next[3] : + (cas_latency == 3'b011) ? l_rd_next[4] : + (cas_latency == 3'b100) ? l_rd_next[5] : + l_rd_next[6]; + + assign d_rd_last = (cas_latency == 3'b001) ? l_rd_last[2] : + (cas_latency == 3'b010) ? l_rd_last[3] : + (cas_latency == 3'b011) ? l_rd_last[4] : + (cas_latency == 3'b100) ? l_rd_last[5] : + l_rd_last[6]; + + assign d_rd_start = (cas_latency == 3'b001) ? l_rd_start[2] : + (cas_latency == 3'b010) ? l_rd_start[3] : + (cas_latency == 3'b011) ? l_rd_start[4] : + (cas_latency == 3'b100) ? l_rd_start[5] : + l_rd_start[6]; + + assign rd_pipe_mt = (cas_latency == 3'b001) ? ~|l_rd_next[1:0] : + (cas_latency == 3'b010) ? ~|l_rd_next[2:0] : + (cas_latency == 3'b011) ? ~|l_rd_next[3:0] : + (cas_latency == 3'b100) ? ~|l_rd_next[4:0] : + ~|l_rd_next[5:0]; + + assign dt_next = wr_next | d_rd_next; + + assign xfr_end = ~|xfr_len; + + assign l_xfr_end = ~|(l_len-1); + + assign rd_start = ld_xfr & b2x_read & b2x_start; + + assign wr_start = ld_xfr & b2x_write & b2x_start; + + assign rd_last = rd_next & last_burst & ~|xfr_len[`REQ_BW-1:1]; + + //assign wr_last = wr_next & last_burst & ~|xfr_len[APP_RW-1:1]; + + assign wr_last = last_burst & ~|xfr_len[`REQ_BW-1:1]; + + //assign xfr_ba = (ld_xfr) ? b2x_ba : l_ba; + assign xfr_ba = (sel_mgmt) ? mgmt_ba : + (sel_b2x) ? b2x_ba : l_ba; + + assign xfr_wrap = (ld_xfr) ? b2x_wrap : l_wrap; + +// assign burst_bdry = ~|xfr_caddr[2:0]; + wire [1:0] xfr_caddr_lsb = (xfr_caddr[1:0]+1); + assign burst_bdry = ~|(xfr_caddr_lsb[1:0]); + + always @ (posedge clk) begin + if (~reset_n) begin + xfr_caddr <= 13'b0; + l_start <= 1'b0; + l_last <= 1'b0; + l_wrap <= 1'b0; + l_id <= 0; + l_ba <= 0; + l_len <= 0; + l_rd_next <= 7'b0; + l_rd_start <= 7'b0; + l_rd_last <= 7'b0; + act_cmd <= 1'b0; + d_act_cmd <= 1'b0; + xfr_st <= `XFR_IDLE; + end // if (~reset_n) + + else begin + xfr_caddr <= (ld_xfr) ? b2x_addr : + (rd_next | wr_next) ? xfr_caddr + 1 : xfr_caddr; + l_start <= (dt_next) ? 1'b0 : + (ld_xfr) ? b2x_start : l_start; + l_last <= (ld_xfr) ? b2x_last : l_last; + l_wrap <= (ld_xfr) ? b2x_wrap : l_wrap; + l_id <= (ld_xfr) ? b2x_id : l_id; + l_ba <= (ld_xfr) ? b2x_ba : l_ba; + l_len <= next_xfr_len; + l_rd_next <= {l_rd_next[5:0], rd_next}; + l_rd_start <= {l_rd_start[5:0], rd_start}; + l_rd_last <= {l_rd_last[5:0], rd_last}; + act_cmd <= (xfr_cmd == `SDR_ACTIVATE) ? 1'b1 : 1'b0; + d_act_cmd <= act_cmd; + xfr_st <= next_xfr_st; + end // else: !if(~reset_n) + + end // always @ (posedge clk) + + + always @ (*) begin + case (xfr_st) + + `XFR_IDLE : begin + + sel_mgmt = mgmt_req; + sel_b2x = ~mgmt_req & sdr_init_done & b2x_req; + i_xfr_cmd = `SDR_DESEL; + rd_next = ~mgmt_req & sdr_init_done & b2x_req & b2x_read; + wr_next = ~mgmt_req & sdr_init_done & b2x_req & b2x_write; + rdok = ~mgmt_req; + cb_pre_ok = 1'b1; + wrok = ~mgmt_req; + next_xfr_st = (mgmt_req | ~sdr_init_done) ? `XFR_IDLE : + (~b2x_req) ? `XFR_IDLE : + (b2x_read) ? `XFR_READ : + (b2x_write) ? `XFR_WRITE : `XFR_IDLE; + + end // case: `XFR_IDLE + + `XFR_READ : begin + rd_next = ~l_xfr_end | + l_xfr_end & ~mgmt_req & b2x_req & b2x_read; + wr_next = 1'b0; + rdok = l_xfr_end & ~mgmt_req; + // Break the timing path for FPGA Based Design + cb_pre_ok = (`TARGET_DESIGN == `FPGA) ? 1'b0 : l_xfr_end; + wrok = 1'b0; + sel_mgmt = 1'b0; + + if (l_xfr_end) begin // end of transfer + + if (~l_wrap) begin + // Current transfer was not wrap mode, may need BT + // If next cmd is a R or W or PRE to same bank allow + // it else issue BT + // This is a little pessimistic since BT is issued + // for non-wrap mode transfers even if the transfer + // ends on a burst boundary, but is felt to be of + // minimal performance impact. + + i_xfr_cmd = `SDR_BT; + sel_b2x = b2x_req & ~mgmt_req & (b2x_read | b2x_prechg_hit); + + end // if (~l_wrap) + + else begin + // Wrap mode transfer, by definition is end of burst + // boundary + + i_xfr_cmd = `SDR_DESEL; + sel_b2x = b2x_req & ~mgmt_req & ~b2x_write; + + end // else: !if(~l_wrap) + + next_xfr_st = (sdr_init_done) ? ((b2x_req & ~mgmt_req & b2x_read) ? `XFR_READ : `XFR_RDWT) : `XFR_IDLE; + + end // if (l_xfr_end) + + else begin + // Not end of transfer + // If current transfer was not wrap mode and we are at + // the start of a burst boundary issue another R cmd to + // step sequemtially thru memory, ELSE, + // issue precharge/activate commands from the bank control + + i_xfr_cmd = (burst_bdry & ~l_wrap) ? `SDR_READ : `SDR_DESEL; + sel_b2x = ~(burst_bdry & ~l_wrap) & b2x_req; + next_xfr_st = `XFR_READ; + + end // else: !if(l_xfr_end) + + end // case: `XFR_READ + + `XFR_RDWT : begin + rd_next = ~mgmt_req & b2x_req & b2x_read; + wr_next = rd_pipe_mt & ~mgmt_req & b2x_req & b2x_write; + rdok = ~mgmt_req; + cb_pre_ok = 1'b1; + wrok = rd_pipe_mt & ~mgmt_req; + + sel_mgmt = mgmt_req; + + sel_b2x = ~mgmt_req & b2x_req; + + i_xfr_cmd = `SDR_DESEL; + + next_xfr_st = (~mgmt_req & b2x_req & b2x_read) ? `XFR_READ : + (~rd_pipe_mt) ? `XFR_RDWT : + (~mgmt_req & b2x_req & b2x_write) ? `XFR_WRITE : + `XFR_IDLE; + + end // case: `XFR_RDWT + + `XFR_WRITE : begin + rd_next = l_xfr_end & ~mgmt_req & b2x_req & b2x_read; + wr_next = ~l_xfr_end | + l_xfr_end & ~mgmt_req & b2x_req & b2x_write; + rdok = l_xfr_end & ~mgmt_req; + cb_pre_ok = 1'b0; + wrok = l_xfr_end & ~mgmt_req; + sel_mgmt = 1'b0; + + if (l_xfr_end) begin // End of transfer + + if (~l_wrap) begin + // Current transfer was not wrap mode, may need BT + // If next cmd is a R or W allow it else issue BT + // This is a little pessimistic since BT is issued + // for non-wrap mode transfers even if the transfer + // ends on a burst boundary, but is felt to be of + // minimal performance impact. + + + sel_b2x = b2x_req & ~mgmt_req & (b2x_read | b2x_write); + i_xfr_cmd = `SDR_BT; + end // if (~l_wrap) + + else begin + // Wrap mode transfer, by definition is end of burst + // boundary + + sel_b2x = b2x_req & ~mgmt_req & ~b2x_prechg_hit; + i_xfr_cmd = `SDR_DESEL; + end // else: !if(~l_wrap) + + next_xfr_st = (~mgmt_req & b2x_req & b2x_read) ? `XFR_READ : + (~mgmt_req & b2x_req & b2x_write) ? `XFR_WRITE : + `XFR_IDLE; + + end // if (l_xfr_end) + + else begin + // Not end of transfer + // If current transfer was not wrap mode and we are at + // the start of a burst boundary issue another R cmd to + // step sequemtially thru memory, ELSE, + // issue precharge/activate commands from the bank control + + if (burst_bdry & ~l_wrap) begin + sel_b2x = 1'b0; + i_xfr_cmd = `SDR_WRITE; + end // if (burst_bdry & ~l_wrap) + + else begin + sel_b2x = b2x_req & ~mgmt_req; + i_xfr_cmd = `SDR_DESEL; + end // else: !if(burst_bdry & ~l_wrap) + + next_xfr_st = `XFR_WRITE; + end // else: !if(l_xfr_end) + + end // case: `XFR_WRITE + + endcase // case(xfr_st) + + end // always @ (xfr_st or ...) + + // signals to bank_ctl (x2b_refresh, x2b_act_ok, x2b_rdok, x2b_wrok, + // x2b_pre_ok[3:0] + + assign x2b_refresh = (xfr_cmd == `SDR_REFRESH) ? 1'b1 : 1'b0; + + assign x2b_act_ok = ~act_cmd & ~d_act_cmd; + + assign x2b_rdok = rdok; + + assign x2b_wrok = wrok; + + //assign x2b_pre_ok[0] = (l_ba == 2'b00) ? cb_pre_ok : 1'b1; + //assign x2b_pre_ok[1] = (l_ba == 2'b01) ? cb_pre_ok : 1'b1; + //assign x2b_pre_ok[2] = (l_ba == 2'b10) ? cb_pre_ok : 1'b1; + //assign x2b_pre_ok[3] = (l_ba == 2'b11) ? cb_pre_ok : 1'b1; + + assign x2b_pre_ok[0] = cb_pre_ok; + assign x2b_pre_ok[1] = cb_pre_ok; + assign x2b_pre_ok[2] = cb_pre_ok; + assign x2b_pre_ok[3] = cb_pre_ok; + assign last_burst = (ld_xfr) ? b2x_last : l_last; + + /************************************************************************/ + // APP Data I/F + + wire [SDR_DW-1:0] x2a_rddt; + + //assign x2a_start = (ld_xfr) ? b2x_start : l_start; + assign x2a_rdstart = d_rd_start; + assign x2a_wrstart = wr_start; + + assign x2a_rdlast = d_rd_last; + assign x2a_wrlast = wr_last; + + assign x2a_id = (ld_xfr) ? b2x_id : l_id; + + assign x2a_rddt = sdr_din; + + assign x2a_wrnext = wr_next; + + assign x2a_rdok = d_rd_next; + + /************************************************************************/ + // SDRAM I/F + + reg sdr_cs_n, sdr_cke, sdr_ras_n, sdr_cas_n, + sdr_we_n; + reg [SDR_BW-1:0] sdr_dqm; + reg [1:0] sdr_ba; + reg [12:0] sdr_addr; + reg [SDR_DW-1:0] sdr_dout; + reg [SDR_BW-1:0] sdr_den_n; + + always @ (posedge clk) + if (~reset_n) begin + sdr_cs_n <= 1'b1; + sdr_cke <= 1'b1; + sdr_ras_n <= 1'b1; + sdr_cas_n <= 1'b1; + sdr_we_n <= 1'b1; + sdr_dqm <= {SDR_BW{1'b1}}; + sdr_den_n <= {SDR_BW{1'b1}}; + end // if (~reset_n) + else begin + sdr_cs_n <= xfr_cmd[3]; + sdr_ras_n <= xfr_cmd[2]; + sdr_cas_n <= xfr_cmd[1]; + sdr_we_n <= xfr_cmd[0]; + // vish change: cke is kept high after initialization +// sdr_cke <= (xfr_st != `XFR_IDLE) ? 1'b1 : +// ~(mgmt_idle & b2x_idle & r2x_idle); +// + if(init_delay_done) begin + sdr_dqm <= (wr_next) ? a2x_wren_n : {SDR_BW{1'b0}}; + sdr_cke <= 1'b1; + end + sdr_den_n <= (wr_next) ? {SDR_BW{1'b0}} : {SDR_BW{1'b1}}; + end // else: !if(~reset_n) + + always @ (posedge clk) begin + + if (~xfr_cmd[3]) begin + sdr_addr <= xfr_addr; + sdr_ba <= xfr_ba; + end // if (~xfr_cmd[3]) + + sdr_dout <= (wr_next) ? a2x_wrdt : sdr_dout; + + + end // always @ (posedge clk) + + /************************************************************************/ + // Refresh and Initialization +//vish change : increased the MGM size and added one more state + + `define MGM_INIT_DELAY 4'b0000 + `define MGM_INIT_NOOP 4'b0001 + `define MGM_POWERUP 4'b0010 + `define MGM_PRECHARGE 4'b0011 + `define MGM_PCHWT 4'b0100 + `define MGM_REFRESH 4'b0101 + `define MGM_REFWT 4'b0110 + `define MGM_MODE_REG 4'b0111 + `define MGM_MODE_WT 4'b1000 + `define MGM_MODE_EXT_REG 4'b1001 + `define MGM_MODE_EXT_WT 4'b1010 + `define MGM_ACTIVE 4'b1011 + + reg [3:0] mgmt_st, next_mgmt_st; + reg [3:0] tmr0, tmr0_d; + reg [3:0] cntr1, cntr1_d; + wire tmr0_tc, cntr1_tc, rfsh_timer_tc, ref_req, precharge_ok; + reg ld_tmr0, ld_cntr1, dec_cntr1, set_sdr_init_done; + reg [`SDR_RFSH_TIMER_W-1 : 0] rfsh_timer; + reg [`SDR_RFSH_ROW_CNT_W-1:0] rfsh_row_cnt; + + always @ (posedge clk) + if (~reset_n) begin + mgmt_st <= `MGM_POWERUP; + tmr0 <= 4'b0; + cntr1 <= 4'h7; + rfsh_timer <= 0; + rfsh_row_cnt <= 0; + sdr_init_done <= 1'b0; + end // if (~reset_n) + else begin + mgmt_st <= next_mgmt_st; + tmr0 <= (ld_tmr0) ? tmr0_d : + (~tmr0_tc) ? tmr0 - 1 : tmr0; + cntr1 <= (ld_cntr1) ? cntr1_d : + (dec_cntr1) ? cntr1 - 1 : cntr1; + sdr_init_done <= (set_sdr_init_done | sdr_init_done) & sdram_enable; + rfsh_timer <= (rfsh_timer_tc) ? 0 : rfsh_timer + 1; + rfsh_row_cnt <= (~set_sdr_init_done) ? 0 : + (rfsh_timer_tc) ? rfsh_row_cnt + 1 : rfsh_row_cnt; + end // else: !if(~reset_n) + + assign tmr0_tc = ~|tmr0; + + assign cntr1_tc = ~|cntr1; + + assign rfsh_timer_tc = (rfsh_timer == rfsh_time) ? 1'b1 : 1'b0; + + assign ref_req = (rfsh_row_cnt >= rfsh_rmax) ? 1'b1 : 1'b0; + + assign precharge_ok = cb_pre_ok & b2x_tras_ok; + + assign xfr_bank_sel = l_ba; + + + always @ (posedge clk) begin + if(~reset_n) begin + rg_initial_delay <= 0; + init_delay_done <= 0; + //sdram_mode_ext_reg <= 0; + end + else if(rg_initial_delay < 2048) begin + rg_initial_delay <= rg_initial_delay + 1; + init_delay_done <= 0; + +// sdr_dqm <= {SDR_BW{1'b1}}; + end + else begin + init_delay_done <= 1; + end + end + + always@(posedge clk) begin + if(~reset_n) begin + mode_set <= 0; + end + else + mode_set <= wr_mode_set; + end + + always @ (mgmt_st or sdram_enable or mgmt_ack or trp_delay or tmr0_tc or + cntr1_tc or trcar_delay or rfsh_row_cnt or ref_req or sdr_init_done + or precharge_ok or sdram_mode_reg or mode_set or init_delay_done) begin //added mode_set and sdram_mode_ext_reg in the sensitivity list. deleted sdram_mode_ext_reg + + // always @ (posedge clk) begin + case (mgmt_st) // synopsys full_case parallel_case + + + `MGM_POWERUP : begin + mgmt_idle = 1'b0; + mgmt_req = 1'b0; + mgmt_cmd = `SDR_DESEL; + mgmt_ba = 2'b0; + mgmt_addr = 13'h400; // A10 = 1 => all banks + ld_tmr0 = 1'b0; + tmr0_d = 4'b0; + dec_cntr1 = 1'b0; + ld_cntr1 = 1'b1; + cntr1_d = 4'hf; // changed for sdrams with higher refresh cycles during initialization + set_sdr_init_done = 1'b0; + wr_mode_set = 1'b0; + next_mgmt_st = (sdram_enable) ? `MGM_INIT_DELAY : `MGM_POWERUP; + end // case: `MGM_POWERUP + + `MGM_INIT_DELAY : begin // Precharge all banks + mgmt_idle = 1'b0; + set_sdr_init_done = 1'b0; + wr_mode_set = 1'b0; + mgmt_req = 0; + mgmt_cmd =`SDR_DESEL; + mgmt_ba = 2'bx; + mgmt_addr = 13'bx; + ld_tmr0 = 1'b0; + tmr0_d = 4'h0; + ld_cntr1 = 1'b0; + dec_cntr1 = 1'b0; + cntr1_d = 4'b0; + next_mgmt_st = (init_delay_done) ? `MGM_INIT_NOOP : `MGM_INIT_DELAY; + end // case: `MGM_INIT_DELAY + + `MGM_INIT_NOOP : begin // Precharge all banks + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = `SDR_NOOP; + mgmt_ba = 2'b0; + mgmt_addr = 13'h400; // A10 = 1 => all banks + wr_mode_set = 1'b0; + ld_tmr0 = mgmt_ack; + tmr0_d = trp_delay; + ld_cntr1 = 1'b0; + cntr1_d = 4'h7; + dec_cntr1 = 1'b0; + set_sdr_init_done = 1'b0; + next_mgmt_st = (mgmt_ack) ? `MGM_PRECHARGE : `MGM_INIT_NOOP; + end // case: `MGM_INIT_DELAY + + `MGM_PRECHARGE : begin // Precharge all banks + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = (precharge_ok) ? `SDR_PRECHARGE : `SDR_DESEL; + mgmt_ba = 2'b0; + mgmt_addr = 13'h400; // A10 = 1 => all banks + ld_tmr0 = mgmt_ack; + tmr0_d = trp_delay; + ld_cntr1 = 1'b0; + cntr1_d = 4'h7; + wr_mode_set = 1'b0; + dec_cntr1 = 1'b0; + set_sdr_init_done = 1'b0; + next_mgmt_st = (precharge_ok & mgmt_ack) ? `MGM_PCHWT : `MGM_PRECHARGE; + end // case: `MGM_PRECHARGE + + `MGM_PCHWT : begin // Wait for Trp + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = `SDR_DESEL; + mgmt_ba = 2'b0; + mgmt_addr = 13'h400; // A10 = 1 => all banks + ld_tmr0 = 1'b0; + tmr0_d = trp_delay; + ld_cntr1 = 1'b0; + cntr1_d = 4'b0; + wr_mode_set = 1'b0; + dec_cntr1 = 1'b0; + set_sdr_init_done = 1'b0; + next_mgmt_st = (tmr0_tc) ? `MGM_REFRESH : `MGM_PCHWT; + end // case: `MGM_PRECHARGE + + `MGM_REFRESH : begin // Refresh + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = `SDR_REFRESH; + mgmt_ba = 2'b0; + mgmt_addr = 13'h400; // A10 = 1 => all banks + ld_tmr0 = mgmt_ack; + tmr0_d = trcar_delay; + dec_cntr1 = mgmt_ack; + ld_cntr1 = 1'b0; + cntr1_d = 4'h7; + wr_mode_set = mode_set; + set_sdr_init_done = 1'b0; + next_mgmt_st = (mgmt_ack) ? `MGM_REFWT : `MGM_REFRESH; + end // case: `MGM_REFRESH + + `MGM_REFWT : begin // Wait for trcar + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = `SDR_DESEL; + mgmt_ba = 2'b0; + mgmt_addr = 13'h400; // A10 = 1 => all banks + ld_tmr0 = 1'b0; + tmr0_d = trcar_delay; + dec_cntr1 = 1'b0; + ld_cntr1 = 1'b0; + wr_mode_set = mode_set; + cntr1_d = 4'h7; + set_sdr_init_done = 1'b0; + next_mgmt_st = (~tmr0_tc) ? `MGM_REFWT : + (~cntr1_tc) ? `MGM_REFRESH : + (sdr_init_done) ? `MGM_ACTIVE : (mode_set) ? `MGM_ACTIVE : `MGM_MODE_REG; + end // case: `MGM_REFWT + + `MGM_MODE_REG : begin // Program mode Register & wait for + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = `SDR_MODE; + mgmt_ba = {1'b0, sdram_mode_reg[11]}; + mgmt_addr = sdram_mode_reg; + ld_tmr0 = mgmt_ack; + tmr0_d = 4'h7; + dec_cntr1 = 1'b0; + ld_cntr1 = 1'b0; + wr_mode_set = 1'b0; + cntr1_d = 4'h7; + set_sdr_init_done = 1'b0; + next_mgmt_st = (mgmt_ack) ? `MGM_MODE_WT : `MGM_MODE_REG; + end // case: `MGM_MODE_REG + + `MGM_MODE_WT : begin // Wait for tMRD + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = `SDR_DESEL; + mgmt_ba = 2'bx; + mgmt_addr = 13'bx; + ld_tmr0 = 1'b0; + tmr0_d = 4'h7; + dec_cntr1 = 1'b0; + ld_cntr1 = 1'b0; + cntr1_d = 4'h7; + wr_mode_set = 1'b0; + set_sdr_init_done = 1'b0; + next_mgmt_st = (~tmr0_tc) ? `MGM_MODE_WT : `MGM_MODE_EXT_REG; + end // case: `MGM_MODE_WT + + `MGM_MODE_EXT_REG : begin // Program mode Register & wait for + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = `SDR_MODE; + mgmt_ba = 2'b10; + mgmt_addr = 0;//sdram_mode_ext_reg; + ld_tmr0 = mgmt_ack; + tmr0_d = 4'h7; + dec_cntr1 = 1'b0; + ld_cntr1 = 1'b0; + wr_mode_set = 1'b0; + cntr1_d = 4'h7; + set_sdr_init_done = 1'b0; + next_mgmt_st = (mgmt_ack) ? `MGM_MODE_EXT_WT : `MGM_MODE_EXT_REG; + end // case: `MGM_MODE_EXT_REG + + `MGM_MODE_EXT_WT : begin // Wait for tMRD + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = `SDR_DESEL; + mgmt_ba = 2'bx; + mgmt_addr = 13'bx; + ld_tmr0 = 1'b0; + tmr0_d = 4'h7; + dec_cntr1 = 1'b0; + ld_cntr1 = 1'b0; + cntr1_d = 4'h7; + wr_mode_set = 1'b1; + set_sdr_init_done = 1'b0; + next_mgmt_st = (~tmr0_tc) ? `MGM_MODE_EXT_WT : `MGM_REFRESH; + end // case: `MGM_MODE_WT + + `MGM_ACTIVE : begin // Wait for ref_req + mgmt_idle = ~ref_req; + mgmt_req = 1'b0; + mgmt_cmd = `SDR_DESEL; + mgmt_ba = 2'bx; + mgmt_addr = 13'bx; + ld_tmr0 = 1'b0; + tmr0_d = 4'h7; + dec_cntr1 = 1'b0; + ld_cntr1 = ref_req; + wr_mode_set = 1'b0; + cntr1_d = rfsh_row_cnt; + set_sdr_init_done = 1'b1; + next_mgmt_st = (~sdram_enable) ? `MGM_POWERUP : + (ref_req) ? `MGM_PRECHARGE : `MGM_ACTIVE; + end // case: `MGM_MODE_WT + default: begin + mgmt_idle = 0; + mgmt_req = 0; + mgmt_cmd =`SDR_DESEL; + mgmt_ba = 2'bx; + mgmt_addr = 13'bx; + ld_tmr0 = 1'b0; + tmr0_d = 4'h0; + wr_mode_set = 0; + ld_cntr1 = 1'b0; + dec_cntr1 = 1'b0; + cntr1_d = 4'b0; + set_sdr_init_done = 1'b0; + next_mgmt_st = `MGM_POWERUP; + + end // case: default + + endcase // case(mgmt_st) + + end // always @ (mgmt_st or ....) + + + +endmodule // sdr_xfr_ctl diff --git a/src/peripherals/sdram/sdr_top.bsv b/src/peripherals/sdram/sdr_top.bsv new file mode 100644 index 0000000..a33e06d --- /dev/null +++ b/src/peripherals/sdram/sdr_top.bsv @@ -0,0 +1,814 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ + +`include "defined_parameters.bsv" +`define DELAY 250 +`define SDR_RFSH_TIMER_W 12 +`define SDR_RFSH_ROW_CNT_W 3 + +`define ACTPRE_DELAY 8'h0 +`define PREACT_DELAY 8'h8 +`define ACT_RW_DELAY 8'h10 +`define EN_SDRAM 8'h18 +`define MAX_REQ 8'h20 +`define MODE_REG 8'h28 +`define CAS_LATNCY 8'h30 +`define AUTO_REFRESH 8'h38 +`define RECRY_DELAY 8'h40 +`define RFRSH_TIMER 8'h48 +`define RFRSH_ROW_CNT 8'h50 +`define SDR_INIT_DONE 8'h58 +`define SDR_WIDTH 8'h60 +`define SDR_COLBITS 8'h68 +`define SDR_SDIO_CTRL 8'h70 +`define SDR_CLK_DELAY 8'h78 +`define verbose + +package sdr_top; + +import Semi_FIFOF :: *; +import AXI4_Types :: *; +import AXI4_Fabric :: *; +import bsvmksdrc_top :: *; +import BUtils ::*; +import Connectable ::*; +import ConfigReg ::*; +import DReg::*; +import FIFOF::*; +import Clocks::*; + +interface Ifc_sdram_out; + (*always_enabled,always_ready*) + method Action ipad_sdr_din(Bit#(64) pad_sdr_din); + method Bit#(9) sdram_sdio_ctrl(); + method Bit#(64) osdr_dout(); + method Bit#(8) osdr_den_n(); + method Bool osdr_cke(); + method Bool osdr_cs_n(); + method Bool osdr_ras_n (); + method Bool osdr_cas_n (); + method Bool osdr_we_n (); + method Bit#(8) osdr_dqm (); + method Bit#(2) osdr_ba (); + method Bit#(13) osdr_addr (); + interface Clock sdram_clk; +endinterface + +interface Ifc_sdr_slave; + interface AXI4_Slave_IFC#(`PADDR, `Reg_width,`USERSPACE) axi4_slave_sdram; + interface AXI4_Slave_IFC#(`PADDR, `Reg_width,`USERSPACE) axi4_slave_cntrl_reg; + interface Ifc_sdram_out ifc_sdram_out; +endinterface + +typedef enum{ + IDLE, + WRITE_START, + WAIT_DELAY, + WRITE_FIRST, + WRITE_DATA0, + WRITE_DATA1 +} Write_state deriving(Bits, Eq, FShow); + +typedef enum{ + IDLE, + START_READ, + READ_DATA, + READ_FLUSH +} Read_state deriving(Bits, Eq,FShow); + +typedef enum { + IDLE, + START_SPLIT, + SEND_VALUE +} Write_split_states deriving(Bits, Eq, FShow); + + + +function (Bit#(9)) fn_wr_len(Bit#(8) length, Bit#(3) awsize, Bit#(3) lwr_addr); + Bit#(3) w_packet = 0; + Bit#(9) s_length = 0; + case(awsize) + + 'd0 : begin + w_packet = lwr_addr >> awsize; + s_length = ((zeroExtend(length) + zeroExtend(w_packet)) >> 3) + 1; + end + 'd1: begin + w_packet = lwr_addr >> awsize; + s_length = ((zeroExtend(length) + zeroExtend(w_packet)) >> 2) + 1; + //`ifdef verbose $display($time(),"\t SSSS w_packet %b s_lenght %h length %h", w_packet, s_length, length); `endif + end + 'd2 : begin + //w_packet = lwr_addr >> awsize; + // s_length = ((s_length + w_packets) >> 1) + 1; + s_length = zeroExtend(length >> 1) + 1; + end + 'd3 : begin + s_length = zeroExtend(length) + 1; + end + endcase + + return s_length; +endfunction + + +function Bit#(64) fn_wr_split_data(Bit#(64) data, Bit#(8) wstrb); + Bit#(64) data0 = 0; + if(wstrb[0] == 1) + data0[7:0] = data[7:0]; + else + data0[7:0] = 0; + + if(wstrb[1] == 1) + data0[15:8] = data[15:8]; + else + data0[15:8] = 0; + + if(wstrb[2] == 1) + data0[23:16] = data[23:16]; + else + data0[23:16] = 0; + + if(wstrb[3] == 1) + data0[31:24] = data[31:24]; + else + data0[31:24] = 0; + + if(wstrb[4] == 1) + data0[39:32] = data[39:32]; + else + data0[39:32] = 0; + + if(wstrb[5] == 1) + data0[47:40] = data[47:40]; + else + data0[47:40] = 0; + + if(wstrb[6] == 1) + data0[55:48] = data[55:48]; + else + data0[55:48] = 0; + + if(wstrb[7] == 1) + data0[63:56] = data[63:56]; + else + data0[63:56] = 0; + + return data0; +endfunction + +function Bit#(26) fn_wr_address(Bit#(`PADDR) address); + Bit#(29) sdr_addr = address[31:3]; + return sdr_addr[25:0]; +endfunction + +function Bit#(64) fn_rd_data(Bit#(3) bsize,Bit#(4) lwr_addr,Bit#(64) data); + + case(bsize) + 'b000: begin + case(lwr_addr) + 'b000: begin + return duplicate(data[7:0]); + end + 'b001: begin + return duplicate(data[15:8]); + end + 'b010: begin + return duplicate(data[23:16]); + end + 'b011: begin + return duplicate(data[31:24]); + end + 'b100: begin + return duplicate(data[39:32]); + end + 'b101: begin + return duplicate(data[47:40]); + end + 'b110: begin + return duplicate(data[55:48]); + end + 'b111: begin + return duplicate(data[63:56]); + end + endcase + end + + 'b001: begin + case(lwr_addr) + 'b000: begin + return duplicate(data[15:0]); + end + 'b010: begin + return duplicate(data[31:16]); + end + 'b100: begin + return duplicate(data[47:32]); + end + 'b110: begin + return duplicate(data[63:48]); + end + endcase + end + + 'b010: begin + case(lwr_addr) + 'b000: begin + return duplicate(data[31:0]); + end + 'b100: begin + return duplicate(data[63:32]); + end + endcase + end + + 'b011: begin + return data; + end + endcase +endfunction + + + + + +(*synthesize*) + +module mksdr_axi4_slave#(Clock clk0) (Ifc_sdr_slave); + + Reset rst0 <- mkAsyncResetFromCR (0, clk0); + + Reg#(Bit#(9)) rg_delay_count <- mkReg(0,clocked_by clk0, reset_by rst0); + Reg#(Bit#(9)) rg_rd_actual_len <- mkReg(0,clocked_by clk0, reset_by rst0); + Reg#(bit) rg_app_req <- mkDReg(0,clocked_by clk0, reset_by rst0); + Reg#(bit) rg_app_req_wrap <- mkConfigReg(0,clocked_by clk0, reset_by rst0); + Reg#(Bit#(26)) rg_app_req_addr <- mkConfigReg(0,clocked_by clk0, reset_by rst0); + Reg#(Bit#(4)) rg_cfg_sdr_tras_d <- mkConfigReg(4'h4,clocked_by clk0, reset_by rst0); + Reg#(Bit#(4)) rg_cfg_sdr_trp_d <- mkConfigReg(4'h2,clocked_by clk0, reset_by rst0); + Reg#(Bit#(4)) rg_cfg_sdr_trcd_d <- mkConfigReg(4'h2,clocked_by clk0, reset_by rst0); + Reg#(bit) rg_cfg_sdr_en <- mkConfigReg(1'h0,clocked_by clk0, reset_by rst0); + Reg#(Bit#(2)) rg_cfg_req_depth <- mkConfigReg(2'h3,clocked_by clk0, reset_by rst0); + Reg#(Bit#(13)) rg_cfg_sdr_mode_reg <- mkConfigReg(13'h032,clocked_by clk0, reset_by rst0); + Reg#(Bit#(3)) rg_cfg_sdr_cas <- mkConfigReg(3'h3,clocked_by clk0, reset_by rst0); + Reg#(Bit#(4)) rg_cfg_sdr_trcar_d <- mkConfigReg(4'h7,clocked_by clk0, reset_by rst0); + Reg#(Bit#(4)) rg_cfg_sdr_twr_d <- mkConfigReg(4'h1,clocked_by clk0, reset_by rst0); + Reg#(Bit#(2)) rg_cfg_sdr_width <- mkConfigReg(2'b0,clocked_by clk0, reset_by rst0); + Reg#(Bit#(2)) rg_cfg_colbits <- mkConfigReg(2'b01,clocked_by clk0, reset_by rst0); + Reg#(Bit#(9)) rg_cfg_sdio_ctrl <- mkConfigReg(9'b000100011,clocked_by clk0, reset_by rst0); + Reg#(Bit#(8)) rg_cfg_sdr_clk_delay <- mkConfigReg(8'b00001000,clocked_by clk0, reset_by rst0); + + Reg#(Bit#(`SDR_RFSH_TIMER_W )) rg_cfg_sdr_rfsh <- mkConfigReg(12'h100,clocked_by clk0, reset_by rst0); + Reg#(Bit#(`SDR_RFSH_ROW_CNT_W)) rg_cfg_sdr_rfmax <- mkConfigReg(3'h6,clocked_by clk0, reset_by rst0); + Reg#(Bit#(9)) rg_app_req_len <- mkConfigReg(0,clocked_by clk0, reset_by rst0); + Reg#(Bit#(4)) rg_lwraddr <- mkConfigReg(0,clocked_by clk0, reset_by rst0); + Reg#(Bit#(3)) rg_arsize <- mkConfigReg(0,clocked_by clk0, reset_by rst0); + Reg#(bit) rg_app_req_wr_n <- mkConfigReg(0,clocked_by clk0, reset_by rst0); + Reg#(Bit#(8)) rg_app_wr_en_n <- mkDWire(8'hFF,clocked_by clk0, reset_by rst0); + Reg#(Bit#(64)) rg_app_wr_data <- mkDWire(0,clocked_by clk0, reset_by rst0); + Wire#(Bool) wr_sdr_init_done <- mkDWire(False,clocked_by clk0, reset_by rst0); + Wire#(Bool) wr_app_req_ack <- mkDWire(False,clocked_by clk0, reset_by rst0); + Wire#(Bool) wr_app_wr_next_req <- mkDWire(False,clocked_by clk0, reset_by rst0); + Wire#(Bool) wr_app_rd_valid <- mkDWire(False,clocked_by clk0, reset_by rst0); + Wire#(Bool) wr_app_last_rd <- mkDWire(False,clocked_by clk0, reset_by rst0); + Wire#(Bool) wr_app_last_wr <- mkDWire(False,clocked_by clk0, reset_by rst0); + Wire#(Bit#(64)) wr_app_rd_data <- mkWire(clocked_by clk0, reset_by rst0); + + + Reg#(Bit#(4)) rg_rid <- mkReg(0, clocked_by clk0, reset_by rst0); + Reg#(bit) rg_rd_not_active_flag <- mkSyncRegToCC(0,clk0, rst0); + Reg#(Bit#(4)) rg_ctrl_rid <- mkReg(0); + Reg#(Bit#(4)) rg_wid <- mkReg(0); + + Reg#(Write_split_states) rg_wr_split_states <- mkReg(IDLE); + Reg#(Bit#(3)) rg_awsize <- mkReg(0); + Reg#(Bit#(9)) rg_ac_count <- mkReg(0); + Reg#(Bit#(6)) rg_single_burst <- mkReg(0); + Reg#(Bit#(64)) rg_wr_ac_data <- mkReg(0); + Reg#(Bit#(8)) rg_wr_ac_wstrb <- mkReg(0); + Reg#(Bit#(4)) rg_wr_lwr_addr <- mkReg(0); + Reg#(Bit#(9)) rg_local_actual_wr_length <- mkReg(0); + Reg#(Bit#(9)) rg_actual_wr_length <- mkSyncRegFromCC(0,clk0); + Reg#(Bit#(32)) rg_wr_address <- mkSyncRegFromCC(0,clk0); + + Reg#(Bit#(3)) rg_awsize_sclk <- mkSyncRegFromCC(0,clk0); + + Reg#(Bit#(9)) rg_burst_counter <- mkReg(0); + + Bool burst_eq = (rg_burst_counter == rg_local_actual_wr_length); + + Reg#(Bit#(3)) rg_packets <- mkReg(0); + Reg#(Bit#(3)) rg_packet_counter <- mkReg(0); + + + Reg#(Write_state) rg_write_states <- mkReg(IDLE,clocked_by clk0, reset_by rst0); + Reg#(Read_state) rg_read_states <- mkReg(IDLE,clocked_by clk0, reset_by rst0); + + FIFOF#(AXI4_Wr_Addr#(`PADDR,`USERSPACE)) ff_wr_addr <- mkSizedFIFOF(13); + FIFOF#(AXI4_Wr_Data#(`Reg_width)) ff_wr_data <- mkSizedFIFOF(13); + SyncFIFOIfc#(Bit#(`Reg_width)) ff_ac_wr_data <- mkSyncFIFOFromCC(13,clk0); + SyncFIFOIfc#(Bit#(8)) ff_ac_wr_wstrb <- mkSyncFIFOFromCC(13,clk0); + + SyncFIFOIfc#(Bool) ff_sync_write_response<-mkSyncFIFOToCC(1,clk0,rst0); + + //FIFOF#(AXI4_Rd_Addr#(`PADDR,`USERSPACE)) ff_rd_addr <- mkSizedFIFOF(3); + FIFOF#(Bit#(64)) ff_rd_data <- mkSizedFIFOF(86,clocked_by clk0, reset_by rst0); + SyncFIFOIfc#(AXI4_Rd_Addr#(`PADDR,`USERSPACE)) ff_rd_addr <- mkSyncFIFOFromCC(30,clk0); + SyncFIFOIfc#(AXI4_Rd_Data#(`Reg_width,`USERSPACE)) ff_sync_read_response <-mkSyncFIFOToCC(13,clk0,rst0); + + SyncFIFOIfc#(Tuple2#(Bit#(`PADDR),Bit#(`Reg_width))) ff_sync_ctrl_write<- mkSyncFIFOFromCC(1,clk0); + SyncFIFOIfc#(Bit#(`PADDR)) ff_sync_ctrl_read<- mkSyncFIFOFromCC(1,clk0); + SyncFIFOIfc#(Bit#(`Reg_width)) ff_sync_ctrl_read_response<- mkSyncFIFOToCC(1,clk0,rst0); + +// Polling Registers + Reg#(Bit#(2)) rg_poll_cnt <- mkReg(0,clocked_by clk0, reset_by rst0); + Reg#(Bool) rg_polling_status <- mkSyncRegToCC(False,clk0,rst0); + Reg#(Bool) rg_polling_status_clk0 <- mkReg(False,clocked_by clk0, reset_by rst0); + Reg#(Bool) rg_rd_trnc_flg <- mkReg(False); + Reg#(Bool) rg_wr_trnc_flg <- mkReg(False); + Reg#(bit) rg_odd_len <- mkReg(0); + + AXI4_Slave_Xactor_IFC #(`PADDR, `Reg_width, `USERSPACE) s_xactor_sdram <- mkAXI4_Slave_Xactor; + AXI4_Slave_Xactor_IFC #(`PADDR, `Reg_width, `USERSPACE) s_xactor_cntrl_reg <- mkAXI4_Slave_Xactor; + Ifc_sdram sdr_cntrl <- mksdrc_top(clocked_by clk0, reset_by rst0); + + function Action fn_wr_cntrl_reg(Bit#(64) data, Bit#(8) address); + action + case(address) + + `ACTPRE_DELAY : rg_cfg_sdr_tras_d <= data[3:0]; + + `PREACT_DELAY : rg_cfg_sdr_trp_d <= data[3:0]; + + `ACT_RW_DELAY : rg_cfg_sdr_trcd_d <= data[3:0]; + + `EN_SDRAM : rg_cfg_sdr_en <= data[0]; + + `MAX_REQ : rg_cfg_req_depth <= data[1:0]; + + `MODE_REG : rg_cfg_sdr_mode_reg <= data[12:0]; + + `CAS_LATNCY : rg_cfg_sdr_cas <= data[2:0]; + + `AUTO_REFRESH : rg_cfg_sdr_trcar_d <= data[3:0]; + + `RECRY_DELAY : rg_cfg_sdr_twr_d <= data[3:0]; + + `RFRSH_TIMER : rg_cfg_sdr_rfsh <= data[11:0]; + + `RFRSH_ROW_CNT : rg_cfg_sdr_rfmax <= data[2:0]; + + `SDR_WIDTH : rg_cfg_sdr_width <= data [1:0]; + + `SDR_COLBITS : rg_cfg_colbits <= data [1:0]; + + `SDR_SDIO_CTRL : rg_cfg_sdio_ctrl <= data [8:0]; + + `SDR_CLK_DELAY : rg_cfg_sdr_clk_delay <= data [7:0]; + + default : noAction; + endcase + endaction + endfunction + + + function Bit#(64) fn_rd_cntrl_reg(Bit#(8) address); + case(address) + + `ACTPRE_DELAY : return extend(rg_cfg_sdr_tras_d); + + `PREACT_DELAY : return extend(rg_cfg_sdr_trp_d); + + `ACT_RW_DELAY : return extend(rg_cfg_sdr_trcd_d); + + `EN_SDRAM : return extend(rg_cfg_sdr_en); + + `MAX_REQ : return extend(rg_cfg_req_depth); + + `MODE_REG : return extend(rg_cfg_sdr_mode_reg); + + `CAS_LATNCY : return extend(rg_cfg_sdr_cas); + + `AUTO_REFRESH : return extend(rg_cfg_sdr_trcar_d); + + `RECRY_DELAY : return extend(rg_cfg_sdr_twr_d); + + `RFRSH_TIMER : return extend(rg_cfg_sdr_rfsh); + + `RFRSH_ROW_CNT : return extend(rg_cfg_sdr_rfmax); + + `SDR_INIT_DONE : return extend(pack(wr_sdr_init_done)); + + `SDR_WIDTH : return extend(rg_cfg_sdr_width); + + `SDR_COLBITS : return extend(rg_cfg_colbits); + + `SDR_SDIO_CTRL : return extend(rg_cfg_sdio_ctrl); + + `SDR_CLK_DELAY : return extend(rg_cfg_sdr_clk_delay); + + endcase + endfunction + +//(*preempts="(rl_pop_read_request, rl_send_rd_data, rl_send_read_data, rl_flush_redundant_data), rl_write_transaction_write_start"*) + + rule rl_for_writing_ctrl_reg(ff_sync_ctrl_write.notFull); + let aw <- pop_o(s_xactor_cntrl_reg.o_wr_addr); + let w <- pop_o(s_xactor_cntrl_reg.o_wr_data); + `ifdef verbose $display($time,"\tSDRAM: control_reg written addr %x data %x", aw.awaddr, w.wdata); `endif + ff_sync_ctrl_write.enq(tuple2(aw.awaddr,w.wdata)); + let w_resp = AXI4_Wr_Resp {bresp: AXI4_OKAY, buser: 0, bid: aw.awid}; + s_xactor_cntrl_reg.i_wr_resp.enq(w_resp); + endrule + + rule rl_perform_write_to_ctrl(ff_sync_ctrl_write.notEmpty); + let {awaddr,wdata}=ff_sync_ctrl_write.first; + `ifdef verbose $display("\tSDRAM: "); `endif + ff_sync_ctrl_write.deq; +`ifdef verbose $display($time,"\tSDRAM: Actually writing data: %h to addr: %h", wdata, awaddr); `endif + fn_wr_cntrl_reg(wdata , truncate(awaddr)); + endrule + + rule rl_for_read_cntrl_reg; + let ar <- pop_o(s_xactor_cntrl_reg.o_rd_addr); + ff_sync_ctrl_read.enq(ar.araddr); + rg_ctrl_rid<=ar.arid; + endrule + + rule rl_send_ctrl_read_response(ff_sync_ctrl_read.notEmpty); + ff_sync_ctrl_read_response.enq(fn_rd_cntrl_reg(truncate(ff_sync_ctrl_read.first))); + ff_sync_ctrl_read.deq; + endrule + + rule sync_ctr_response(ff_sync_ctrl_read_response.notEmpty); + ff_sync_ctrl_read_response.deq; + let r = AXI4_Rd_Data {rresp: AXI4_OKAY, rdata:ff_sync_ctrl_read_response.first , rlast: True, ruser: 0, rid: rg_ctrl_rid}; + s_xactor_cntrl_reg.i_rd_data.enq(r); + endrule + + rule rl_direct_connection_insdram; + sdr_cntrl.iapp_req(rg_app_req); + sdr_cntrl.iapp_req_wrap(rg_app_req_wrap); + sdr_cntrl.iapp_req_addr(rg_app_req_addr); + sdr_cntrl.iapp_req_len(rg_app_req_len); + sdr_cntrl.iapp_req_wr_n(rg_app_req_wr_n); + sdr_cntrl.iapp_wr_data(rg_app_wr_data); + sdr_cntrl.iapp_wr_en_n(rg_app_wr_en_n); + endrule + + rule rl_direct_connection_outsdram; + wr_sdr_init_done <= sdr_cntrl.osdr_init_done ; + wr_app_req_ack <= sdr_cntrl.oapp_req_ack (); + wr_app_wr_next_req <= sdr_cntrl.oapp_wr_next_req (); + wr_app_rd_valid <= sdr_cntrl.oapp_rd_valid (); + wr_app_last_rd <= sdr_cntrl.oapp_last_rd (); + wr_app_last_wr <= sdr_cntrl.oapp_last_wr (); + wr_app_rd_data <= sdr_cntrl.oapp_rd_data (); + endrule + + rule rl_direct_connection_config_reg; + sdr_cntrl.icfg_sdr_tras_d(rg_cfg_sdr_tras_d); + sdr_cntrl.icfg_sdr_trp_d(rg_cfg_sdr_trp_d); + sdr_cntrl.icfg_sdr_trcd_d(rg_cfg_sdr_trcd_d); + sdr_cntrl.icfg_sdr_en(rg_cfg_sdr_en); + sdr_cntrl.icfg_req_depth(rg_cfg_req_depth); + sdr_cntrl.icfg_sdr_mode_reg(rg_cfg_sdr_mode_reg); + sdr_cntrl.icfg_sdr_cas(rg_cfg_sdr_cas); + sdr_cntrl.icfg_sdr_trcar_d(rg_cfg_sdr_trcar_d); + sdr_cntrl.icfg_sdr_twr_d(rg_cfg_sdr_twr_d); + sdr_cntrl.icfg_sdr_rfsh(rg_cfg_sdr_rfsh); + sdr_cntrl.icfg_sdr_rfmax(rg_cfg_sdr_rfmax); + sdr_cntrl.icfg_sdr_width(rg_cfg_sdr_width); + sdr_cntrl.icfg_colbits(rg_cfg_colbits); + endrule + + rule rl_intial_polling(rg_polling_status_clk0 == False && wr_sdr_init_done == True); + `ifdef verbose $display($time,"\tSDRAM: POLLING MODE: %d",rg_poll_cnt); `endif + case (rg_poll_cnt) + 0: begin + rg_app_req <= 1; + rg_app_req_addr <= 0; + rg_app_req_len <= 1; + rg_app_req_wr_n <= 0; + rg_app_wr_en_n <= 'hFF; + rg_app_wr_data <= 0; + rg_poll_cnt <= rg_poll_cnt + 1; + end + 1: begin + rg_app_req <= 1; + rg_app_req_addr <= 0; + rg_app_req_len <= 1; + rg_app_req_wr_n <= 0; + rg_app_wr_en_n <= 'hFF; + rg_app_wr_data <= 0; + rg_poll_cnt <= rg_poll_cnt + 1; + end + 2: begin + rg_app_req <= 0; + rg_app_req_addr <= 0; + rg_app_wr_en_n <= 'hFF; + rg_app_wr_data <= 0; + if(wr_app_wr_next_req == True) + rg_poll_cnt <= rg_poll_cnt + 1; + end + 3: begin + rg_polling_status <= True; + rg_polling_status_clk0<=True; + end + endcase + endrule + +/******************* WRITE TRANSACTION ****************/ + + rule rl_parallel_data_enq(rg_polling_status == True && rg_rd_trnc_flg == False); + let aw <- pop_o(s_xactor_sdram.o_wr_addr); + let w <- pop_o(s_xactor_sdram.o_wr_data); + ff_wr_addr.enq(aw); + ff_wr_data.enq(w); + rg_wr_trnc_flg <= True; + `ifdef verbose $display($time,"\tSDRAM: WRITE_FIRST Parallel enq %h addr: %h",w.wdata,aw.awaddr); `endif + endrule + + rule rl_write_split_state(rg_wr_split_states == IDLE); + let aw = ff_wr_addr.first(); + if(aw.awsize != 3) begin + rg_actual_wr_length <= fn_wr_len(aw.awlen, aw.awsize, aw.awaddr[2:0]); + + rg_local_actual_wr_length <= extend(aw.awlen); + end + else begin + rg_actual_wr_length <= extend(aw.awlen) + 1; + rg_local_actual_wr_length <= extend(aw.awlen); + end + rg_wid <= aw.awid; + rg_awsize <= aw.awsize; + rg_awsize_sclk <= aw.awsize; + rg_wr_address <= aw.awaddr; + rg_wr_lwr_addr <= extend(aw.awaddr[2:0]); + rg_wr_split_states <= START_SPLIT; + rg_packets <= (aw.awsize==0)?7:(aw.awsize==1)?3:(aw.awsize == 2)? 1 : (aw.awsize == 3) ? 0 : 0; //(64 >> (aw.awsize+4)); //1 << ~aw.awsize[1:0]; + rg_packet_counter <= (aw.awaddr[2:0]) >> aw.awsize; + `ifdef verbose $display($time,"Initial Values -- Starting IDLE to START_SPLIT"); `endif + //$display("Initial Values: rg_packets: %h rg_packet_counter: %h ",(64>>(aw.awsize+4)),aw.awaddr[2:0]>>aw.awsize); + rg_burst_counter <= 0; + endrule + + + rule rl_write_data_splitting0(rg_wr_split_states == START_SPLIT && rg_awsize != 3); + rg_wr_ac_data <= rg_wr_ac_data | fn_wr_split_data(ff_wr_data.first.wdata,ff_wr_data.first.wstrb); + rg_wr_ac_wstrb <= rg_wr_ac_wstrb | ff_wr_data.first.wstrb; + rg_burst_counter <= rg_burst_counter + 1; + `ifdef verbose $display($time,"burst_eq: %h rg_packets: %h rg_packet_counter: %d rg_burst_counter: %d rg_local_actual_wr_length %d rg_wr_ac_data %h rg_wr_ac_wstrb %b",burst_eq,rg_packets,rg_packet_counter,rg_burst_counter,rg_local_actual_wr_length, fn_wr_split_data(ff_wr_data.first.wdata,ff_wr_data.first.wstrb), ff_wr_data.first.wstrb); `endif + if(burst_eq || rg_packets == rg_packet_counter) begin + rg_wr_split_states <= SEND_VALUE; + end + else begin + rg_packet_counter <= rg_packet_counter + 1; + end + ff_wr_data.deq(); + ff_wr_addr.deq(); + endrule + + rule rl_write_data_splitting1(rg_wr_split_states == SEND_VALUE && rg_awsize != 3); + `ifdef verbose $display($stime,"Splitting1 Enqueued data rg_wr_ac_data %h rg_wr_ac_wstrb %b", rg_wr_ac_data, rg_wr_ac_wstrb); `endif + ff_ac_wr_data.enq(rg_wr_ac_data); + ff_ac_wr_wstrb.enq(rg_wr_ac_wstrb); + rg_wr_ac_data <= 0; + rg_wr_ac_wstrb <= 0; + rg_wr_lwr_addr <= 0; + rg_packet_counter <= 0; + `ifdef verbose $display($time,"Sending Value to the SDRAM"); `endif + rg_wr_split_states <= START_SPLIT; + endrule + + + rule rl_write_data_spliting3(rg_wr_split_states == START_SPLIT && rg_awsize == 3); + ff_ac_wr_data.enq(ff_wr_data.first.wdata); + ff_ac_wr_wstrb.enq(ff_wr_data.first.wstrb); + ff_wr_data.deq(); + ff_wr_addr.deq(); + endrule + + + rule rl_start_write_transaction(rg_write_states == IDLE && wr_sdr_init_done == True); + if(ff_ac_wr_data.notEmpty()) begin + if(rg_awsize_sclk == 0) + rg_write_states <= WAIT_DELAY; + else + rg_write_states <= WRITE_START; + `ifdef verbose $display($time,"\tSDRAM: Going to write start state"); `endif + end + endrule + + rule rl_wait_delay(rg_write_states == WAIT_DELAY); + if(rg_delay_count == 14) begin + rg_write_states <= WRITE_START; + rg_delay_count <= 0; + end + else + rg_delay_count <= rg_delay_count + 1; + endrule + + rule rl_write_transaction_write_start(rg_write_states == WRITE_START && wr_sdr_init_done == True && rg_read_states == IDLE); + `ifdef verbose $display($time,"\tSDRAM: WRITE_START state Controller Length %d",rg_actual_wr_length); `endif + rg_app_req <= 1; + rg_app_req_addr <= fn_wr_address(rg_wr_address); + rg_app_req_len <= extend(rg_actual_wr_length); + rg_app_req_wr_n <= 0; + rg_app_wr_data <= 0; + rg_app_wr_en_n <= 8'hFF; + rg_write_states <= WRITE_FIRST; + rg_delay_count <= extend(rg_actual_wr_length) - 1; + endrule + + rule rl_write_transaction_write_first(rg_write_states == WRITE_FIRST && wr_app_wr_next_req == False); + `ifdef verbose $display($time,"\tSDRAM: WRITE_FIRST state next is false data %x",ff_ac_wr_data.first); `endif + rg_app_req <= 0; + rg_app_wr_en_n <= ~(ff_ac_wr_wstrb.first()); + rg_app_wr_data <= ff_ac_wr_data.first(); + endrule + + rule rl_write_transaction_write_data(rg_write_states == WRITE_FIRST && wr_app_wr_next_req == True); + `ifdef verbose $display($time,"\tSDRAM: WRITE_DATA state next is true sending data %x %b",ff_ac_wr_data.first,wr_app_wr_next_req); `endif + rg_app_req <= 0; + rg_app_wr_data <= ff_ac_wr_data.first(); + rg_app_wr_en_n <= ~(ff_ac_wr_wstrb.first()); + ff_ac_wr_data.deq; + ff_ac_wr_wstrb.deq; + rg_delay_count <= rg_delay_count - 1; + if(rg_delay_count == 0) begin + rg_write_states <= IDLE; + ff_sync_write_response.enq(True); + end + endrule + + rule synchronize_write_response(ff_sync_write_response.notEmpty); + ff_sync_write_response.deq; + let w_resp = AXI4_Wr_Resp {bresp: AXI4_OKAY, buser: 0, bid: rg_wid}; //TODO user value is null + s_xactor_sdram.i_wr_resp.enq(w_resp); + rg_wr_split_states <= IDLE; + rg_ac_count <= 0; + rg_wr_trnc_flg <= False; + `ifdef verbose $display($time,"\tSDRAM: WRITE complete state true"); `endif + endrule + + /****************** Read Transaction ********************/ + // `ifdef verbose + // rule display_read_states; + // $display($time,"\tSDRAM: Read State: ",fshow(rg_read_states)); + // endrule + // `endif + rule rl_paralel_read_req_enq(rg_polling_status == True && rg_wr_trnc_flg == False); + let ar <- pop_o(s_xactor_sdram.o_rd_addr); + ff_rd_addr.enq(ar); + rg_rd_trnc_flg <= True; + `ifdef verbose $display($time,"\tSDRAM: Got Read request from AXI for AddresS: %h",ar.araddr); `endif + endrule + + rule rl_read_idle_state(rg_read_states == IDLE); + if(ff_rd_addr.notEmpty() == True) begin + rg_read_states <= START_READ; + rg_rd_not_active_flag <= 0; + `ifdef verbose $display($time,"\tSDRAM: READ IDLE state"); `endif + end + + endrule + + rule rl_pop_read_request(wr_sdr_init_done == True && rg_read_states == START_READ && (rg_write_states == IDLE || rg_write_states == WRITE_START)); + let ar = ff_rd_addr.first; + `ifdef verbose $display($time,"\tSDRAM: STAR_READ state ar.arlen %d ar.arsize %d ar.araddr %h ar.arburst %b", ar.arlen,ar.arsize, ar.araddr, ar.arburst); `endif + + rg_app_req <= 1; + if(ar.arburst == 2) + rg_app_req_wrap <= 1; + else + rg_app_req_wrap <= 0; + rg_lwraddr <= extend(ar.araddr[2:0]); + rg_arsize <= ar.arsize; + rg_app_req_addr <= fn_wr_address(ar.araddr); + rg_app_req_len <= fn_wr_len(ar.arlen, ar.arsize, ar.araddr[2:0]); + rg_rd_actual_len <= extend(ar.arlen); + rg_app_req_wr_n <= 1; + rg_delay_count <= 0; + rg_read_states <= READ_DATA; + rg_rid <= ar.arid; + `ifdef verbose $display($time,"\t SSSSS SDRAM START_READ length "); `endif + endrule + + rule rl_send_rd_data(wr_app_rd_valid == True); + `ifdef verbose $display($time,"\tSDRAM: READ DATA1 state %x",wr_app_rd_data); `endif + ff_rd_data.enq(wr_app_rd_data); + endrule + + rule rl_send_read_data(rg_read_states==READ_DATA); + `ifdef verbose $display($time,"\tSDRAM: Response from BFM. RequestLenght: %d CurrentCount: %d",rg_rd_actual_len,rg_delay_count); `endif + rg_app_req_wrap <= 0; + if(rg_lwraddr < 8) begin + let r = AXI4_Rd_Data {rresp: AXI4_OKAY, rdata: fn_rd_data(rg_arsize, rg_lwraddr, ff_rd_data.first), rlast: (rg_rd_actual_len == rg_delay_count), ruser: 0, rid: rg_rid}; + ff_sync_read_response.enq(r); + ff_rd_addr.deq; + if(rg_arsize!=3) + rg_lwraddr <= rg_lwraddr + (1 << rg_arsize); + else + ff_rd_data.deq; + `ifdef verbose $display($time,"\tSDRAM: SENDING READ DATA : %h, rg_lwraddr %b rg_arsize %d", fn_rd_data(rg_arsize, rg_lwraddr, ff_rd_data.first),rg_lwraddr, rg_arsize); `endif + `ifdef verbose $display($time,"\tSDRAM: Removing Request for Addr : %h",ff_rd_addr.first.araddr); `endif + if(rg_delay_count == rg_rd_actual_len) begin + `ifdef verbose $display($time,"\tSDRAM: SENT ALL READ DATA state rg_delay_count %d rg_rd_actual_len %d", rg_delay_count, rg_rd_actual_len); `endif + rg_read_states <= READ_FLUSH; + rg_rd_not_active_flag <= 1; + rg_delay_count <= 0; + end + else + rg_delay_count <= rg_delay_count + 1; + end + else if(rg_lwraddr > 7) begin + `ifdef verbose $display($time,"\tSDRAM: Dequeuing ff READ"); `endif + rg_lwraddr <= 0; + ff_rd_data.deq; + end + endrule + + rule rl_flush_redundant_data(rg_read_states == READ_FLUSH); + ff_rd_data.clear(); + rg_read_states <= IDLE; + endrule + + rule send_synchronized_read_response(ff_sync_read_response.notEmpty); + let r=ff_sync_read_response.first; + `ifdef verbose $display($time,"\tSDRAM: Sending Read response: %h rlast: %b",r.rdata,r.rlast); `endif + ff_sync_read_response.deq; + if(rg_rd_not_active_flag == 1) + rg_rd_trnc_flg <= False; + s_xactor_sdram.i_rd_data.enq(r); + endrule + + + + + + interface Ifc_sdram_out ifc_sdram_out; + + method Action ipad_sdr_din(Bit#(64) pad_sdr_din); + sdr_cntrl.ipad_sdr_din(pad_sdr_din); + endmethod + method Bit#(9) sdram_sdio_ctrl(); + return rg_cfg_sdio_ctrl; + endmethod + method Bit#(64) osdr_dout(); + return sdr_cntrl.osdr_dout(); + endmethod + method Bit#(8) osdr_den_n(); + return sdr_cntrl.osdr_den_n(); + endmethod + method Bool osdr_cke(); + return sdr_cntrl.osdr_cke(); + endmethod + + method Bool osdr_cs_n(); + return sdr_cntrl.osdr_cs_n(); + endmethod + + method Bool osdr_ras_n (); + return sdr_cntrl.osdr_ras_n; + endmethod + + method Bool osdr_cas_n (); + return sdr_cntrl.osdr_cas_n; + endmethod + + method Bool osdr_we_n (); + return sdr_cntrl.osdr_we_n; + endmethod + + method Bit#(8) osdr_dqm (); + return sdr_cntrl.osdr_dqm; + endmethod + + method Bit#(2) osdr_ba (); + return sdr_cntrl.osdr_ba; + endmethod + + method Bit#(13) osdr_addr (); + return sdr_cntrl.osdr_addr; + endmethod + + interface sdram_clk = clk0; + endinterface + + + interface axi4_slave_sdram = s_xactor_sdram.axi_side; + interface axi4_slave_cntrl_reg = s_xactor_cntrl_reg.axi_side; + +endmodule +endpackage diff --git a/src/peripherals/sdram/tb_bsv_wrapper.bsv b/src/peripherals/sdram/tb_bsv_wrapper.bsv new file mode 100644 index 0000000..a834b29 --- /dev/null +++ b/src/peripherals/sdram/tb_bsv_wrapper.bsv @@ -0,0 +1,365 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +package tb_bsv_wrapper; + +import Semi_FIFOF :: *; +import AXI4_Types :: *; +import AXI4_Fabric :: *; +import bsvmksdram_model_wrapper :: *; +import Connectable :: *; +`include "defined_parameters.bsv" + +`define DELAY 10200 + + interface Ifc_tb_sdram_in; + + method Action iAddr(Bit#(11) addr); + method Action iBa(Bit#(2) ba); + method Action iCke(bit cke); + method Action iClk(bit clk); + method Action iCs_n(bit cs_n); + method Action iRas_n(bit ras_n); + method Action iCas_n(bit cas_n); + method Action iWe_n(bit we_n); + method Action iDqm(Bit#(8) dqm); + + endinterface + +interface Ifc_tb_bsv_wrapper; + interface AXI4_Master_IFC#(`PADDR, `Reg_width, `USERSPACE) axi4_sdram; + interface AXI4_Master_IFC#(`PADDR, `Reg_width, `USERSPACE) axi4_cntrl_reg; + interface Ifc_tb_sdram_in ifc_tb_sdram_in; + interface Inout#(Bit#(32)) dq_0 ; + interface Inout#(Bit#(32)) dq_1; +endinterface + + +module mktb_bsv_wrapper(Ifc_tb_bsv_wrapper); + + Reg#(Bit#(9)) rg_burst_count <- mkReg(0); + Reg#(bit) rg_tb_app_req <- mkReg(0); + Reg#(bit) rg_tb_app_wr_n <- mkRegU(); + Reg#(Bit#(64)) rg_tb_app_req_addr <- mkReg(0); + Reg#(Bit#(8)) rg_tb_app_req_len <- mkReg(0); + Reg#(Bit#(64)) rg_tb_wr_data <- mkReg(0); + Reg#(Bit#(8)) rg_tb_wr_en_n <- mkReg(0); + Reg#(Bit#(64)) rg_tb_rd_data <- mkReg(0); + Reg#(Bit#(5)) rg_state_cnt <- mkReg(0); + Reg#(Bit#(64)) rg_tb_app_rd_addr <- mkReg(0); + Reg#(Bit#(8)) rg_tb_app_rd_len <- mkReg(0); + Reg#(Bit#(16)) rg_delay_count <- mkReg(0); + Reg#(bit) rg_ff <- mkReg(0); + Reg#(Bit#(2)) rg_bmode <- mkReg(0); + + Reg#(Bit#(64)) rg_tb_cntrl_addr <- mkReg(0); + Reg#(Bit#(64)) rg_tb_cntrl_data <- mkReg(4); + + AXI4_Master_Xactor_IFC #(`PADDR,`Reg_width,`USERSPACE) m_xactor_sdram <- mkAXI4_Master_Xactor; + AXI4_Master_Xactor_IFC #(`PADDR,`Reg_width,`USERSPACE) m_xactor_cntrl_reg <- mkAXI4_Master_Xactor; + + Ifc_sdram_model sdram_model_0 <- mksdram_model_wrapper; + Ifc_sdram_model sdram_model_1 <- mksdram_model_wrapper; + + function Action burst_write(Bit#(64) address, Bit#(8) bl); + return + action + rg_tb_app_req <= 1; + rg_tb_app_wr_n <= 0; + rg_tb_app_req_addr <= address; + rg_tb_app_req_len <= bl; + +// for(Integer i = 0;i <= bl; i++) begin + rg_tb_wr_en_n <= 8'hFF; + // end + endaction; + endfunction + + function Action data_change(bit ff); + return + action + if(ff == 1) + rg_tb_wr_data <= 64'hDEADBEEFBABECAFE; + else + rg_tb_wr_data <= 64'hBABECAFEDEADBEEF; + + rg_ff <= ~rg_ff; + + endaction; + endfunction + + + function Action burst_read(Bit#(64) address, Bit#(8) bl); + return + action + rg_tb_app_req <= 1; + rg_tb_app_wr_n <= 1; + rg_tb_app_rd_addr <= address; + rg_tb_app_rd_len <= bl; + endaction; + + endfunction + + function Action fn_send_cntrl_reg(Bit#(9) count); + action + case(count) + 0: begin + rg_tb_cntrl_addr <= 64'h00; + rg_tb_cntrl_data <= 64'h4; + end + 1: begin + rg_tb_cntrl_addr <= 64'h08; + rg_tb_cntrl_data <= 64'h4; + end + 2: begin + rg_tb_cntrl_addr <= 64'h10; + rg_tb_cntrl_data <= 64'h2; + end + 3: begin + rg_tb_cntrl_addr <= 64'h18; + rg_tb_cntrl_data <= 64'h1; + end + 4: begin + rg_tb_cntrl_addr <= 64'h20; + rg_tb_cntrl_data <= 64'h3; + end + 5: begin + rg_tb_cntrl_addr <= 64'h28; + rg_tb_cntrl_data <= 64'h32; + end + 6: begin + rg_tb_cntrl_addr <= 64'h30; + rg_tb_cntrl_data <= 64'h3; + end + 7: begin + rg_tb_cntrl_addr <= 64'h38; + rg_tb_cntrl_data <= 64'h7; + end + 8: begin + rg_tb_cntrl_addr <= 64'h40; + rg_tb_cntrl_data <= 64'h1; + end + 9: begin + rg_tb_cntrl_addr <= 64'h48; + rg_tb_cntrl_data <= 64'h100; + end + 10: begin + rg_tb_cntrl_addr <= 64'h50; + rg_tb_cntrl_data <= 64'h6; + end + endcase + endaction +endfunction + + + rule rl_delay(rg_ff == 0 && rg_state_cnt == 0); + if(rg_burst_count == 300) + rg_ff <= 1; + else + rg_burst_count <= rg_burst_count + 1; + + if(rg_burst_count <= 10) begin + if(rg_burst_count == 0) begin + let aw = AXI4_Wr_Addr {awaddr: rg_tb_cntrl_addr, awprot:0, awuser:0, awlen: 10, awsize: 3, awburst: 'b01}; + m_xactor_cntrl_reg.i_wr_addr.enq(aw); + end + + let w = AXI4_Wr_Data {wdata: rg_tb_cntrl_data, wstrb: 8'h11, wlast: (rg_burst_count == 10)}; + m_xactor_cntrl_reg.i_wr_data.enq(w); + fn_send_cntrl_reg(rg_burst_count + 1); + $display("%d: Sending Control register info",$stime()); + end + endrule + + rule rl_response_from_cntrl_reg; + let resp <- pop_o(m_xactor_cntrl_reg.o_wr_resp); + $display("%d: Response from control reg bus %d",$stime(),(resp.bresp == AXI4_OKAY)? 1:0); + endrule + + + + rule rl_write_request(rg_state_cnt == 0 && rg_ff == 1); + burst_write({32'b0,{8'd0,11'h0,2'b00,8'd0,3'b0}}, 8'd255); + rg_state_cnt <= rg_state_cnt + 1; + rg_burst_count <= 0; + endrule + + rule rl_read_request_gen(rg_state_cnt == 15); + burst_read({32'b0,{8'd0,11'd0,2'b00,8'hA,3'b000}}, 8'd7); + rg_state_cnt <= rg_state_cnt + 1; + rg_bmode <= 'b01; + rg_burst_count <= 0; + endrule + + rule rl_iapp_req_ack_connection(rg_state_cnt == 2 || rg_state_cnt == 5 || rg_state_cnt == 8 || rg_state_cnt == 11 || rg_state_cnt == 14 || rg_state_cnt == 27); + let resp <- pop_o(m_xactor_sdram.o_wr_resp); + $display("%d: Response from write bus %d",$stime(),(resp.bresp == AXI4_OKAY)? 1:0); + rg_state_cnt <= rg_state_cnt + 1; +// $finish(); +// tb_core.iapp_req_ack((resp.bresp == AXI4_OKAY)? 1:0 ); + endrule + + rule rl_oapp_wr_data(rg_state_cnt == 1 || rg_state_cnt == 4 || rg_state_cnt == 7 || rg_state_cnt == 10 || rg_state_cnt == 13 || rg_state_cnt == 26); + if(rg_tb_app_req_len == 0) begin + let aw = AXI4_Wr_Addr {awaddr: rg_tb_app_req_addr, awprot:0, awuser:0, awlen: extend(rg_tb_app_req_len), awsize: 2, awburst: 'b01}; + let w = AXI4_Wr_Data {wdata: 64'hDEADBEEFBABECAFE, wstrb: rg_tb_wr_en_n, wlast: True}; + m_xactor_sdram.i_wr_addr.enq(aw); + m_xactor_sdram.i_wr_data.enq(w); + $display("%d: Sending write request",$stime()); + end + else begin + if(rg_burst_count == 0) begin + let aw = AXI4_Wr_Addr {awaddr: rg_tb_app_req_addr, awprot:0, awuser: 0, awlen: extend(rg_tb_app_req_len), awsize: 2, awburst: 'b01}; + let w = AXI4_Wr_Data {wdata: 64'hDEADBEEFBABECAFE, wstrb: rg_tb_wr_en_n, wlast: False}; + data_change(rg_ff); + rg_burst_count <= rg_burst_count + 1; + m_xactor_sdram.i_wr_addr.enq(aw); + m_xactor_sdram.i_wr_data.enq(w); + + end + else if(rg_burst_count <= extend(rg_tb_app_req_len) && rg_burst_count != 0) begin + let w = AXI4_Wr_Data {wdata: rg_tb_wr_data, wstrb: rg_tb_wr_en_n, wlast: (rg_burst_count == extend(rg_tb_app_req_len))}; + rg_burst_count <= rg_burst_count + 1; + $display("%d: Sending write data %x rg_ff %b",$stime(),rg_tb_wr_data, rg_ff); + data_change(rg_ff); + m_xactor_sdram.i_wr_data.enq(w); + //tb_core.iapp_last_wr(pack(rg_burst_count == tb_core.oapp_req_len)); + end + else begin + rg_burst_count <= 0; + rg_state_cnt <= rg_state_cnt + 1; + end + end + endrule + + rule rl_next_write(rg_state_cnt == 3); + burst_write({32'b0,{8'd0,11'd1500,2'b01,8'd56,3'b0}}, 8'd246); + rg_state_cnt <= rg_state_cnt + 1; + rg_burst_count <= 0; + endrule + + rule rl_next_write1(rg_state_cnt == 6); + burst_write({32'b0,{8'd0,11'd2010,2'b01,8'd25,3'b0}}, 8'd7); + rg_state_cnt <= rg_state_cnt + 1; + rg_burst_count <= 0; + endrule + + rule rl_next_write2(rg_state_cnt == 9); + burst_write({32'b0,{8'd0,11'd1600,2'b10,8'd55,3'b0}}, 8'd4); + rg_state_cnt <= rg_state_cnt + 1; + rg_burst_count <= 0; + endrule + + rule rl_next_write3(rg_state_cnt == 12); + burst_write({32'b0,{8'd0,11'h8,2'b0,8'd5,3'b0}}, 8'd3); + rg_state_cnt <= rg_state_cnt + 1; + rg_burst_count <= 0; + endrule + + rule rl_next_write4(rg_state_cnt == 20); + burst_write({32'b0,{8'd0,11'h8,2'b01,8'd255,3'b0}}, 8'd2); + rg_state_cnt <= rg_state_cnt + 1; + rg_burst_count <= 0; + endrule + + rule rl_read_request(rg_state_cnt == 16 || rg_state_cnt == 19); + let read_request = AXI4_Rd_Addr {araddr: rg_tb_app_rd_addr, arprot: 0, aruser: 0, arlen: extend(rg_tb_app_rd_len), arsize: 3, arburst: rg_bmode}; // arburst: 00-FIXED 01-INCR 10-WRAP + m_xactor_sdram.i_rd_addr.enq(read_request); + $display("%d: Sending read request",$stime()); + rg_state_cnt <= rg_state_cnt + 1; + endrule + + rule rl_read_response(rg_state_cnt == 17 || rg_state_cnt == 20); + if(rg_burst_count == 300) begin + let response <- pop_o(m_xactor_sdram.o_rd_data); + rg_tb_rd_data <= response.rdata; + $display("%d: Read data %x",$stime(),response.rdata); + rg_tb_app_rd_len <= rg_tb_app_rd_len - 1; + if(rg_tb_app_rd_len == 0) + rg_state_cnt <= rg_state_cnt + 1; + end + else rg_burst_count <= rg_burst_count + 1; + endrule + + rule rl_read_request_gen1(rg_state_cnt == 18); + burst_read({32'b0,{8'd0,11'd0,2'b00,8'hA,3'b000}}, 8'd3); + rg_bmode <= 'b10; + rg_state_cnt <= rg_state_cnt + 1; + rg_burst_count <= 0; + endrule + + + + interface dq_0 = sdram_model_0.dq; + interface dq_1 = sdram_model_1.dq; + + interface Ifc_tb_sdram_in ifc_tb_sdram_in; + +// interface Inout#(Bit#(32)) dq = tb_core.sdr_dq; + + method Action iAddr(Bit#(11) addr); + sdram_model_0.iAddr(addr); + sdram_model_1.iAddr(addr); + endmethod + + method Action iBa(Bit#(2) ba); + sdram_model_0.iBa(ba); + sdram_model_1.iBa(ba); + endmethod + + method Action iCke(bit cke); + sdram_model_0.iCke(cke); + sdram_model_1.iCke(cke); + endmethod + + method Action iClk(bit clk); + sdram_model_0.iClk(clk); + sdram_model_1.iClk(clk); + endmethod + + method Action iCs_n(bit cs_n); + sdram_model_0.iCs_n(cs_n); + sdram_model_1.iCs_n(cs_n); + endmethod + + method Action iRas_n(bit ras_n); + sdram_model_0.iRas_n(ras_n); + sdram_model_1.iRas_n(ras_n); + endmethod + + method Action iCas_n(bit cas_n); + sdram_model_0.iCas_n(cas_n); + sdram_model_1.iCas_n(cas_n); + endmethod + + method Action iWe_n(bit we_n); + sdram_model_0.iWe_n(we_n); + sdram_model_1.iWe_n(we_n); + endmethod + + method Action iDqm(Bit#(8) dqm); + sdram_model_0.iDqm(dqm[3:0]); + sdram_model_1.iDqm(dqm[7:4]); + endmethod + + endinterface + + interface axi4_sdram = m_xactor_sdram.axi_side; + interface axi4_cntrl_reg = m_xactor_cntrl_reg.axi_side; + +endmodule +endpackage + + + + diff --git a/src/peripherals/sdram/tb_top.bsv b/src/peripherals/sdram/tb_top.bsv new file mode 100644 index 0000000..8e920a0 --- /dev/null +++ b/src/peripherals/sdram/tb_top.bsv @@ -0,0 +1,99 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +package tb_top; + +import Semi_FIFOF :: *; +import AXI4_Types :: *; +import AXI4_Fabric :: *; +import sdr_top :: *; +import tb_bsv_wrapper :: *; +import Connectable :: *; +`include "defined_parameters.bsv" + + +typedef 1 Num_Masters; +typedef 1 Num_Slaves; + +function Tuple2 #(Bool, Bit#(TLog#(Num_Slaves))) fn_addr_to_slave_num (Bit #(`PADDR) addr); + return tuple2(True, 0); +endfunction + +(*synthesize*) +module mkTb_top(Empty); + + + AXI4_Fabric_IFC #(Num_Masters, Num_Slaves, `PADDR, `Reg_width,`USERSPACE) + fabric_m <- mkAXI4_Fabric(fn_addr_to_slave_num); + AXI4_Fabric_IFC #(Num_Masters, Num_Slaves, `PADDR, `Reg_width,`USERSPACE) + fabric_c <- mkAXI4_Fabric(fn_addr_to_slave_num); + + Ifc_sdr_slave sdr_cntrl <- mksdr_axi4_slave; + + Ifc_tb_bsv_wrapper tb_wrapper <- mktb_bsv_wrapper; + + mkConnection (tb_wrapper.axi4_sdram, fabric_m.v_from_masters [0]); + mkConnection(fabric_m.v_to_slaves[0], sdr_cntrl.axi4_slave_sdram); + mkConnection (tb_wrapper.axi4_cntrl_reg, fabric_c.v_from_masters [0]); + mkConnection(fabric_c.v_to_slaves[0], sdr_cntrl.axi4_slave_cntrl_reg); + mkConnection(tb_wrapper.dq_0, sdr_cntrl.sdr_dq0); + mkConnection(tb_wrapper.dq_1, sdr_cntrl.sdr_dq1); + + + rule rl_iAddr_connection; + let in = sdr_cntrl.ifc_sdram_out.osdr_addr(); + tb_wrapper.ifc_tb_sdram_in.iAddr(truncate(in)); + endrule + + rule rl_iBa_connection; + let in = sdr_cntrl.ifc_sdram_out.osdr_ba(); + tb_wrapper.ifc_tb_sdram_in.iBa(in); + endrule + + rule rl_iCke_connection; + let in = sdr_cntrl.ifc_sdram_out.osdr_cke(); + tb_wrapper.ifc_tb_sdram_in.iCke(pack(in)); + endrule + + rule rl_iClk_connection; + let in = sdr_cntrl.ifc_sdram_out.osdr_clk(); + tb_wrapper.ifc_tb_sdram_in.iClk(in); + endrule + + rule rl_iCs_n_connection; + let in = sdr_cntrl.ifc_sdram_out.osdr_cs_n(); + tb_wrapper.ifc_tb_sdram_in.iCs_n(pack(in)); + endrule + + rule rl_iRas_n_connection; + let in = sdr_cntrl.ifc_sdram_out.osdr_ras_n(); + tb_wrapper.ifc_tb_sdram_in.iRas_n(pack(in)); + endrule + + rule rl_iCas_n_connection; + let in = sdr_cntrl.ifc_sdram_out.osdr_cas_n(); + tb_wrapper.ifc_tb_sdram_in.iCas_n(pack(in)); + endrule + + rule rl_iWe_n_connection; + let in = sdr_cntrl.ifc_sdram_out.osdr_we_n(); + tb_wrapper.ifc_tb_sdram_in.iWe_n(pack(in)); + endrule + + rule rl_iDqm_connection; + let in = sdr_cntrl.ifc_sdram_out.osdr_dqm(); + tb_wrapper.ifc_tb_sdram_in.iDqm(extend(in)); + endrule + + endmodule + endpackage diff --git a/src/peripherals/tdm/TCM.bsv b/src/peripherals/tdm/TCM.bsv new file mode 100644 index 0000000..a9b48cd --- /dev/null +++ b/src/peripherals/tdm/TCM.bsv @@ -0,0 +1,151 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +package TCM; + /*====== Porject imports ====*/ + import defined_types::*; + `include "defined_parameters.bsv" + import Semi_FIFOF :: *; + import AXI4_Types :: *; + import AXI4_Fabric :: *; + import axi_addr_generator::*; + /*==== Package imports ======*/ + import BRAMCore :: *; + import DReg::*; + import BUtils::*; + /*============================*/ + + typedef TSub#(TLog#(TSub#(`TCMEnd,`TCMBase)),3) Index_bits; + + interface Ifc_TCM; + interface AXI4_Slave_IFC#(`PADDR,`Reg_width,`USERSPACE) axi_slave; + endinterface + typedef enum{Idle,HandleBurst} Mem_state deriving(Bits,Eq, FShow); + (*synthesize*) + module mkTCM(Ifc_TCM); + + + let index_bits=valueOf(Index_bits); + BRAM_DUAL_PORT_BE#(Bit#(TSub#(TLog#(TSub#(`TCMEnd,`TCMBase)),3)), Bit#(32),4) dmemMSB <-mkBRAMCore2BE(valueOf(TExp#(Index_bits)),False); + BRAM_DUAL_PORT_BE#(Bit#(TSub#(TLog#(TSub#(`TCMEnd,`TCMBase)),3)), Bit#(32),4) dmemLSB <-mkBRAMCore2BE(valueOf(TExp#(Index_bits)),False); + + AXI4_Slave_Xactor_IFC #(`PADDR, `Reg_width, `USERSPACE) s_xactor <- mkAXI4_Slave_Xactor; + + Reg#(Mem_state) rd_state <-mkReg(Idle); + Reg#(Mem_state) wr_state <-mkReg(Idle); + Reg#(Bit#(8)) rg_readburst_counter<-mkReg(0); + Reg#(AXI4_Rd_Addr #(`PADDR,`USERSPACE)) rg_read_packet <-mkReg(?); // hold the read packet during bursts + Reg#(AXI4_Wr_Addr #(`PADDR,`USERSPACE)) rg_write_packet<-mkReg(?); // hold the write packer during bursts + + rule rl_wr_respond(wr_state==Idle); + let aw <- pop_o (s_xactor.o_wr_addr); + let w <- pop_o (s_xactor.o_wr_data); + Bit#(Index_bits) index_address=(aw.awaddr-`TCMBase)[index_bits+2:3]; + dmemLSB.b.put(w.wstrb[3:0],index_address,truncate(w.wdata)); + dmemMSB.b.put(w.wstrb[7:4],index_address,truncateLSB(w.wdata)); + let b = AXI4_Wr_Resp {bresp: AXI4_OKAY, buser: aw.awuser, bid:aw.awid}; + if(aw.awburst!=0) begin + wr_state<=HandleBurst; + let new_address=burst_address_generator(aw.awlen,aw.awsize,aw.awburst,aw.awaddr); + aw.awaddr=new_address; + rg_write_packet<=aw; + end + else + s_xactor.i_wr_resp.enq (b); + `ifdef verbose $display($time,"\t",module_name,":\t Recieved Write Request for Address: %h data: %h strb: %b awlen: %d",aw.awaddr,w.wdata,w.wstrb,aw.awlen); `endif + endrule + + rule rl_wr_burst_response(wr_state==HandleBurst); + let w <- pop_o (s_xactor.o_wr_data); + let b = AXI4_Wr_Resp {bresp: AXI4_OKAY, buser: rg_write_packet.awuser, bid:rg_write_packet.awid}; + if(w.wlast)begin + wr_state<=Idle; + s_xactor.i_wr_resp.enq (b); + end + Bit#(Index_bits) index_address=(rg_write_packet.awaddr-`TCMBase)[index_bits+2:3]; + dmemLSB.b.put(w.wstrb[3:0],index_address,truncate(w.wdata)); + dmemMSB.b.put(w.wstrb[7:4],index_address,truncateLSB(w.wdata)); + let new_address=burst_address_generator(rg_write_packet.awlen,rg_write_packet.awsize,rg_write_packet.awburst,rg_write_packet.awaddr); + rg_write_packet.awaddr<=new_address; + `ifdef verbose $display($time,"\t",module_name,":\t BURST Write Request for Address: %h data: %h strb: %b awlen: %d",rg_write_packet.awaddr,w.wdata,w.wstrb,rg_write_packet.awlen); `endif + endrule + + rule rl_rd_request(rd_state==Idle); + let ar<- pop_o(s_xactor.o_rd_addr); + rg_read_packet<=ar; + Bit#(Index_bits) index_address=(ar.araddr-`TCMBase)[index_bits+2:3]; + dmemLSB.a.put(0,index_address,?); + dmemMSB.a.put(0,index_address,?); + rd_state<=HandleBurst; + `ifdef verbose $display($time,"\t",module_name,"\t Recieved Read Request for Address: %h Index Address: %h",ar.araddr,index_address); `endif + endrule + + rule rl_rd_response(rd_state==HandleBurst); + Bit#(`Reg_width) data0 = {dmemMSB.a.read(),dmemLSB.a.read()}; + AXI4_Rd_Data#(`Reg_width,`USERSPACE) r = AXI4_Rd_Data {rresp: AXI4_OKAY, rdata: data0 ,rlast:rg_readburst_counter==rg_read_packet.arlen, ruser: 0, rid:rg_read_packet.arid}; + let transfer_size=rg_read_packet.arsize; + let address=rg_read_packet.araddr; + if(transfer_size==2)begin // 32 bit + if(address[2:0]==0) + r.rdata=duplicate(data0[31:0]); + else + r.rdata=duplicate(data0[63:32]); + end + else if (transfer_size=='d1)begin // half_word + if(address[2:0] ==0) + r.rdata = duplicate(data0[15:0]); + else if(address[2:0] ==2) + r.rdata = duplicate(data0[31:16]); + else if(address[2:0] ==4) + r.rdata = duplicate(data0[47:32]); + else if(address[2:0] ==6) + r.rdata = duplicate(data0[63:48]); + end + else if (transfer_size=='d0) begin// one byte + if(address[2:0] ==0) + r.rdata = duplicate(data0[7:0]); + else if(address[2:0] ==1) + r.rdata = duplicate(data0[15:8]); + else if(address[2:0] ==2) + r.rdata = duplicate(data0[23:16]); + else if(address[2:0] ==3) + r.rdata = duplicate(data0[31:24]); + else if(address[2:0] ==4) + r.rdata = duplicate(data0[39:32]); + else if(address[2:0] ==5) + r.rdata = duplicate(data0[47:40]); + else if(address[2:0] ==6) + r.rdata = duplicate(data0[55:48]); + else if(address[2:0] ==7) + r.rdata = duplicate(data0[63:56]); + end + s_xactor.i_rd_data.enq(r); + address=burst_address_generator(rg_read_packet.arlen, rg_read_packet.arsize, rg_read_packet.arburst,rg_read_packet.araddr); + Bit#(Index_bits) index_address=(address-`TCMBase)[index_bits+2:3]; + if(rg_readburst_counter==rg_read_packet.arlen)begin + rg_readburst_counter<=0; + rd_state<=Idle; + end + else begin + dmemLSB.a.put(0,index_address,?); + dmemMSB.a.put(0,index_address,?); + rg_readburst_counter<=rg_readburst_counter+1; + end + rg_read_packet.araddr<=address; + Bit#(64) new_data=r.rdata; + `ifdef verbose $display($time,"\t",module_name,"\t Responding Read Request with CurrAddr: %h Data: %8h BurstCounter: %d BurstValue: %d NextAddress: %h",rg_read_packet.araddr,new_data,rg_readburst_counter,rg_read_packet.arlen,address); `endif + endrule + + interface axi_slave= s_xactor.axi_side; + endmodule +endpackage diff --git a/src/peripherals/vme/Memory_vme_16.bsv b/src/peripherals/vme/Memory_vme_16.bsv new file mode 100644 index 0000000..234cc5e --- /dev/null +++ b/src/peripherals/vme/Memory_vme_16.bsv @@ -0,0 +1,363 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ + +package Memory_vme_16; + import defined_types::*; + `include "defined_parameters.bsv" + import BRAMCore :: *; + // import TriState ::*; +// import DReg::*; +// import Semi_FIFOF :: *; +// import AXI4_Types :: *; +// import AXI4_Fabric :: *; + + +typedef enum + +{RCV_REQ,DET_DS,END_REQ +}State_slave deriving (Bits,Eq); + +interface Memory_vme_16#(numeric type base_address,numeric type mem_size); +(*always_ready, always_enabled*) +method Action rd_as_l(Bit#(1) m_as_l); +(*always_ready, always_enabled*) +method Action rd_ds_l(Bit#(1)m_ds_l); +(*always_ready, always_enabled*) +method Action rd_siz0(Bit#(1)m_ds1_l); +(*always_ready, always_enabled*) +method Action rd_siz1(Bit#(1)m_siz1); +(*always_ready, always_enabled*) +method Action rd_addr(Bit#(32)m_addr); +(*always_ready, always_enabled*) +method Action rd_wr_l(Bit#(1)m_wr_l); +(*always_ready*) +method Bit#(1) wr_dsack_0_l(); +(*always_ready*) +method Bit#(1) wr_dsack_1_l(); +(*always_ready*) +method Bit#(1) wr_berr_l(); +(*always_ready*) +method Bit#(1) wr_halt_l(); + +//.........Methods to write and read data when tristate is not enabled.........// + + +method Bit#(8) wr_byte_31_24(); +method Bit#(8) wr_byte_23_16(); +//method Bit#(8) wr_byte_15_8(); +//method Bit#(8) wr_byte_7_0(); + +method Action rd_byte_31_24(Bit #(8) d3); +method Action rd_byte_23_16(Bit #(8) d2); +//method Action rd_byte_15_8 (Bit #(8) d1); +//method Action rd_byte_7_0 (Bit #(8) d0); + + + +endinterface:Memory_vme_16 + +module mkMemory_16 #(parameter String mem_init_file, parameter String module_name) (Memory_vme_16#(base_address,mem_size)); + +// `ifdef BRF +// BRAM_DUAL_PORT_BE#(Bit#(TSub#(mem_size,2)),Bit#(`Reg_width_vme_slave),TDiv#(`Reg_width_vme_slave,8)) dmemLSB <- mkBRAMCore2BE(valueOf(TExp#(TSub#(mem_size,2))),False); +// `else + BRAM_DUAL_PORT_BE#(Bit#(TSub#(mem_size,1)),Bit#(16),TDiv#(16,8)) dmemLSB <- mkBRAMCore2BELoad(valueOf(TExp#(TSub#(mem_size,1))),False,mem_init_file,False); +// `endif + +//Defining the slave interface lines + +Reg #(Bit#(1)) s_dsack_0_l<-mkReg(1); +Reg #(Bit#(1)) s_dsack_1_l<-mkReg(1); +Reg #(Bit#(1)) s_berr_l<-mkReg(1); +Reg #(Bit#(1)) s_halt_l<-mkReg(1); +Wire #(Bit #(1)) s_as_l<-mkDWire(1); +Wire #(Bit #(1)) s_ds_l<-mkDWire(1); +Wire #(Bit #(1)) s_siz0<-mkDWire(0); +Wire #(Bit #(1)) s_siz1<-mkDWire(0); +Wire #(Bit #(32)) s_addr<-mkDWire(0); +Wire #(Bit #(1)) s_wr_l<-mkDWire(0); + + +Reg#(State_slave) slave_state <- mkReg (RCV_REQ); + + +//..........data_out registers of tristate buffers and their control...... +//....................................................................... + + +Wire#(Bit#(8)) data_in_4<-mkDWire(0); +Wire#(Bit#(8)) data_in_3<-mkDWire(0); +//Wire#(Bit#(8)) data_in_2<-mkDWire(0); +//Wire#(Bit#(8)) data_in_1<-mkDWire(0); + +Reg#(Bit#(8)) data_out_4<-mkReg(0); +Reg#(Bit#(8)) data_out_3<-mkReg(0); +//Reg#(Bit#(8)) data_out_2<-mkReg(0); +//Reg#(Bit#(8)) data_out_1<-mkReg(0); +Reg #(Bit#(2)) data_control <-mkReg(0); + + +/*In REQ_RCV State_slave +1.If read, sends acknowledge on detecting data strobe low + puts the data into the data bus +2.If write,sends acknowledge on address strobe low +*/ + +Bool start_rd = (s_wr_l==1'b1)&&(s_ds_l==1'b0)&&(s_as_l==1'b0); +Bool start_wr = (s_wr_l==1'b0)&&(s_as_l==1'b0); +Bool store_data=(s_wr_l==1'b0)&&(s_ds_l==1'b0); +rule rcv_req((slave_state==RCV_REQ)&&(start_rd||start_wr)); + + + $display("............SELECTING SLAVE WITH PORT WIDTH 32..............."); + if(start_wr) + + + begin + $display("Write_cycle"); + s_dsack_0_l<=1'b1; + s_dsack_1_l<=1'b0; + slave_state<=DET_DS; + end + else + begin + $display("Starting read from address",$time); + slave_state<=DET_DS; + Bit#(TSub#(mem_size,1)) index_address=(s_addr-fromInteger(valueOf(base_address)))[valueOf(mem_size)-1:1]; + dmemLSB.b.put(0,index_address,?); + $display("Index Address : %h",index_address); + end + +endrule + +/* +1. Checks for data_strobe +2. Reads data if data_strobe is asserted +*/ + + +rule send_ack(slave_state==DET_DS ); + if(s_wr_l==1'b1) + begin + s_dsack_0_l<=1'b1; + s_dsack_1_l<=1'b0; + slave_state<=END_REQ; + Bit#(16) data0 = dmemLSB.b.read(); + $display("32 bit data_read : %h",data0,$time); + case({s_siz1,s_siz0}) + + 2'b00: + begin + + data_out_4 <=data0[7:0]; + data_out_3 <=data0[15:8]; + // data_out_2 <=data0[15:8]; + // data_out_1 <=data0[7:0]; + data_control<=2'b11; + end + 2'b01 : + case({s_addr[1],s_addr[0]}) + 2'b00:begin + data_out_4<=data0[7:0]; + data_control<=2'b11; + $display("Reading data %h from %h addr",data0[7:0],s_addr); + end + 2'b01:begin + data_out_3<=data0[15:8]; + data_control<=2'b11; + $display("Reading data %h from %h addr",data0[15:8],s_addr); + end + 2'b10:begin + data_out_4<=data0[7:0]; + data_control<=2'b11; + $display("Reading data %h from %h addr",data0[7:0],s_addr); + end + 2'b11:begin + data_out_3<=data0[15:8]; + data_control<=2'b11; + $display("Reading data %h from %h addr",data0[15:8],s_addr); + end + + endcase + 2'b10 : + if({s_addr[1],s_addr[0]}==2'b00) + begin + data_out_4<=data0[7:0]; + data_out_3<=data0[15:8]; + data_control<=2'b11; + end + else + begin + data_out_4<=data0[7:0]; + data_out_3<=data0[15:8]; + data_control<=2'b11; + end + endcase + + end + else if(store_data) + + begin + $display("Writing to addr %0d ",s_addr,$time); + slave_state<=END_REQ; + Bit#(TSub#(mem_size,1)) index_address=(s_addr-fromInteger(valueOf(base_address)))[valueOf(mem_size)-1:1]; + $display("Index_address : %h",index_address); + case({s_siz1,s_siz0}) + 2'b00 :begin + dmemLSB.b.put(2'b11,index_address,{data_in_3,data_in_4}); + $display ("Data :%0h mode: quad_word",{data_in_3,data_in_4}); + end + 2'b01 :begin + case({s_addr[1],s_addr[0]}) + 2'b00: + begin + dmemLSB.b.put(2'b01,index_address,{8'b0,data_in_4}); + $display("Writing data %h",data_in_4); + end + 2'b01:dmemLSB.b.put(2'b10,index_address,{data_in_3,8'b0}); + 2'b10:dmemLSB.b.put(2'b01,index_address,{8'b0,data_in_4}); + 2'b11:dmemLSB.b.put(2'b10,index_address,{data_in_3,8'b0}); + endcase + end + 2'b10 : + if({s_addr[1],s_addr[0]}==2'b00) + begin + dmemLSB.b.put(2'b11,index_address,{data_in_3,data_in_4}); + $display ("Data :%0h mode: double_word",{data_in_3,data_in_4}); + end + else + begin + dmemLSB.b.put(2'b11,index_address,{data_in_3,data_in_4}); + $display ("Data :%0h mode: double_word",{data_in_3,data_in_4}); + + end + endcase + end + /* if(s_berr_l==1) + begin + s_dsack_1_l<=s_siz1; + s_dsack_0_l<=s_siz0; + end +// $display("sending ack",$time); + +*/ + +endrule + +//Releases bus if data strobe is released// +rule end_req(slave_state==END_REQ); + +if((s_ds_l==1) &&(s_as_l==1)) +begin +s_dsack_0_l<=1; +s_dsack_1_l<=1; +s_berr_l<=1; +s_halt_l<=1; +data_control<=2'b00; +$display("SLAVE_STATE:3 Releasing bus ",$time); +slave_state<=RCV_REQ; +end + +endrule + + +/*interface s_io_31_24 = d31_24.io; +interface s_io_23_16 = d23_16.io; +interface s_io_15_8 = d15_8.io; +interface s_io_7_0 = d7_0.io; +*/ + +method Action rd_as_l(Bit#(1) m_as_l); +s_as_l<=m_as_l; +endmethod + +method Action rd_ds_l(Bit#(1)m_ds_l); +s_ds_l<=m_ds_l; +endmethod + +method Action rd_siz0(Bit#(1)m_ds1_l); +s_siz0<=m_ds1_l; +endmethod + +method Action rd_siz1(Bit#(1)m_siz1); +s_siz1<=m_siz1; +endmethod + +method Action rd_addr(Bit #(32)m_addr); +s_addr<=m_addr; + +endmethod + +method Bit#(1) wr_dsack_0_l(); +return s_dsack_0_l; +endmethod + +method Bit#(1) wr_dsack_1_l(); +return s_dsack_1_l; +endmethod + +method Bit#(1)wr_berr_l(); +return s_berr_l; +endmethod + +method Bit#(1)wr_halt_l(); +return s_halt_l; +endmethod + + +method Action rd_wr_l(m_wr_l); +s_wr_l<=m_wr_l; +endmethod + +/*Methods to emulate tristate functionality*/ + + +method Bit#(8) wr_byte_31_24()if(data_control[1]==1); +return data_out_4; +endmethod + +method Bit#(8) wr_byte_23_16()if(data_control[0]==1); +return data_out_3; +endmethod + +/*method Bit#(8) wr_byte_15_8()if(data_control[1]==1); +return data_out_2; +endmethod + + +method Bit#(8) wr_byte_7_0()if (data_control[0]==1); +return data_out_1; +endmethod +*/ + +method Action rd_byte_31_24(Bit #(8) d4)if(data_control[1]==0); +data_in_4<=d4; +endmethod + +method Action rd_byte_23_16(Bit #(8) d3)if(data_control[0]==0); +data_in_3<=d3; +endmethod + + +/*method Action rd_byte_15_8 (Bit #(8) d2)if(data_control[1]==0); +data_in_2<=d2; +endmethod + +method Action rd_byte_7_0 (Bit #(8) d1)if(data_control[0]==0); +data_in_1<=d1; +endmethod +*/ + +endmodule +endpackage diff --git a/src/peripherals/vme/Memory_vme_32.bsv b/src/peripherals/vme/Memory_vme_32.bsv new file mode 100644 index 0000000..d5ee3b1 --- /dev/null +++ b/src/peripherals/vme/Memory_vme_32.bsv @@ -0,0 +1,338 @@ + +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ + +package Memory_vme_32; + + import defined_types::*; + `include "defined_parameters.bsv" + import BRAMCore :: *; + `include "vme_parameters.bsv" + +//typedef enum{Send_req,Get_resp} Mem_state deriving(Bits,Eq); + +typedef enum + +{RCV_REQ,DET_DS,END_REQ +}State_slave deriving (Bits,Eq); + +interface Vme_slave #(numeric type base_address,numeric type mem_size); +(*always_ready, always_enabled*) +method Action rd_as_l(Bit#(1) m_as_l); +(*always_ready, always_enabled*) +method Action rd_ds_l(Bit#(1)m_ds_l); +(*always_ready, always_enabled*) +method Action rd_siz0(Bit#(1)m_ds1_l); +(*always_ready, always_enabled*) +method Action rd_siz1(Bit#(1)m_siz1); +(*always_ready, always_enabled*) +method Action rd_addr(Bit#(32)m_addr); +(*always_ready, always_enabled*) +method Action rd_wr_l(Bit#(1)m_wr_l); +(*always_ready*) +method Bit#(1) wr_dsack_0_l(); +(*always_ready*) +method Bit#(1) wr_dsack_1_l(); +(*always_ready*) +method Bit#(1) wr_berr_l(); +(*always_ready*) +method Bit#(1) wr_halt_l(); + +//.........Methods to write and read data when tristate is not enabled.........// + + +method Bit#(8) wr_byte_31_24(); +method Bit#(8) wr_byte_23_16(); +method Bit#(8) wr_byte_15_8(); +method Bit#(8) wr_byte_7_0(); + +method Action rd_byte_31_24(Bit #(8) d3); +method Action rd_byte_23_16(Bit #(8) d2); +method Action rd_byte_15_8 (Bit #(8) d1); +method Action rd_byte_7_0 (Bit #(8) d0); + +endinterface:Vme_slave + +module mkMemory #(parameter String mem_init_file, parameter String module_name) (Vme_slave#(base_address,mem_size)); + + BRAM_DUAL_PORT_BE#(Bit#(TSub#(mem_size,2)),Bit#(`Reg_width_vme_slave),TDiv#(`Reg_width_vme_slave,8)) dmemLSB <- mkBRAMCore2BELoad(valueOf(TExp#(TSub#(mem_size,2))),False,mem_init_file,False); + +//Defining the slave interface lines + +Reg #(Bit#(1)) s_dsack_0_l<-mkReg(1); +Reg #(Bit#(1)) s_dsack_1_l<-mkReg(1); +Reg #(Bit#(1)) s_berr_l<-mkReg(1); +Reg #(Bit#(1)) s_halt_l<-mkReg(1); +Wire #(Bit #(1)) s_as_l<-mkDWire(1); +Wire #(Bit #(1)) s_ds_l<-mkDWire(1); +Wire #(Bit #(1)) s_siz0<-mkDWire(0); +Wire #(Bit #(1)) s_siz1<-mkDWire(0); +Wire #(Bit #(32)) s_addr<-mkDWire(0); +Wire #(Bit #(1)) s_wr_l<-mkDWire(0); + +Reg#(State_slave) slave_state <- mkReg (RCV_REQ); + + +//..........data_out registers of tristate buffers and their control...... +//....................................................................... + + +Wire#(Bit#(8)) data_in_4<-mkDWire(0); +Wire#(Bit#(8)) data_in_3<-mkDWire(0); +Wire#(Bit#(8)) data_in_2<-mkDWire(0); +Wire#(Bit#(8)) data_in_1<-mkDWire(0); +Reg#(Bit#(8)) data_out_4<-mkReg(0); +Reg#(Bit#(8)) data_out_3<-mkReg(0); +Reg#(Bit#(8)) data_out_2<-mkReg(0); +Reg#(Bit#(8)) data_out_1<-mkReg(0); +Reg #(Bit#(4)) data_control <-mkReg(0); + + +/*In REQ_RCV State_slave +1.If read, sends acknowledge on detecting data strobe low + puts the data into the data bus +2.If write,sends acknowledge on address strobe low +*/ + +Bool start_rd = (s_wr_l==1'b1)&&(s_ds_l==1'b0)&&(s_as_l==1'b0)&&(s_addr>=32'h40000000 && s_addr<=32'h4FFFFFFF); +Bool start_wr = (s_wr_l==1'b0)&&(s_as_l==1'b0)&&(s_addr>=32'h40000000 && s_addr <=32'h4FFFFFFF); +Bool store_data=(s_wr_l==1'b0)&&(s_ds_l==1'b0); + +rule rcv_req((slave_state==RCV_REQ)&&(start_rd||start_wr)); + + + $display("............SELECTING SLAVE WITH PORT WIDTH 32..............."); + if(start_wr) + + + begin + $display("Write_cycle"); + s_dsack_0_l<=1'b0; + s_dsack_1_l<=1'b0; + slave_state<=DET_DS; + end + else + begin + $display("Starting read from address",$time); + slave_state<=DET_DS; + Bit#(TSub#(mem_size,2)) index_address=(s_addr-fromInteger(valueOf(base_address)))[valueOf(mem_size)-1:2]; + dmemLSB.b.put(0,index_address,?); + $display("Index Address : %h",index_address); + end + +endrule + +/* +1. Checks for data_strobe +2. Reads data if data_strobe is asserted +*/ + + +rule send_ack(slave_state==DET_DS ); + if(s_wr_l==1'b1) + begin + s_dsack_0_l<=1'b0; + s_dsack_1_l<=1'b0; + slave_state<=END_REQ; + Bit#(`Reg_width_vme_slave) data0 = dmemLSB.b.read(); + $display("32 bit data_read : %h",data0,$time); + case({s_siz1,s_siz0}) + + 2'b00: + begin + + data_out_1 <=data0[31:24]; + data_out_2 <=data0[23:16]; + data_out_3 <=data0[15:8]; + data_out_4 <=data0[7:0]; + data_control<=4'b1111; + end + 2'b01 : + case({s_addr[1],s_addr[0]}) + 2'b00:begin + data_out_4<=data0[7:0]; + data_control<=4'b1111; + $display("Reading data %h from %h addr",data0[7:0],s_addr); + end + 2'b01:begin + data_out_3<=data0[15:8]; + data_control<=4'b1111; + $display("Reading data %h from %h addr",data0[15:8],s_addr); + end + 2'b10:begin + data_out_2<=data0[23:16]; + data_control<=4'b1111; + $display("Reading data %h from %h addr",data0[23:16],s_addr); + end + 2'b11:begin + data_out_1<=data0[31:24]; + data_control<=4'b1111; + $display("Reading data %h from %h addr",data0[31:24],s_addr); + end + + endcase + 2'b10 : + if({s_addr[1],s_addr[0]}==2'b00) + begin + data_out_3<=data0[15:8]; + data_out_4<=data0[7:0]; + data_control<=4'b1111; + end + else + begin + data_out_1<=data0[31:24]; + data_out_2<=data0[23:16]; + data_control<=4'b1111; + end + endcase + + end + else if(store_data) + + begin + $display("Writing to addr %0d ",s_addr,$time); + slave_state<=END_REQ; + Bit#(TSub#(mem_size,2)) index_address=(s_addr-fromInteger(valueOf(base_address)))[valueOf(mem_size)-1:2]; + $display("Index_address : %h",index_address); + case({s_siz1,s_siz0}) + 2'b00 :begin + dmemLSB.b.put(4'b1111,index_address,{data_in_1,data_in_2,data_in_3,data_in_4}); + $display ("Data :%0h mode: quad_word",{data_in_1,data_in_2,data_in_3,data_in_4}); + end + 2'b01 :begin + case({s_addr[1],s_addr[0]}) + 2'b00:begin + + + dmemLSB.b.put(4'b0001,index_address,{24'b0,data_in_4}); + $display("Writing data %h",data_in_4); + end + 2'b01:dmemLSB.b.put(4'b0010,index_address,{16'b0,data_in_3,8'b0}); + 2'b10:dmemLSB.b.put(4'b0100,index_address,{8'b0,data_in_2,16'b0}); + 2'b11:dmemLSB.b.put(4'b1000,index_address,{data_in_1,24'b0}); + endcase + end + 2'b10 : + if({s_addr[1],s_addr[0]}==2'b00) + begin + dmemLSB.b.put(4'b0011,index_address,{16'b0,data_in_3,data_in_4}); + end + else + begin + dmemLSB.b.put(4'b1100,index_address,{data_in_1,data_in_2,16'b0}); + end + endcase + end + +endrule + +//Releases bus if data strobe is released// +rule end_req(slave_state==END_REQ); + +if((s_ds_l==1) &&(s_as_l==1)) +begin +s_dsack_0_l<=1; +s_dsack_1_l<=1; +s_berr_l<=1; +s_halt_l<=1; +data_control<=4'b0000; +$display("SLAVE_STATE:3 Releasing bus ",$time); +slave_state<=RCV_REQ; +end + +endrule + + + +method Action rd_as_l(Bit#(1) m_as_l); +s_as_l<=m_as_l; +endmethod + +method Action rd_ds_l(Bit#(1)m_ds_l); +s_ds_l<=m_ds_l; +endmethod + +method Action rd_siz0(Bit#(1)m_ds1_l); +s_siz0<=m_ds1_l; +endmethod + +method Action rd_siz1(Bit#(1)m_siz1); +s_siz1<=m_siz1; +endmethod + +method Action rd_addr(Bit #(32)m_addr); +s_addr<=m_addr; + +endmethod + +method Bit#(1) wr_dsack_0_l(); +return s_dsack_0_l; +endmethod + +method Bit#(1) wr_dsack_1_l(); +return s_dsack_1_l; +endmethod + +method Bit#(1)wr_berr_l(); +return s_berr_l; +endmethod + +method Bit#(1)wr_halt_l(); +return s_halt_l; +endmethod + + +method Action rd_wr_l(m_wr_l); +s_wr_l<=m_wr_l; +endmethod + +/*Methods to emulate tristate functionality*/ + + +method Bit#(8) wr_byte_31_24()if(data_control[3]==1); +return data_out_4; +endmethod + +method Bit#(8) wr_byte_23_16()if(data_control[2]==1); +return data_out_3; +endmethod + +method Bit#(8) wr_byte_15_8()if(data_control[1]==1); +return data_out_2; +endmethod + + +method Bit#(8) wr_byte_7_0()if (data_control[0]==1); +return data_out_1; +endmethod + +method Action rd_byte_31_24(Bit #(8) d4)if(data_control[3]==0); +data_in_4<=d4; +endmethod + +method Action rd_byte_23_16(Bit #(8) d3)if(data_control[2]==0); +data_in_3<=d3; +endmethod + +method Action rd_byte_15_8 (Bit #(8) d2)if(data_control[1]==0); +data_in_2<=d2; +endmethod + +method Action rd_byte_7_0 (Bit #(8) d1)if(data_control[0]==0); +data_in_1<=d1; +endmethod + + +endmodule +endpackage diff --git a/src/peripherals/vme/Memory_vme_8.bsv b/src/peripherals/vme/Memory_vme_8.bsv new file mode 100644 index 0000000..e8bb898 --- /dev/null +++ b/src/peripherals/vme/Memory_vme_8.bsv @@ -0,0 +1,297 @@ + +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ + +package Memory_vme_8; + import defined_types::*; + `include "defined_parameters.bsv" + import BRAMCore :: *; + + +//typedef enum{Send_req,Get_resp} Mem_state deriving(Bits,Eq); + +typedef enum + +{RCV_REQ,DET_DS,END_REQ +}State_slave deriving (Bits,Eq); + +interface Vme_slave_8 #(numeric type base_address,numeric type mem_size); +(*always_ready, always_enabled*) +method Action rd_as_l(Bit#(1) m_as_l); +(*always_ready, always_enabled*) +method Action rd_ds_l(Bit#(1)m_ds_l); +(*always_ready, always_enabled*) +method Action rd_siz0(Bit#(1)m_ds1_l); +(*always_ready, always_enabled*) +method Action rd_siz1(Bit#(1)m_siz1); +(*always_ready, always_enabled*) +method Action rd_addr(Bit#(32)m_addr); +(*always_ready, always_enabled*) +method Action rd_wr_l(Bit#(1)m_wr_l); +(*always_ready*) +method Bit#(1) wr_dsack_0_l(); +(*always_ready*) +method Bit#(1) wr_dsack_1_l(); +(*always_ready*) +method Bit#(1) wr_berr_l(); +(*always_ready*) +method Bit#(1) wr_halt_l(); + +//.........Methods to write and read data when tristate is not enabled.........// + + +method Bit#(8) wr_byte_31_24(); +//method Bit#(8) wr_byte_23_16(); +//method Bit#(8) wr_byte_15_8(); +//method Bit#(8) wr_byte_7_0(); + +method Action rd_byte_31_24(Bit #(8) d3); +//method Action rd_byte_23_16(Bit #(8) d2); +//method Action rd_byte_15_8 (Bit #(8) d1); +//method Action rd_byte_7_0 (Bit #(8) d0); + + + +endinterface:Vme_slave_8 + +module mkMemory_8 #(parameter String mem_init_file, parameter String module_name) (Vme_slave_8#(base_address,mem_size)); + + BRAM_DUAL_PORT_BE#(Bit#(TSub#(mem_size,0)),Bit#(8),TDiv#(8,8)) dmemLSB <- mkBRAMCore2BELoad(valueOf(TExp#(TSub#(mem_size,0))),False,mem_init_file,False); + +//Defining the slave interface lines + +Reg #(Bit#(1)) s_dsack_0_l<-mkReg(1); +Reg #(Bit#(1)) s_dsack_1_l<-mkReg(1); +Reg #(Bit#(1)) s_berr_l<-mkReg(1); +Reg #(Bit#(1)) s_halt_l<-mkReg(1); +Wire #(Bit #(1)) s_as_l<-mkDWire(1); +Wire #(Bit #(1)) s_ds_l<-mkDWire(1); +Wire #(Bit #(1)) s_siz0<-mkDWire(0); +Wire #(Bit #(1)) s_siz1<-mkDWire(0); +Wire #(Bit #(32)) s_addr<-mkDWire(0); +Wire #(Bit #(1)) s_wr_l<-mkDWire(0); + + +Reg#(State_slave) slave_state <- mkReg (RCV_REQ); + + +//..........data_out registers of tristate buffers and their control...... +//....................................................................... + + +Wire#(Bit#(8)) data_in_4<-mkDWire(0); +Wire#(Bit#(8)) data_in_3<-mkDWire(0); +Wire#(Bit#(8)) data_in_2<-mkDWire(0); +Wire#(Bit#(8)) data_in_1<-mkDWire(0); + +Reg#(Bit#(8)) data_out_4<-mkReg(0); +Reg#(Bit#(8)) data_out_3<-mkReg(0); +Reg#(Bit#(8)) data_out_2<-mkReg(0); +Reg#(Bit#(8)) data_out_1<-mkReg(0); +Reg #(Bit#(4)) data_control <-mkReg(0); + + + + + + + +/*In REQ_RCV State_slave +1.If read, sends acknowledge on detecting data strobe low + puts the data into the data bus +2.If write,sends acknowledge on address strobe low +*/ + +Bool start_rd = (s_wr_l==1'b1)&&(s_ds_l==1'b0)&&(s_as_l==1'b0); +Bool start_wr = (s_wr_l==1'b0)&&(s_as_l==1'b0); +Bool store_data=(s_wr_l==1'b0)&&(s_ds_l==1'b0); + +rule rcv_req((slave_state==RCV_REQ)&&(start_rd||start_wr)); + + + $display("............SELECTING SLAVE WITH PORT WIDTH 32..............."); + if(start_wr) + + + begin + $display("Write_cycle"); + s_dsack_0_l<=1'b0; + s_dsack_1_l<=1'b1; + slave_state<=DET_DS; + end + else + begin + $display("Starting read from address",$time); + + slave_state<=DET_DS; + Bit#(TSub#(mem_size,0)) index_address=(s_addr-fromInteger(valueOf(base_address)))[valueOf(mem_size)-1:0]; + dmemLSB.b.put(0,index_address,?); + $display("Index Address : %h",index_address); + end + +endrule + +/* +1. Checks for data_strobe +2. Reads data if data_strobe is asserted +*/ + + +rule send_ack(slave_state==DET_DS ); + if(s_wr_l==1'b1) + begin + s_dsack_0_l<=1'b0; + s_dsack_1_l<=1'b1; + slave_state<=END_REQ; + Bit#(8) data0 = dmemLSB.b.read(); + $display("8 bit data_read : %h",data0,$time); + case({s_siz1,s_siz0}) + + 2'b00: + begin + + data_out_4 <=data0; + // data_out_3 <=data0[23:16]; + // data_out_2 <=data0[15:8]; + // data_out_1 <=data0[7:0]; + data_control<=4'b1111; + end + 2'b01 : + case({s_addr[1],s_addr[0]}) + 2'b00:begin + data_out_4<=data0; + data_control<=4'b1111; + //$display("Reading data %h from %h addr",data0[7:0],s_addr); + end + 2'b01:begin + data_out_4<=data0; + data_control<=4'b1111; + //$display("Reading data %h from %h addr",data0[15:8],s_addr); + end + 2'b10:begin + data_out_4<=data0; + data_control<=4'b1111; + // $display("Reading data %h from %h addr",data0[23:16],s_addr); + end + 2'b11:begin + data_out_4<=data0; + data_control<=4'b1111; + // $display("Reading data %h from %h addr",data0[31:24],s_addr); + end + + endcase + 2'b10 : + begin + data_out_4<=data0; + // data_out_3<=data0[7:0]; + data_control<=4'b1111; + end + /*else + begin + data_out_2<=data0[31:24]; + data_out_1<=data0[23:16]; + data_control<=4'b1111; + end + */ + endcase + + end + else if(store_data) + + begin + $display("Writing to addr %0d ",s_addr,$time); + slave_state<=END_REQ; + Bit#(TSub#(mem_size,0)) index_address=(s_addr-fromInteger(valueOf(base_address)))[valueOf(mem_size)-1:0]; + $display("Index_address : %h",index_address); + dmemLSB.b.put(1,index_address,data_in_4); + + end + +endrule + +//Releases bus if data strobe is released// +rule end_req(slave_state==END_REQ); + +if((s_ds_l==1) &&(s_as_l==1)) +begin +s_dsack_0_l<=1; +s_dsack_1_l<=1; +s_berr_l<=1; +s_halt_l<=1; +data_control<=4'b0000; +$display("SLAVE_STATE:3 Releasing bus ",$time); +slave_state<=RCV_REQ; +end + +endrule + + + +method Action rd_as_l(Bit#(1) m_as_l); +s_as_l<=m_as_l; +endmethod + +method Action rd_ds_l(Bit#(1)m_ds_l); +s_ds_l<=m_ds_l; +endmethod + +method Action rd_siz0(Bit#(1)m_ds1_l); +s_siz0<=m_ds1_l; +endmethod + +method Action rd_siz1(Bit#(1)m_siz1); +s_siz1<=m_siz1; +endmethod + +method Action rd_addr(Bit #(32)m_addr); +s_addr<=m_addr; + +endmethod + +method Bit#(1) wr_dsack_0_l(); +return s_dsack_0_l; +endmethod + +method Bit#(1) wr_dsack_1_l(); +return s_dsack_1_l; +endmethod + +method Bit#(1)wr_berr_l(); +return s_berr_l; +endmethod + +method Bit#(1)wr_halt_l(); +return s_halt_l; +endmethod + + +method Action rd_wr_l(m_wr_l); +s_wr_l<=m_wr_l; +endmethod + +/*Methods to emulate tristate functionality*/ + + +method Bit#(8) wr_byte_31_24()if(data_control[3]==1); +return data_out_4; +endmethod + + +method Action rd_byte_31_24(Bit #(8) d4)if(data_control[3]==0); +data_in_4<=d4; +endmethod + + +endmodule +endpackage diff --git a/src/peripherals/vme/vme_defines.bsv b/src/peripherals/vme/vme_defines.bsv new file mode 100644 index 0000000..09e32ab --- /dev/null +++ b/src/peripherals/vme/vme_defines.bsv @@ -0,0 +1,29 @@ + + +package vme_defines; + + +typedef struct +{ +Bit #(32) addr; +Bit #(32) wr_data; +Bit #(2) mode; +Bit #(3) fun_code; +Bit #(1) rd_req;//HIGH FOR READ,LOW FOR WRITE +}Req_vme deriving (Bits,Eq);//Request from cpu + +typedef struct + +{ + +Bit#(2) port_type; +Bit#(32) data; +Bit#(1)berr ; //r0 for bus_error 1 for no error +}Resp_vme deriving (Bits,Eq);//Response to cpu + + + + + + +endpackage diff --git a/src/peripherals/vme/vme_master.bsv b/src/peripherals/vme/vme_master.bsv new file mode 100644 index 0000000..9c29912 --- /dev/null +++ b/src/peripherals/vme/vme_master.bsv @@ -0,0 +1,750 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +/* +Generating VME master requests + +*/ + +package vme_master; +//import TriState ::*; +import FIFOF ::*; +import vme_defines ::*; +//import Clocks ::*; + + + +/* + READ CYCLE + + +1.STATE 0 : receives req (function codes,r/w,siz1,siz0,addrbus) latched + +2.STATE 1 : assert address strobe and data strobe + +3. STATE 2 : Wait + +4. STATE 3 : Check for acknowledgement + +5. STATE 4 : latch data + +6. STATE 5: Release address strobe and data strobe(acknowledge lines will be released one cycle later) + + WRITE CYCLE + + +1.STATE 0: receives req (function codes,r/w,siz1,siz0,addrbus) latched + +2.STATE 1 : assert address strobe + +3. STATE 2 : place data on the bus and wait for acknowledgement + +4. STATE 3 : assert data and strobe and enable required data lines + +5. STATE 4 : No operation + +6. STATE 5:Release address strobe and data strobe(acknowledge lines will be released one cycle later)READ CYCLE + +Data_mode :01 byte + 10 Word + 00 Long word +*/ + +typedef enum + + +{RCV_REQ,PRC_REQ_1,PRC_REQ_2,PRC_REQ_3,LATCH_DATA,END_REQ,ADDR_INVALID,HALT +}State_master deriving (Bits,Eq); + +typedef enum +{LW,BYTE,WORD,TRI_BYTE}Data_mode deriving (Bits,Eq); + +interface Vme_out; + (*always_enabled,always_ready*) + method Bit#(1) wr_as_l(); + (*always_enabled,always_ready*) + method Bit#(1) wr_ds_l(); + (*always_enabled,always_ready*) + method Bit#(1) wr_wr_l(); + (*always_ready*) + method Action rd_dsack_0_l(Bit#(1) x); + (*always_ready*) + method Action rd_dsack_1_l(Bit#(1) y); + (*always_ready*) + method Action rd_berr_l(Bit#(1) z); + (*always_ready*) + method Action rd_halt_l(Bit#(1) u); +endinterface:Vme_out + +interface Data_bus_inf; + + method Bit#(8) wr_byte_31_24(); + (*always_enabled,always_ready*) + method Bit#(1) wr_siz1(); + (*always_enabled,always_ready*) + method Bit#(1) wr_siz0(); + method Bool wr_mode_en(); + (*always_enabled,always_ready*) + method Bit#(32) wr_addr(); + method Bool wr_addr_en(); + method Bit#(4) wr_en(); + + method Bit#(3) wr_fun_code(); + method Bool wr_fun_code_en(); + method Bit#(8) wr_byte_23_16(); + method Bit#(8) wr_byte_15_8(); + method Bit#(8) wr_byte_7_0(); + + method Action rd_byte_31_24(Bit #(8) d3); + method Action rd_byte_23_16(Bit #(8) d2); + method Action rd_byte_15_8 (Bit #(8) d1); + method Action rd_byte_7_0 (Bit #(8) d0); + +endinterface + +interface Vme_master ; + method Action get_req (Req_vme req); + interface Vme_out vme_interface; + interface Data_bus_inf data_bus; + method ActionValue #(Resp_vme) resp(); +endinterface:Vme_master + +(*synthesize*) + +module mkvmemaster(Vme_master); + + +//Fifos to get request and send response +FIFOF #(Req_vme) cpu_req <- mkFIFOF; +FIFOF #(Resp_vme) cpu_resp <- mkFIFOF; +//............................................................// + +Reg #(State_master) master_state <- mkReg (RCV_REQ); +Reg#(Bit#(2)) mode<-mkReg(0); +Reg#(Bool) mode_en<-mkReg(False);//Enable SIZ1,SIZ0 +Reg#(Bit#(3)) fun_code<-mkReg(0); +Reg#(Bool) fun_code_en<-mkReg(False); +Reg#(Bit#(1)) as_l<-mkReg(1);//address_stop +Reg#(Bit#(1)) ds_l<-mkReg(1);//data_strobe +Reg#(Bit#(1)) stop<-mkReg(0);//Indicates processor stopped +Reg#(Bit#(1)) retry<-mkReg(0);//Indicates retry mode +Wire#(Bit#(1)) dsack_0_l<-mkDWire(1);//ack from VIC controller,indicates port size 0-32 bit port,1-8 bit port,2-16 bit port +Wire#(Bit#(1)) dsack_1_l<-mkDWire(1); +Wire#(Bit#(1)) berr_l <-mkDWire(1);//Bus error from slave +Wire#(Bit#(1)) halt_l<-mkDWire(1);//halt signal from the slave +//Wire#(Bit#(3)) ipl_l<-mkDWire(1);//interrupt prioritylevel + +Reg #(Bit#(32)) addr<-mkReg(0);//addr_bus +Reg #(Bool) addr_en<-mkReg(False); +Reg #(Bit#(8)) data_out_4<-mkReg(0);//wr_data_4 +Reg #(Bit#(8)) data_out_3<-mkReg(0);//wr_data_3 +Reg #(Bit#(8)) data_out_2<-mkReg(0);//wr_data_2 +Reg #(Bit#(8)) data_out_1<-mkReg(0);//wr_data_1 + +Wire #(Bit#(8)) data_in_4<-mkDWire(0);//rd_data_4 +Wire #(Bit#(8)) data_in_3<-mkDWire(0);//rd_data_3 +Wire #(Bit#(8)) data_in_2<-mkDWire(0);//rd_data_2 +Wire #(Bit#(8)) data_in_1<-mkDWire(0);//rd_data_1 + + +Reg #(Bit#(1)) wr_l <-mkReg(1'd1);//read : 1,write:0 +Reg #(Bit#(4)) data_control <-mkReg(0);//Enable bits to data and control registers +Reg #(Bit#(2)) cntl_wd<-mkReg(0); //To synchronize if more than one cycle is required to r/w data +//.........Tristate signals...............// +/* + +/* +*/ +(* mutually_exclusive = "rcv_req_new,prc_req,prc_req_1,prc_req_2,req_wait,end_req" *) + +/* REQ_RCV master_state.... +1. Master receives request +2. address,FC2-FC0,Data,Write lines are driven +*/ +rule rcv_req_new(master_state==RCV_REQ && cntl_wd==2'b00 && (halt_l==1'b1) && (berr_l==1'b1)) ;//To recieve new request + + let req =cpu_req.first(); + $display("MASTER_STATE 1: receiving request to address %h req_type:%h",req.addr,req.rd_req,$time); + cpu_req.deq(); + addr<=req.addr; + addr_en<=True; + fun_code_en<=True; + mode_en<=True; + mode<=req.mode; + $display("mode of operation %b",req.mode); + fun_code<=req.fun_code; + wr_l<=req.rd_req; + master_state<=PRC_REQ_1; + +//............Multiplexing logic to route data to data bus...................................................................................................... + + if (req.mode==2'b01)//For 8 bit data operations + case({req.addr[1],req.addr[0]}) + + 2'b00:data_out_4<=req.wr_data[7:0]; + + 2'b01:begin + data_out_4<=req.wr_data[7:0]; + data_out_3<=req.wr_data[7:0]; + end + + 2'b10:begin + data_out_4<=req.wr_data[7:0]; + data_out_2<=req.wr_data[7:0]; + end + 2'b11:begin + data_out_4<=req.wr_data[7:0]; + data_out_3<=req.wr_data[7:0]; + data_out_1<=req.wr_data[7:0]; + end + endcase + + + else if (req.mode==2'b10)//For 16 data operations + case({req.addr[1],req.addr[0]}) + + 2'b00:begin + + data_out_4<=req.wr_data[7:0]; + data_out_3<=req.wr_data[15:8]; + + end + + 2'b10: begin + data_out_4<=req.wr_data[7:0]; + data_out_3<=req.wr_data[15:8]; + data_out_1<=req.wr_data[15:8]; + data_out_2<=req.wr_data[7:0]; + end + endcase + + else if (req.mode==2'b00)//for 32 bit operation + + case({req.addr[1],req.addr[0]}) + + 2'b00: + begin + data_out_1<=req.wr_data[31:24]; + data_out_2<=req.wr_data[23:16]; + data_out_3<=req.wr_data[15:8]; + data_out_4<=req.wr_data[7:0]; + $display("Data to be written = %h",req.wr_data); + end + endcase +//.............................................................................................................................................................. +endrule + +rule prc_req(master_state==RCV_REQ && cntl_wd!=2'b00);//If a request takes multiple cycles + + if(cntl_wd==2'b01)//32 bit operation from 8 bit or 16 bit slave + + + begin + + data_out_4<=data_out_3; + data_out_3<=data_out_2; + data_out_2<=data_out_1; + data_out_1<=8'b0; + addr <=addr+1; + mode <=mode-1; + end +else + begin//32 bit operation on a 16 bit slave + + data_out_4<=data_out_2; + data_out_3<=data_out_1; + data_out_2<=8'b0; + data_out_1<=8'b0; + addr <= addr+2; + mode <=2'b10; + end + master_state<=PRC_REQ_1; + +endrule +/* +InPRC_REQ_1.... + +1.Address strobe is asserted + +2.Data Strobe is asserted if it is a read cycle + +3. Data lines are enabled for write cycle + + +*/ + +rule prc_req_1(master_state==PRC_REQ_1); + + + + $display("MASTER_STATE 2: Activating address strobe",$time); + as_l<=0; + master_state<=PRC_REQ_2; + ds_l<=0; + if(wr_l==1'b0) + data_control<=4'b1111; + +endrule +/* +In PRC_REQ_2 +1. Data strobe is asserted in write cycle on receiving ack,halt or bus error cycle +*/ +rule prc_req_2(master_state==PRC_REQ_2); + + begin + $display("MASTER_STATE_3 ",$time); + if (({dsack_0_l,dsack_1_l}!=2'b11)||(berr_l==1'b0)||(halt_l==1'b0)) + begin + master_state<=PRC_REQ_3; + end + + + end +endrule +/*In WAIT_RESP +1. Master waits for response +2. On receiving response,goes to next state +*/ + +rule req_wait((master_state==PRC_REQ_3)&&(({dsack_0_l,dsack_1_l}!=2'b11)||(berr_l==1'b0)||(halt_l==1'b0))); + +// if (wr_l==1'b0) + +// ds_l<=0; + + master_state<=LATCH_DATA; + $display(" MASTER_STATE_4:",$time); + if({dsack_0_l,dsack_1_l}==mode) + begin +// $display("detected response %h",$time); +// master_state<=LATCH_DATA; + cntl_wd<=2'b00;//Done can take the next request + end +//if a 32 bit word r/w fro/to a 16 bit port + else if({dsack_0_l,dsack_1_l}==2'b10 && mode==2'b00) + + begin + cntl_wd<=2'b10; + // mode <=2'b10; + end + +// If a 32 bit word or 1 16 bit is r/w fro/to a 8 bit port + else if({dsack_0_l,dsack_1_l}==2'b01 && mode!=2'b01) + + begin + cntl_wd<=2'b01; + // mode<=mode-1; + end + + + +endrule +//.......................Latch_data when not using tristatebuffers............................................................................. +//In LATCH DATA state +//Latches on-to data and response +rule latch_data(master_state==LATCH_DATA); + +if(berr_l==1'b0 && halt_l==1'b0) +begin +retry<=1; +end + +else if(berr_l!=1'b0 && halt_l==1'b0) +begin +stop<=1; +end + +else if(berr_l==1'b0) +begin + + +let resp_data = Resp_vme{ data:{data_in_4, + data_in_3, + data_in_2,8'b0},berr:1}; + cpu_resp.enq(resp_data); +end + + +else +if (mode==2'b01 )//Receiving 8 bit data + case({dsack_0_l,dsack_1_l}) +//......................................SLAVE PORT..............................//:-32 byte +//....................................................................................... + 2'b00 : + + case({addr[1],addr[0]})//Position where byte read from depends on A1,A0 + 2'b00 :begin + $display("Master recieved data %h addr:00",data_in_4); + let resp_data = Resp_vme{ data:{24'b0, + data_in_4},berr:0,port_type:{dsack_0_l,dsack_1_l}}; + cpu_resp.enq(resp_data); + end + 2'b01 :begin + let resp_data = Resp_vme{ data:{24'b0, + + data_in_3},berr:0,port_type:{dsack_0_l,dsack_1_l}}; + cpu_resp.enq(resp_data); + $display("Master recieved data %h addr 01",data_in_3); + end + 2'b10 :begin + let resp_data = Resp_vme{ data:{24'b0, + data_in_2},berr:0,port_type:{dsack_0_l,dsack_1_l}}; + + $display("Master recieved data %h addr :10",data_in_2); + cpu_resp.enq(resp_data); + end + 2'b11 :begin + let resp_data = Resp_vme{ data:{24'b0, + data_in_1},berr:0,port_type:{dsack_0_l,dsack_1_l}}; + + + + $display("Master recieved data %h addr: 11",data_in_1); + cpu_resp.enq(resp_data); + end + endcase + //If slave is an 8 bit port + 2'b01 : begin + + let resp_data = Resp_vme{data:{24'b0,data_in_4 + },berr:0,port_type:{dsack_0_l,dsack_1_l}}; + cpu_resp.enq(resp_data); + + end + //if slave is a 16 bit port + 2'b10 : + if (addr[0]==1'b0) + begin + let resp_data =Resp_vme{ data:{24'b0,data_in_4 + },berr:0,port_type:{dsack_0_l,dsack_1_l}}; + + cpu_resp.enq(resp_data); + end + else + + begin + + let resp_data =Resp_vme{ data:{24'b0,data_in_3 + },berr:0,port_type:{dsack_0_l,dsack_1_l}}; + + cpu_resp.enq(resp_data); + end +endcase +else + if(mode==2'b10)//Receiving 16 bit data + + case({dsack_0_l,dsack_1_l}) + //...........SLAVE PORT....................:-32 byte + 2'b00 : + + case({addr[1],addr[0]})//Position where byte read from depends on A1,A0 + 2'b00 :begin + let resp_data = Resp_vme{ data:{16'b0,data_in_3, + data_in_4},berr:0,port_type:{dsack_0_l,dsack_1_l}}; + cpu_resp.enq(resp_data); + end + + 2'b10 :begin + let resp_data = Resp_vme{ data:{16'b0,data_in_1, + data_in_2},berr:0,port_type:{dsack_0_l,dsack_1_l}}; + + cpu_resp.enq(resp_data); + end + endcase + //If slave is an 8 bit port + 2'b01 :begin + + let resp_data = Resp_vme{data:{24'b0,data_in_4 + },berr:0,port_type:{dsack_0_l,dsack_1_l}}; + cpu_resp.enq(resp_data); + + end + //if slave is a 16 bit port + 2'b10 : + + begin + let resp_data =Resp_vme{ data:{16'b0,data_in_3, + data_in_4},berr:0,port_type:{dsack_0_l,dsack_1_l}}; + + cpu_resp.enq(resp_data); + end + endcase +else + if(mode==2'b00)//Receiving 32 bit data + + case({dsack_0_l,dsack_1_l}) + //...........SLAVE PORT....................:-32 bit port + 2'b00 :begin + + let resp_data = Resp_vme{ data:{data_in_1, + data_in_2,data_in_3,data_in_4},berr:0,port_type:{dsack_0_l,dsack_1_l}}; + $display("Master recieved data %h",{data_in_1,data_in_2,data_in_3,data_in_4}); + cpu_resp.enq(resp_data); + + end + //.......................................16 bit port + 2'b10 :begin + let resp_data = Resp_vme{ data:{16'b0,data_in_3, + data_in_4},berr:0,port_type:{dsack_0_l,dsack_1_l}}; + + cpu_resp.enq(resp_data); + end + + //........................If slave is an 8 bit port + 2'b01 : begin + + let resp_data = Resp_vme{data:{24'b0,data_in_4 + },berr:0,port_type:{dsack_0_l,dsack_1_l}}; + cpu_resp.enq(resp_data); + + // $display("Data_latched",data_in_4); + + end + + + endcase +else +begin + + let resp_data = Resp_vme{data:{24'b0,data_in_4 + },berr:0,port_type:{dsack_0_l,dsack_1_l}}; + cpu_resp.enq(resp_data); + + +end + + master_state<=END_REQ; + + +endrule +/* +1.Releases address and data strobe and data bus + +2. DSACK lines are deasserted one cycle after + +One more stage should be inserted here +*/ + +rule end_req(master_state==END_REQ); + + $display("\tMASTER_STATE_6:Releasing data strobes",$time); + ds_l<=1; + as_l<=1; + data_control<=4'b0000; + master_state<=ADDR_INVALID; + endrule + +rule rel_addr(master_state==ADDR_INVALID);//Release the address and data bus when transfer is finished + + if(stop==0 && retry==0) + begin + if(((dsack_0_l!=0)&&(dsack_1_l!=0))||(berr_l!=1'b0)) + master_state<=RCV_REQ; + if(cntl_wd==2'b00) + + begin + $display("\tMASTER_STATE_7:Releasing address strobes",$time); + addr_en<=False; + mode_en<=False; + fun_code_en<=False; + end + + $display("Ready to receive a new request",$time); + + end + + else + master_state<=HALT; + +endrule + + +rule stop_wait(master_state==HALT); + +//If HALT.....resume when halt signal is negated +if(stop==1) + if (halt_l!=0) + begin + stop<=0; + master_state<=RCV_REQ; + $display("\tMASTER_STATE_7:Releasing address strobes",$time); + addr_en<=False; + mode_en<=False; + fun_code_en<=False; + + end + else + master_state<=HALT; + + +//If Retry.........start retry cycle when bus error and halt are negated +else + if(halt_l!=0 && berr_l!=0) + begin + retry<=0; + master_state<=PRC_REQ_1; + end + else + + master_state<=HALT; + + +endrule + +//Methods for driving signals in and out of master + + +interface Vme_out vme_interface; + + + method Bit#(1) wr_as_l(); + return as_l; + endmethod + + method Bit#(1) wr_ds_l(); + return ds_l; + endmethod + + + method Bit#(1) wr_wr_l(); + return wr_l; + endmethod + + + method Action rd_dsack_0_l(Bit#(1) x); + dsack_0_l<=x; + endmethod + + method Action rd_dsack_1_l(Bit#(1) y); + dsack_1_l<=y; + endmethod + + method Action rd_berr_l(Bit#(1) z); + berr_l<=z; + endmethod + + method Action rd_halt_l(Bit#(1) u); + halt_l<=u; + endmethod +endinterface + +/*Methods to emulate tristate functionality*/ + +interface Data_bus_inf data_bus; + + + method Bit#(1) wr_siz0(); + return mode[0]; + endmethod + + method Bit#(1) wr_siz1(); + return mode[1]; + endmethod + + method Bit#(32) wr_addr(); + return addr; + endmethod + method Bit#(8) wr_byte_31_24(); + return data_out_4; + endmethod + + method Bit#(8) wr_byte_23_16(); + return data_out_3; + endmethod + + method Bit#(8) wr_byte_15_8(); + return data_out_2; + endmethod + + method Bit#(3) wr_fun_code(); + return fun_code; + endmethod + + method Bit#(8) wr_byte_7_0(); + return data_out_1; + endmethod + + method Action rd_byte_31_24(Bit #(8) d4); + data_in_4<=d4; + endmethod + + method Action rd_byte_23_16(Bit #(8) d3); + data_in_3<=d3; + endmethod + + method Action rd_byte_15_8 (Bit #(8) d2); + data_in_2<=d2; + endmethod + + method Action rd_byte_7_0 (Bit #(8) d1); + data_in_1<=d1; + endmethod + + + method Bit#(4) wr_en(); + return data_control; + endmethod + + method Bool wr_mode_en(); + return mode_en; + endmethod + + + method Bool wr_addr_en(); + return addr_en; + endmethod + + + method Bool wr_fun_code_en(); + return fun_code_en; + endmethod + + +endinterface + +method Action get_req (Req_vme req) if(!(cpu_req.notEmpty())); +cpu_req.enq(req); +endmethod + +method ActionValue #(Resp_vme) resp(); +cpu_resp.deq(); +return cpu_resp.first(); +endmethod + + + +endmodule + +endpackage + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/peripherals/vme/vme_parameters.bsv b/src/peripherals/vme/vme_parameters.bsv new file mode 100644 index 0000000..39d6b5b --- /dev/null +++ b/src/peripherals/vme/vme_parameters.bsv @@ -0,0 +1,17 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ + + + `define Reg_width_vme_slave 32 + `define Reg_width_vme 32 diff --git a/src/peripherals/vme/vme_top.bsv b/src/peripherals/vme/vme_top.bsv new file mode 100644 index 0000000..502e0d8 --- /dev/null +++ b/src/peripherals/vme/vme_top.bsv @@ -0,0 +1,456 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +/* +Transalates AXI master request to VME master request +*/ +`define PADDR 56 +package vme_top; + + /* ======== Package imports ======= */ + import Vector :: *; + import FIFO :: *; + import ConfigReg ::*; + import AXI4_Types ::*; + import AXI4_Fabric ::*; + import Semi_FIFOF ::*; + import BUtils::*; + /*================================== */ + + /*========= Project imports ======== */ + `include "vme_parameters.bsv" + `include "defined_parameters.bsv" + import defined_types ::*; + import FIFOF ::*; + import vme_master :: *; + import vme_defines :: *; + /*================================== */ + + + interface Ifc_vme_top; + interface Vme_out proc_ifc; + interface Data_bus_inf proc_dbus; + interface AXI4_Slave_IFC#(`PADDR,`Reg_width,`USERSPACE) slave_axi_vme; + method Action rd_ipl(Bit#(3) ip); + /*-============================================================================= */ + endinterface + + typedef enum {DATA,INST} Priority_cache deriving (Bits, Eq, FShow); + typedef enum {DATA_MODE_8_READ,DATA_MODE_16_READ,DATA_MODE_32_READ,DATA_MODE_8_WRITE,DATA_MODE_16_WRITE,DATA_MODE_32_WRITE,INST_MODE} Data_mode deriving (Bits, Eq, FShow); + + function Bit#(2) modeconv_vme(Bit#(3) transfer_size ); + if(transfer_size==0)//8 bit transfer + return 2'b01; + else if (transfer_size==1)//16 bit transfer + return 2'b10; + else + return 2'b00;//32 bit transfer + endfunction + + (*synthesize*) + module mkvme_top(Ifc_vme_top); + + AXI4_Slave_Xactor_IFC #(`PADDR,`Reg_width,`USERSPACE) s_xactor <- mkAXI4_Slave_Xactor; + Vme_master proc_master <-mkvmemaster; + Reg#(Bit#(`Reg_width_vme_slave)) response_buff <-mkReg(0);//To buffer multiple cycle transfers + FIFOF#(Bit#(4)) ff_id <-mkSizedFIFOF(2);//To store request address of instruction + FIFOF#(Bit#(`Reg_width_vme_slave)) ff_address <-mkSizedFIFOF(2);//To store request address of instruction + FIFOF#(Data_mode) ff_req<-mkFIFOF;//To keep track of last pending request + Reg#(Bit#(2)) port_count <- mkReg(0); + Reg#(Bit#(32)) inst_rcvd <- mkReg(0); +//.....................................................SEND_REQUEST_TO_MEMORY.........................................................................................................................// +//....................................................................................................................................................................................................// + + + rule check_wr_request_to_memory; + let info<-pop_o(s_xactor.o_wr_addr); + let data<-pop_o(s_xactor.o_wr_data); + let request=Req_vme{addr:truncate(info.awaddr),wr_data:truncate(data.wdata),mode:modeconv_vme(info.awsize),fun_code:3'b010,rd_req:0}; + if(info.awaddr[27:0]==28'hFFFF_FFF) + request.fun_code=3'b111; + proc_master.get_req(request); + ff_id.enq(info.awid); + $display("Enqueing request onto VME"); + ff_address.enq(info.awaddr); + case(request.mode) + 2'b00 :ff_req.enq(DATA_MODE_32_WRITE); + 2'b01 :ff_req.enq(DATA_MODE_8_WRITE); + 2'b10 :ff_req.enq(DATA_MODE_16_WRITE); + endcase + + endrule + + + rule check_read_request_to_memory; + let info<- pop_o(s_xactor.o_rd_addr); + ff_id.enq(info.arid); + ff_address.enq(info.araddr); + let request=Req_vme{addr:truncate(info.araddr),wr_data:?,mode:modeconv_vme(info.arsize),fun_code:3'b010,rd_req:1}; + + case(request.mode) + 2'b00 :ff_req.enq(DATA_MODE_32_READ); + 2'b01 :ff_req.enq(DATA_MODE_8_READ); + 2'b10 :ff_req.enq(DATA_MODE_16_READ); + endcase + + proc_master.get_req(request); + + endrule + + (* preempts = "check_read_request_to_memory,check_wr_request_to_memory"*) + +//...............................................................SEND RESPONSE TO MEMORY................................................................................................................// +// +// Data is retreived from a Big-Endian memory and sent back in little Endian format + + (* mutually_exclusive="send_read_response_from_memory_to_mem_stage_8,send_read_response_from_memory_to_mem_stage_16,send_read_response_from_memory_to_mem_stage_32,send_write_response_from_memory_to_mem_stage_8,send_write_response_from_memory_to_mem_stage_16,send_write_response_from_memory_to_mem_stage_32"*) + + + rule send_read_response_from_memory_to_mem_stage_8(ff_req.first==DATA_MODE_8_READ); + let response <-proc_master.resp(); + ff_req.deq(); + let r = AXI4_Rd_Data {rresp: AXI4_OKAY, rdata:duplicate(response.data[7:0]),rlast:True, ruser: 0, rid: ff_id.first }; + if(response.berr==1'b1) + r.rresp = AXI4_SLVERR; + // if(ff_address.first[4]==1) + // r.rdata={response.data,32'b0}; + ff_address.deq(); + s_xactor.i_rd_data.enq(r); + $display("Data received %h from address %h to mem_stage",response.data,ff_id.first()); + ff_id.deq(); + endrule + + rule send_read_response_from_memory_to_mem_stage_16(ff_req.first==DATA_MODE_16_READ); + let response <-proc_master.resp(); + if(response.port_type==2'b10 ) + begin + ff_req.deq(); + let r = AXI4_Rd_Data {rresp: AXI4_OKAY, rdata:duplicate(response.data[15:0]),rlast:True, ruser: 0, rid: ff_id.first }; + if(response.berr==1'b1) + r.rresp = AXI4_SLVERR; + + // if(ff_address.first[4]==1) + // r.rdata={response.data,32'b0}; + ff_address.deq(); + s_xactor.i_rd_data.enq(r); + //let resp = To_Cpu_Mem {data_word:zeroExtend(response.data),bus_error:response.berr==1'b1,misaligned_error:1'b0,address:ff_id.first(),load_store:Load}; + ff_id.deq(); + $display("Data received %h from address %h to mem_stage",response.data,ff_id.first()); + end + else if(response.port_type==2'b01) + if(port_count==0) + begin + response_buff<=response.data; + port_count<=port_count+1; + end + else + begin + + ff_req.deq(); + let r = AXI4_Rd_Data {rresp: AXI4_OKAY, rdata:duplicate({response.data[7:0],response_buff[7:0]}),rlast:True,ruser: 0,rid: ff_id.first }; + if(response.berr==1'b1) + r.rresp = AXI4_SLVERR; + port_count<=0; + // if(ff_address.first[4]==1) + // r.rdata={16'b0,{response.data[7:0],response_buff[7:0]},32'b0}; + ff_address.deq(); + s_xactor.i_rd_data.enq(r); + response_buff<=0; + //let resp = To_Cpu_Mem {data_word:zeroExtend({response.data[7:0],response_buff[7:0]}),bus_error:response.berr==1'b1,misaligned_error:1'b0,address:ff_id.first( ),load_store:Load}; + ff_id.deq(); + $display("Data received %h from address %h to mem_stage",{response.data[7:0],response_buff[7:0]},ff_id.first()); + + end + + else + + begin + + ff_req.deq(); + port_count<=0; + response_buff<=0; + let r = AXI4_Rd_Data{rresp: AXI4_OKAY, rdata:duplicate(response.data[15:0]),rlast:True,ruser: 0,rid: ff_id.first }; + if(response.berr==1'b1) + r.rresp = AXI4_SLVERR; + // if(ff_address.first[4]==1) + // r.rdata={response.data,32'b0}; + ff_address.deq(); + s_xactor.i_rd_data.enq(r); + ff_id.deq(); + $display("Data received %h from address %h mem_stage",{response.data[15:0]},ff_id.first()); + end + endrule + + + rule send_read_response_from_memory_to_mem_stage_32(ff_req.first==DATA_MODE_32_READ); + let response <-proc_master.resp(); + if(response.port_type==2'b00) + begin + ff_req.deq(); + let r = AXI4_Rd_Data{rresp: AXI4_OKAY, rdata:duplicate({response.data}),rlast:True,ruser: 0,rid: ff_id.first }; + if(response.berr==1'b1) + r.rresp = AXI4_SLVERR; + // if(ff_address.first[4]==1) + // r.rdata={response.data,32'b0}; + ff_address.deq; + s_xactor.i_rd_data.enq(r); + ff_id.deq(); + $display("Data received %h from address %h from mem_stage",response.data,ff_id.first()); + end + + + else if(response.port_type==2'b10) + + if(port_count==0) + begin + response_buff<=response.data; + port_count<=port_count+1; + end + else + + begin + + ff_id.deq(); + ff_req.deq(); + port_count<=0; + response_buff<=0; + let r = AXI4_Rd_Data{rresp: AXI4_OKAY, rdata:duplicate({response.data[15:0],response_buff[15:0]}),rlast:True,ruser: 0,rid: ff_id.first }; + if(response.berr==1'b1) + r.rresp = AXI4_SLVERR; + // if(ff_address.first[4]==1) + // r.rdata={{response.data[15:0],response_buff[15:0]},32'b0}; + ff_address.deq; + s_xactor.i_rd_data.enq(r); + $display("Data received %h from address %h from mem_stage",{response.data[15:0],response_buff[15:0]},ff_id.first()); + + end + + else if(response.port_type==2'b01) + begin + + if(port_count<3) + begin + response_buff<={response.data[7:0],response_buff[23:0]}; + port_count<=port_count+1; + end + else + begin + + ff_req.deq(); + port_count<=0; + response_buff<=0; + let r = AXI4_Rd_Data{rresp: AXI4_OKAY, rdata:duplicate({response.data[7:0],response_buff[23:0]}),rlast:True,ruser: 0,rid: ff_id.first }; + if(response.berr==1'b1) + r.rresp = AXI4_SLVERR; + // if(ff_address.first[4]==1) + // r.rdata={{response.data[15:0],response_buff[15:0]},32'b0}; + ff_address.deq; + s_xactor.i_rd_data.enq(r); + ff_id.deq(); + + $display("Data received %h from address %h to mem_stage",{response.data[7:0],response_buff[23:0]},ff_id.first()); + + end + + end + endrule + + + + + /* rule send_read_response_from_memory_to_fetch(ff_req.first==INST_MODE); //MEMORY READ RESP TO ICACHE + let response <-proc_master.resp(); + if(response.port_type==2'b00) + begin + ff_req.deq(); + ff_id_imem.deq(); + inst_rcvd <= response.data; + let resp = To_Cpu{data_word:zeroExtend(response.data),bus_error:response.berr==1'b1,misaligned_error:1'b0,address:ff_id_imem.first()}; + $display("Data received %h from address %h to fetch_stage",response.data,ff_id_imem.first()); + end + + + else if(response.port_type==2'b10) + + if(port_count==0) + begin + response_buff<=response.data; + port_count<=port_count+1; + end + else + begin + ff_id_imem.deq(); + ff_req.deq(); + port_count<=0; + response_buff<=0; + inst_rcvd <= {response.data[15:0],response_buff[15:0]}; + let resp= To_Cpu{data_word:zeroExtend({response.data[15:0],response_buff[15:0]}),bus_error:response.berr==1'b1,misaligned_error:1'b0,address:ff_id_imem.first()}; + $display("Data received %h from address %h to fetch_stage",{response.data[15:0],response_buff[15:0]},ff_id_imem.first()); + + end + endrule +*/ + + rule send_write_response_from_memory_to_mem_stage_8(ff_req.first==DATA_MODE_8_WRITE);//MEMORY WRITE RESP TO DCACHE + + let response <-proc_master.resp(); + ff_req.deq(); + let resp = AXI4_Wr_Resp {bresp: AXI4_OKAY, bid: ff_id.first}; + if (response.berr==1'b1) + resp.bresp=AXI4_SLVERR; + ff_id.deq(); + + ff_address.deq(); + s_xactor.i_wr_resp.enq(resp); + `ifdef verbose $display($time,"\t CORE: Received Write Response:"); `endif + endrule + + rule send_write_response_from_memory_to_mem_stage_16(ff_req.first==DATA_MODE_16_WRITE); + let response <-proc_master.resp(); + $display("Received respons from port_type %h",response.port_type); + if(response.port_type==2'b10 ) + begin + ff_req.deq(); + ff_id.deq(); + `ifdef verbose $display($time,"CORE: Received Write Response:"); `endif + //let resp = To_Cpu_Mem {data_word:?,bus_error:response.berr==1'b1,misaligned_error:1'b0,address:ff_id.first(),load_store:Store}; + let resp = AXI4_Wr_Resp {bresp: AXI4_OKAY, bid: ff_id.first}; + + ff_address.deq(); + if (response.berr==1'b1) + resp.bresp=AXI4_SLVERR; + s_xactor.i_wr_resp.enq(resp); + + end + else if(response.port_type==2'b01) + if(port_count==0) + begin + port_count<=port_count+1; + end + else + + begin + + ff_address.deq(); + // ff_id.deq(); + ff_req.deq(); + port_count<=0; + `ifdef verbose $display($time,"CORE: Received Write Response:"); `endif + /// let resp = To_Cpu_Mem {data_word:?,bus_error:response.berr==1'b1,misaligned_error:1'b0,address:ff_id.first(),load_store:Store}; + let resp = AXI4_Wr_Resp {bresp: AXI4_OKAY, bid: ff_id.first}; + if (response.berr==1'b1) + resp.bresp=AXI4_SLVERR; + ff_id.deq(); + s_xactor.i_wr_resp.enq(resp); + + end + + else + + begin + + ff_address.deq(); + // ff_id.deq(); + ff_req.deq(); + port_count<=0; + response_buff<=0; + + `ifdef verbose $display($time,"CORE: Received Write Response:"); `endif + //let resp = To_Cpu_Mem {data_word:?,bus_error:response.berr==1'b1,misaligned_error:1'b0,address:ff_id.first(),load_store:Store}; + let resp = AXI4_Wr_Resp {bresp: AXI4_OKAY, bid: ff_id.first}; + if (response.berr==1'b1) + resp.bresp=AXI4_SLVERR; + ff_id.deq(); + s_xactor.i_wr_resp.enq(resp); + + end + + endrule + + rule send_write_response_from_memory_to_mem_stage_32(ff_req.first==DATA_MODE_32_WRITE); + let response <-proc_master.resp(); + if(response.port_type==2'b00) + begin + ff_req.deq(); + // + + + + + + `ifdef verbose $display($time,"CORE: Received Write Response:"); `endif + + //let resp = To_Cpu_Mem {data_word:?,bus_error:response.berr==1'b1,misaligned_error:1'b0,address:ff_id.first(),load_store:Store}; + + let resp = AXI4_Wr_Resp {bresp: AXI4_OKAY, bid: ff_id.first}; + if (response.berr==1'b1) + resp.bresp=AXI4_SLVERR; + ff_id.deq(); + ff_address.deq(); + s_xactor.i_wr_resp.enq(resp); + end + + else if(response.port_type==2'b10) + + if(port_count==0) + begin + port_count<=port_count+1; + end + else + + begin + + // ff_id.deq(); + ff_req.deq(); + ff_address.deq(); + port_count<=0; + + ff_id.deq(); + let resp = AXI4_Wr_Resp {bresp: AXI4_OKAY, bid: ff_id.first}; + if (response.berr==1'b1) + resp.bresp=AXI4_SLVERR; + s_xactor.i_wr_resp.enq(resp); + // let resp = To_Cpu_Mem {data_word:?,bus_error:response.berr==1'b1,misaligned_error:1'b0,address:ff_id.first(),load_store:Store}; + + `ifdef verbose $display($time,"CORE: Received Write Response:"); `endif + + end + else if(response.port_type==2'b01) + begin + if(port_count<3) + begin + port_count<=port_count+1; + end + else + begin + + // ff_id.deq(); + ff_req.deq(); + ff_address.deq(); + port_count<=0; + let resp = AXI4_Wr_Resp {bresp: AXI4_OKAY, bid: ff_id.first}; + if (response.berr==1'b1) + resp.bresp=AXI4_SLVERR; + ff_id.deq(); +// let resp = To_Cpu_Mem {data_word:?,bus_error:response.berr==1'b1,misaligned_error:1'b0,address:ff_id.first(),load_store:Store}; + s_xactor.i_wr_resp.enq(resp); + + `ifdef verbose $display($time,"CORE: Received Write Response:"); `endif + end + end + endrule + interface proc_ifc = proc_master.vme_interface; + interface proc_dbus = proc_master.data_bus; + interface slave_axi_vme = s_xactor.axi_side; +endmodule +endpackage diff --git a/src/uncore/axi4/SlaveWrapper.bsv b/src/uncore/axi4/SlaveWrapper.bsv new file mode 100644 index 0000000..f226a52 --- /dev/null +++ b/src/uncore/axi4/SlaveWrapper.bsv @@ -0,0 +1,62 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +package SlaveWrapper; + /*======= Project Imports ====*/ + import AXI4_Types::*; + import AXI4_Fabric :: *; + import AXI4_Lite_Types::*; + import AXI4_Lite_Fabric :: *; + import Mem_Controller::*; + /*==============================*/ + + interface SlaveWrapper; + interface AXI4_Lite_Slave_IFC #(Wd_Addr, Wd_Data, Wd_User) axi4slave; + interface AXI4_Lite_Master_IFC #(Wd_Addr, Wd_Data, Wd_User) axi4litemaster; + endinterface + + module mkSlaveWrapper(SlaveWrapper); + AXI4_Slave_Xactor_IFC #(`Addr_width, `Reg_width, 0) s_axi4xactor <- mkAXI4_Slave_Xactor; + AXI4_Lite_Master_Xactor_IFC #(`Addr_width, `Reg_width, 0) m_axi4litexactor <- mkAXI4_Lite_Slave_Xactor; + + Reg#(Bit#(8)) rg_readburst_counter<-mkReg(0); + Reg#(Bit#(8)) rg_readburst_value<-mkReg(0); + Reg#(Bit#(8)) rg_writeburst_counter<-mkReg(0); + Reg#(Bit#(8)) rg_writeburst_value<-mkReg(0); + + rule rl_wr_request; + // Get the wr request + let awreq <- pop_o (s_xactor.o_wr_addr); + let wreq <- pop_o (s_xactor.o_wr_data); + let aw = AXI4_Lite_Wr_Addr {awaddr: awreq.awaddr, awprot:awreq.awprot, awuser:0}; + let w = AXI4_Lite_Wr_Data {wdata: wreq.wdata, wstrb: wreq.wstrb,}; + m_axi4litexactor.i_wr_addr.enq(aw); + m_axi4litexactor.i_wr_data.enq(w); + rg_writeburst_value<=awreq.awlen; + endrule + + rule rl_wr_response; + let axi4lite_wr_response<-pop_o(m_axi4litexactor.o_wr_resp); + let b = AXI4_Wr_Resp {bresp: axi4lite_wr_response.bresp, buser: axi4lite_wr_response.buser}; + if(rg_writeburst_counter==rg_writeburst_value)begin + rg_writeburst_counter<=0; + s_axi4xactor.i_wr_resp.enq (b); + end + else + rg_writeburst_counter<=rg_writeburst_counter+1; + `ifdef verbose $display($time,"\t",module_name,":\t Recieved Write Request for Address: %h data: %h strb: %b awlen: %d rg_writeburst_counter: %d",aw.awaddr,w.wdata,w.wstrb,aw.awlen,rg_writeburst_counter); `endif + endrule + + endmodule + +endpackage diff --git a/src/uncore/debug/DebugModule.bsv b/src/uncore/debug/DebugModule.bsv new file mode 100644 index 0000000..75636cc --- /dev/null +++ b/src/uncore/debug/DebugModule.bsv @@ -0,0 +1,654 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +package DebugModule; + /*====== Package imports === */ + import FIFO::*; + import FIFOF::*; + import SpecialFIFOs::*; + import Semi_FIFOF::* ; + import GetPut::*; + import ClientServer::*; + import Vector::*; + import BUtils::*; + import ConfigReg::*; + import DReg::*; + /*========================== */ + /*=== Project imports === */ + import ConcatReg::*; + import AXI4_Types::*; + import AXI4_Fabric::*; + `include "defines.bsv" + `include "defined_parameters.bsv" + import defined_types::*; + import core :: *; + /*========================= */ + + function Reg#(t) readOnlyReg(t r); + return (interface Reg; + method t _read = r; + method Action _write(t x) = noAction; + endinterface); + endfunction + interface Ifc_DebugModule; + method Action set_external_interrupt(Tuple2#(Bool,Bool) i); + method Action request_from_dtm(Bit#(40) requestfrmDTM); + method ActionValue#(Bit#(34)) response_to_dtm; + interface AXI4_Master_IFC#(`PADDR, `Reg_width, `USERSPACE) debug_master; + interface AXI4_Slave_IFC#(`PADDR, `Reg_width, `USERSPACE) debug_slave; + /*======= Core related interfaces ====== */ + interface AXI4_Master_IFC#(`PADDR, `Reg_width, `USERSPACE) imem_master; + interface AXI4_Master_IFC#(`PADDR, `Reg_width, `USERSPACE) dmem_master; + (*always_ready,always_enabled*) + method Action boot_sequence(Bit#(1) bootseq); + `ifdef CLINT + method Action clint_msip(Bit#(1) intrpt); + method Action clint_mtip(Bit#(1) intrpt); + method Action clint_mtime(Bit#(`Reg_width) c_mtime); + `endif + /*===========================================*/ + endinterface + + // this function is used to generate a resume request only when written by the + // debugger + function Reg#(Bit#(1)) condwriteSideEffect(Reg#(Bit#(1)) r, Action a); + return (interface Reg; + method Bit#(1) _read = r._read; + method Action _write(Bit#(1) x); + r._write(x); + if(x==1) + a; + endmethod + endinterface); + endfunction + + (*synthesize*) + module mkDebugModule#(Bit#(`VADDR) reset_vector)(Ifc_DebugModule); + // Instantiating the Core + Ifc_core_AXI4 c64 <-mkcore_AXI4(reset_vector); + // Instantiating the AXI4 Master + AXI4_Master_Xactor_IFC #(`PADDR,`Reg_width,`USERSPACE) master_xactor <- mkAXI4_Master_Xactor; + AXI4_Slave_Xactor_IFC #(`PADDR, `Reg_width, `USERSPACE) slave_xactor <- mkAXI4_Slave_Xactor; + + /*========= FIFOs to communicate with the DTM==== */ + FIFOF#(Bit#(34)) response_to_DTM <-mkFIFOF(); + /*================================================ */ + + /*======= HART INFO REGISTERS =========== */ + Reg#(Bit#(4)) nscratch =readOnlyReg(4'd2); + Reg#(Bit#(1)) dataaccess = readOnlyReg(1'b1); + Reg#(Bit#(4)) datasize = readOnlyReg(4'd12); + Reg#(Bit#(12)) dataaddr = readOnlyReg(12'h4c); + Reg#(Bit#(32)) hart_info =concatReg6(readOnlyReg(8'b0), + nscratch,readOnlyReg(3'b0),dataaccess,datasize,dataaddr); + /*======================================== */ + //Registers from debug spec .13 start here + /*========= DM Control Registers ======== */ + Reg#(Bit#(1)) haltreq<-mkReg(0); + Reg#(Bool) wr_gen_haltreq<-mkDReg(False); + Reg#(Bit#(1)) rg_haltreq=condwriteSideEffect(haltreq,wr_gen_haltreq._write(True)); + Reg#(Bit#(1)) resume<-mkReg(0); + Reg#(Bool) wr_gen_resumereq<-mkDReg(False); + Reg#(Bit#(1)) rg_resumereq=condwriteSideEffect(resume,wr_gen_resumereq._write(True)); + Reg#(Bit#(1)) rg_hartreset<-mkReg(0); + Reg#(Bit#(1)) rg_reset<-mkReg(0); + Reg#(Bit#(1)) rg_dmactive<-mkReg(1'b0); + Reg#(Bit#(10)) rg_hartsel<-mkReg(0); + Reg#(Bit#(32)) dm_control =concatReg9(rg_haltreq,rg_resumereq, + rg_hartreset,readOnlyReg(2'b0),readOnlyReg(1'b0),rg_hartsel, + readOnlyReg(14'b0),rg_reset,rg_dmactive); + /*======================================== */ + + /*====== DM STATUS REGISTERS ========== */ + Reg#(Bit#(1)) rg_resumeack[2]<-mkCReg(2,0); // This is the Resume ACK + Reg#(Bit#(1)) rg_unavailable<-mkReg(0); + Reg#(Bit#(1)) rg_running <-mkReg(0); + Reg#(Bit#(1)) rg_halted<-mkReg(0); + ConfigReg#(Bit#(1)) rg_nonexistent<-mkConfigReg(0); + Reg#(Bit#(32)) dm_status =concatReg12(readOnlyReg(14'd0), + readOnlyReg(rg_resumeack[1]),readOnlyReg(rg_resumeack[1]), + readOnlyReg(rg_nonexistent),readOnlyReg(rg_nonexistent), readOnlyReg(rg_unavailable),readOnlyReg(rg_unavailable), + readOnlyReg(rg_running), readOnlyReg(rg_running), + readOnlyReg(rg_halted), readOnlyReg(rg_halted), + readOnlyReg(8'b10000010)); // TODO Make the 4th bit if using Configstring + /*======================================== */ + + /*== ABSTRACT REGISTERS === */ + Reg#(Bit#(1)) rg_busy[3]<-mkCReg(3,0); + Reg#(Bit#(3)) rg_cmderr<-mkReg(0); + Reg#(Bit#(32)) abstract_Control_And_Status=concatReg8(readOnlyReg(3'b0), + readOnlyReg(5'd16),readOnlyReg(11'b0), + readOnlyReg(rg_busy[2]),readOnlyReg(1'b0),rg_cmderr, + readOnlyReg(3'b0),readOnlyReg(5'd12)); + + Reg#(Bit#(8)) rg_cmdtype <-mkReg(0); + Reg#(Bit#(24)) rg_control<-mkReg(0); + Reg#(Bit#(32)) abstract_Commands =concatReg2(rg_cmdtype,rg_control); // + + Reg#(Bit#(16)) rg_autoexecprogbuf<-mkReg(0); + Reg#(Bit#(12)) rg_autoexecdata<-mkReg(0); + Reg#(Bit#(32)) abstract_Command_Autoexe =concatReg3(rg_autoexecprogbuf,readOnlyReg(4'b0),rg_autoexecdata) ; + Vector#(12,Array#(Reg#(Bit #(32)))) abstract_Data <- replicateM(mkCReg(2,0)); + /*======================================== */ + + + //Reg#(Bit#(32)) configuration_String_Addr_0<-mkReg (0) ; // TODO need to fiure this out + //Reg#(Bit#(32)) configuration_String_Addr_1<-mkReg (0) ; + //Reg#(Bit#(32)) configuration_String_Addr_2<-mkReg (0) ; + //Reg#(Bit#(32)) configuration_String_Addr_3<-mkReg (0) ; + //Reg#(Bit#(32)) serial_Control_And_Status <-mkReg (0) ; + //Reg#(Bit#(64)) serial_Data <-mkReg(0) ; + /*======= System Bus Access Registers ======= */ + Reg#(Bit#(3)) rg_sberror<-mkReg(0); + Reg#(Bit#(1)) rg_sbautoread<-mkReg(0); + Reg#(Bit#(1)) rg_sbautoincrement<-mkReg(0); + Reg#(Bit#(3)) rg_sbaccess<-mkReg(0); + Reg#(Bit#(1)) rg_sbsingleread[2]<-mkCReg(2,0); + Reg#(Bit#(32)) bus_ctrlstatus=concatReg8(readOnlyReg(11'b0), + rg_sbsingleread[1],rg_sbaccess, + rg_sbautoincrement,rg_sbautoread, + rg_sberror,readOnlyReg(7'h40), + readOnlyReg(5'b01111)); + + Reg#(Bit#(32)) busAddr0[2] <- mkCReg(2,0) ; + Reg#(Bit#(32)) busData0[2] <- mkCReg(2,0) ; + Reg#(Bit#(32)) busData1[2] <- mkCReg(2,0) ; + /*======================================== */ + Vector#(16,Array#(Reg#(Bit #(32) ))) program_Buffer <- replicateM(mkCReg(2,0)) ; + + //not in spec , internally maintained for write + Reg#(Bool) write_flag[2] <- mkCReg(2,False) ; + Reg#(Bool) reset_status <-mkReg(True) ; // not in spec internally maintained for reset + Reg#(Bit#(32)) instruction0<-mkReg('h0000100f); // 0x0000100f fence.i + Reg#(Bit#(32)) instruction1<-mkReg('h00000013); // 0x00000013 nop (addi x0,x0,0) + Reg#(Bit#(32)) instruction2<-mkReg('hffdff06f); // 0xffdff06f jump to nop + Reg#(Bit#(32)) instruction3<-mkReg('h0040006f); // jump to progbuffer + Reg#(Bool) prog_ebreak_read<-mkReg(False); + Reg#(Bool) perform_reg_access[2] <-mkCReg(2,False); + Reg#(Bool) start_program_exec[3] <-mkCReg(3,False); + // 0 0 0 0100 0 0 0000 0110 1111 + rule generate_nonexistent; + rg_nonexistent<=rg_hartsel==0?0:1; + endrule + rule rl_rd_respond; + // Get the wr request + let ar<- pop_o(slave_xactor.o_rd_addr); + AXI4_Rd_Data#(`Reg_width,`USERSPACE) r = AXI4_Rd_Data {rresp: AXI4_OKAY, rdata: ? ,rlast:True,ruser:0,rid:ar.arid}; + `ifdef verbose + $display($time,"\tDEBUG:Address:%h size: %d",ar.araddr,ar.arsize); + $display($time,"\tDEBUG:Abstract Command: %h,%h,%h,start_program_exec %h",ar.araddr,rg_control[18] ,rg_busy[1],start_program_exec[0]); + `endif + if(ar.araddr>= (`DebugBase + 'h4c) && ar.araddr<=`DebugEnd)begin + Bit#(4) index=truncate((ar.araddr-'h4c)>>2); + `ifdef verbose $display($time,"\tDEBUG: Reading abstract data %d",index); `endif + if(ar.arsize==3)begin + r.rdata={abstract_Data[index+1][0],abstract_Data[index][0]}; + end + else if(ar.arsize==2)begin + r.rdata=duplicate(abstract_Data[index][0]); + end + else + r.rresp=AXI4_SLVERR; + end + else if(ar.araddr>= (`DebugBase + 12) && ar.araddr<= `DebugBase+'h48) + begin + let index=(ar.araddr[5:2]-3); + `ifdef verbose $display($time,"\tDEBUG: Reading program buffer %d",index); `endif + Bit#(`Reg_width) data0={program_Buffer[index+1][0],program_Buffer[index][0]}; + if(ar.arsize==3)begin + r.rdata={program_Buffer[index+1][0],program_Buffer[index][0]}; + end + else if(ar.arsize==2)begin // 32 bit + r.rdata=duplicate(program_Buffer[index][0]); + end + else if (ar.arsize=='d1)begin // half_word + if(ar.araddr[`byte_offset:0] ==0) + r.rdata = duplicate(data0[15:0]); + else if(ar.araddr[`byte_offset:0] ==2) + r.rdata = duplicate(data0[31:16]); + `ifdef RV64 + else if(ar.araddr[`byte_offset:0] ==4) + r.rdata = duplicate(data0[47:32]); + else if(ar.araddr[`byte_offset:0] ==6) + r.rdata = duplicate(data0[63:48]); + `endif + end + else if (ar.arsize=='d0) begin// one byte + if(ar.araddr[`byte_offset:0] ==0) + r.rdata = duplicate(data0[7:0]); + else if(ar.araddr[`byte_offset:0] ==1) + r.rdata = duplicate(data0[15:8]); + else if(ar.araddr[`byte_offset:0] ==2) + r.rdata = duplicate(data0[23:16]); + else if(ar.araddr[`byte_offset:0] ==3) + r.rdata = duplicate(data0[31:24]); + `ifdef RV64 + else if(ar.araddr[`byte_offset:0] ==4) + r.rdata = duplicate(data0[39:32]); + else if(ar.araddr[`byte_offset:0] ==5) + r.rdata = duplicate(data0[47:40]); + else if(ar.araddr[`byte_offset:0] ==6) + r.rdata = duplicate(data0[55:48]); + else if(ar.araddr[`byte_offset:0] ==7) + r.rdata = duplicate(data0[63:56]); + `endif + end + if((program_Buffer[index][0][14:12]==`EBREAK_f3 && program_Buffer[index][0][6:2]==`CSR_op)) + begin + start_program_exec[0]<=False; + `ifdef verbose $display($time,"\tDEBUG: EBREAK encountered"); `endif + end + end + else if(ar.araddr==`DebugBase && ar.arsize==2) + r.rdata=duplicate(instruction0); + else if(ar.araddr==`DebugBase+4 && ar.arsize==2) + r.rdata=duplicate(instruction1); + else if(ar.araddr==`DebugBase+8 && rg_control[18] == 1 && start_program_exec[0]) // postexec and busy + begin + r.rdata=duplicate(instruction3); + `ifdef verbose $display($time,"\tDEBUG :Redirecting to program buffer"); `endif + end + else if(ar.araddr==`DebugBase+8 && ar.arsize==2)begin + r.rdata=duplicate(instruction2); + rg_busy[1]<=0; + end + else + r.rresp=AXI4_SLVERR; + `ifdef verbose $display($time,"\tDEBUG: Reading Address:%h Data: %h",ar.araddr,r.rdata); `endif + slave_xactor.i_rd_data.enq(r); + endrule + + rule rl_wr_response(!perform_reg_access[0]); + let aw <- pop_o (slave_xactor.o_wr_addr); + let w <- pop_o (slave_xactor.o_wr_data); + let b = AXI4_Wr_Resp {bresp: AXI4_OKAY, buser: aw.awuser, bid:aw.awid}; + if(aw.awaddr>= (`DebugBase + 'h4c) && aw.awaddr<=`DebugEnd)begin + Bit#(4) index=truncate((aw.awaddr-'h4c)>>2); + if(aw.awsize==3)begin + abstract_Data[index+1][0]<=w.wdata[63:32]; + abstract_Data[index][0]<=w.wdata[31:0]; + end + else if(aw.awsize==2)begin + if(w.wstrb=='hf0) + abstract_Data[index+1][0]<=w.wdata[63:32]; + else if(w.wstrb=='h0f) + abstract_Data[index][0]<=w.wdata[31:0]; + end + else + b.bresp=AXI4_SLVERR; + end + else if(aw.awaddr>= (`DebugBase + 12) && aw.awaddr<= (`DebugBase+'h48)) + begin + //let index=(aw.awaddr[7:0]-8)>>2; + let index=(aw.awaddr[5:2]-3); + if(w.wstrb=='hf0) + program_Buffer[index+1][0]<=w.wdata[63:32]; + else if(w.wstrb=='h0f) + program_Buffer[index][0]<=w.wdata[31:0]; + else if(w.wstrb=='hff)begin + program_Buffer[index][0]<=w.wdata[31:0]; + program_Buffer[index+1][0]<=w.wdata[63:32]; + end + end + else + b.bresp=AXI4_SLVERR; + slave_xactor.i_wr_resp.enq (b); + endrule + + + (*conflict_free = "access_register_or_pc,access_csrs"*) + + /*=== Rules to halt the CPU === */ + rule halt_request(wr_gen_haltreq && rg_halted == 0); + `ifdef verbose $display($time,"\tDEBUG: Requesting Halt"); `endif + c64.stop; + endrule + + `ifdef verbose + rule display_Stuff; + `ifdef verbose $display($time,"\tDEBUG: HALT: %b",rg_halted); `endif + endrule + `endif + + rule halt_status_of_cpu; + rg_halted <= pack(c64.halted) ; + endrule + + rule resume_status(!wr_gen_resumereq); + if(resume==1 && !c64.halted) + rg_resumeack[0] <= 1; + endrule + + rule resume_request(wr_gen_resumereq); + `ifdef verbose $display($time,"\tDEBUG: Requesting Resume\n"); `endif + // insert set for resume request set to zero here + rg_resumeack[0]<= 1'b0; // assert low on request + c64.run_continue; + endrule + + + rule reset(rg_hartreset == 1 && reset_status); + c64.reset; + `ifdef verbose $display($time,"\tDEBUG: Requesting Reset"); `endif + endrule + + rule rst_status; + reset_status <= c64.reset_complete ; + endrule + rule access_register_or_pc(rg_halted == 1 && perform_reg_access[0] && rg_control[12]==1); + `ifdef verbose $display($time,"\tDEBUG: Access CONTROL: %h rg_halted: %b REGISTER NO.: %h",rg_control,rg_halted,abstract_Commands[15:0]); `endif + if(rg_control[16] == 0 && rg_control[17] == 1)// READ Operation + begin + `ifdef verbose $display($time,"\tREAD REGISTER OPERATION "); `endif + Bit#(`Reg_width) read_data =0; + if(rg_control[5] ==0) + begin + read_data = c64.read_igpr(rg_control[4:0]) ; + `ifdef verbose $display($time,"\tReading IGPR %d val: %h",rg_control[4:0],read_data); `endif + end + `ifdef spfpu + else + begin + read_data = c64.read_fgpr(rg_control[4:0]) ; + `ifdef verbose $display($time,"\tReading FGPR %d val: %h",rg_control[4:0],read_data); `endif + end + `endif + if(rg_control[22:20] == 2)begin + abstract_Data[0][0] <= read_data[31:0] ; + end + else if(rg_control[22:20] == 3)begin + abstract_Data[0][0] <= read_data[31:0] ; + abstract_Data[1][0] <= read_data[63:32] ; + end + end + else if(rg_control[16] == 1 && rg_control[17] == 1) // Write operation + begin + Bit#(64) write_data = 0 ; + if(rg_control[22:20] == 2)begin + write_data = zeroExtend(abstract_Data[0][0]) ; + end + else if(rg_control[22:20] == 3)begin + write_data[31:0] = abstract_Data[0][0] ; + write_data[63:32] = abstract_Data[1][0] ; + end + + if(rg_control[5] == 'h0) + begin + c64.write_igpr(rg_control[4:0],truncate(write_data) ) ; + `ifdef verbose $display($time,"\tWriting IGPR %d val: %h",rg_control[4:0],write_data); `endif + end + `ifdef spfpu + else + begin + c64.write_fgpr(rg_control[4:0],truncate(write_data)) ; + `ifdef verbose $display($time,"\tWriting FGPR %d val: %h",rg_control[4:0],write_data); `endif + end + `endif + end + perform_reg_access[0]<=False; + if(rg_control[18] == 1)begin + start_program_exec[1] <= True ; //clear busy + `ifdef verbose $display("DEBUG: De-assert Abstract Busy\n"); `endif + end + else + rg_busy[1]<=0; + endrule + + rule access_csrs(rg_halted==1 && perform_reg_access[0] && rg_control[17]==1 && rg_control[12]==0); + Bit#(`Reg_width) read_data =0; + if(rg_control[16]==0)begin// READ Operation + let x<-c64.rw_csr(rg_control[11:0],False,?); + read_data=x; + `ifdef verbose $display($time,"\tDEBUG: READING CSR : address : %h data: %h",rg_control[11:0],read_data); `endif + if(rg_control[22:20] == 2)begin + abstract_Data[0][0] <= read_data[31:0] ; + end + else if(rg_control[22:20] == 3)begin + abstract_Data[0][0] <= read_data[31:0] ; + abstract_Data[1][0] <= read_data[63:32] ; + end + end + else begin// WRITE Operation + Bit#(64) write_data = 0 ; + if(rg_control[22:20] == 2)begin + write_data = zeroExtend(abstract_Data[0][0]) ; + end + else if(rg_control[22:20] == 3)begin + write_data[31:0] = abstract_Data[0][0] ; + write_data[63:32] = abstract_Data[1][0] ; + end + `ifdef verbose $display($time,"\tDEBUG: WRITING CSR : address : %h data: %h",rg_control[11:0],write_data); `endif + let x<-c64.rw_csr(rg_control[11:0],True,write_data); + end + perform_reg_access[0] <=False; //clear busy + if(rg_control[18] == 1)begin + start_program_exec[1] <= True ; //clear busy + `ifdef verbose $display("DEBUG: De-assert Abstract Busy\n"); `endif + end + else + rg_busy[1]<=0; + `ifdef verbose $display($time,"\tDEBUG: De-assert Abstract Busy\n"); `endif + endrule + + + /*==================================== */ + + rule access_memory_request (rg_sbsingleread[0]==1 || write_flag[0] == True); + Bit #(32) address ; + address[31:0]=busAddr0[0]; + + Bit#(8) size =0 ; // size in bytes + case (rg_sbaccess) + 0: size = 1 ; + 1: size = 2; + 2: size = 4 ; + 3: size = 8 ; + endcase + + if(rg_sbsingleread[0] == 1) + begin + rg_sbsingleread[0]<=0; + let read_request = AXI4_Rd_Addr {araddr:truncate(address) , aruser: 0, arlen: 0, arsize:rg_sbaccess, arburst: 'b01, arid:'d2}; // arburst: 00-FIXED 01-INCR 10-WRAP + master_xactor.i_rd_addr.enq(read_request); + end + + else + begin + write_flag[0] <= False ; + Bit#(64) write_data=0; + if(size == 8) + begin + write_data[31:0] = busData0[0] ; + write_data[63:32] = busData1[0] ; + end + else + begin + if (size==4) + begin + write_data[31:0] = busData0[0] ; write_data[63:32]=busData0[0]; + end + if (size==2) + begin + write_data[15:0] = busData0[0][15:0];write_data[31:16] = busData0[0][15:0];write_data[47:32] = busData0[0][15:0];write_data[63:48] = busData0[0][15:0]; + end + if (size==1) + begin + write_data[7:0] = busData0[0][7:0];write_data[15:8] = busData0[0][7:0];write_data[23:16] = busData0[0][7:0];write_data[31:24] = busData0[0][7:0]; + write_data[39:32] = busData0[0][7:0];write_data[47:40] = busData0[0][7:0];write_data[55:48] = busData0[0][7:0];write_data[63:56] = busData0[0][7:0]; + end + end + Bit#(8) write_strobe=size==1?8'b1:size==2?8'b11:size==4?8'hf:8'hff; + if(size!=8)begin // 8-bit write; + write_strobe=write_strobe<<(address[`byte_offset:0]); + end + address[2:0]=0; + + `ifdef verbose $display("Debug : Memory Write: Data written : %d Address : %d Write_Strobe : %b",write_data[31:0],address,write_strobe); `endif + + let request_data = AXI4_Wr_Data {wdata: write_data , wstrb: write_strobe, wlast:True, wid:'d2}; + let request_address = AXI4_Wr_Addr {awaddr: address, awuser:0, awlen: 0, awsize: rg_sbaccess, awburst: 'b01, awid:'d2}; // arburst: 00-FIXED 01-INCR 10-WRAP + master_xactor.i_wr_addr.enq(request_address) ; + master_xactor.i_wr_data.enq(request_data) ; + + end + + if(rg_sbautoincrement == 1)begin + Bit #(32) address1 ; + address1[31:0]=busAddr0[0]; + address1 = address1 + zeroExtend(size) ; + busAddr0[0] <= address1[31:0] ; + end + endrule + + rule read_memory_response ; + let response<-pop_o(master_xactor.o_rd_data); + if (response.rresp==AXI4_OKAY && response.rid=='d2) + begin + Bit #(64) resp=zeroExtend (response.rdata); + busData0[0]<=resp[31:0] ; + busData1[0]<=resp[63:32] ; + end + endrule + + rule write_memory_response ; + let response <- pop_o(master_xactor.o_wr_resp) ; + if(response.bresp == AXI4_OKAY && response.bid=='d2) + begin + `ifdef verbose $display("Write Done Successfully"); `endif + end + endrule + + + + + + /*==== This rule will interact with the external DTM and perform Read/Write to the DM Registers === */ + //method ActionValue#(DTMResponse) toDTM(DTMRequest req)if(rg_busy[0]==0); + method Action request_from_dtm(Bit#(40) requestfrmDTM); + Bit#(2) op=requestfrmDTM[1:0]; + Bit#(32) data=requestfrmDTM[33:2]; + Bit#(6) address=requestfrmDTM[39:34]; + `ifdef verbose $display($time,"\tDEBUG: Receiving Request from DTM:\t op: %d data: %h address: %h",op,data,address); `endif + Bit#(34) response='h0; + if(op==2)begin // WRITE OPERATION + case (address) + `DMCONTROL: + begin + if(data[30] == 1 && data[31] == 1)begin + response[1:0] = 2 ; + end + else begin + dm_control<=data; + end + end + `DMSTATUS : dm_status<=data; + `HARTINFO : hart_info<=data; + `ABSTRACTCNTRL: abstract_Control_And_Status<=data; + `ABSTRACTCMD :begin if(rg_busy[2]==1 || start_program_exec[2]) rg_cmderr<=1; else begin abstract_Commands<=data; rg_busy[2]<=1; perform_reg_access[1]<=True; end end + `ABSTRACTCMDAUTO:begin abstract_Command_Autoexe<=data; end// ; rg_busy[0] <= 1 ; end + `BUSCONTROL: bus_ctrlstatus<=data; + `BUSADDRESS0:busAddr0[1]<=data; + `BUSDATA0 :begin busData0[1]<=data; write_flag[1] <= True ; end + `BUSDATA1 :busData1[1]<=data; + default: begin + if(address>=`ABSTRACTDATASTART && address<=`ABSTRACTDATAEND) + begin + `ifdef verbose $display($time,"DEBUG: Autoexec Write Detected"); `endif + abstract_Data[address[3:0]-`ABSTRACTDATASTART][1]<=data; + if(abstract_Command_Autoexe[address[3:0]-`ABSTRACTDATASTART] == 1) + begin + `ifdef verbose $display($time,"DEBUG: Autoexecuting command based on write to abstract data "); `endif + perform_reg_access[1] <=True; + end + end + else if(address>=`PBSTART && address<=`PBEND) + begin + `ifdef verbose $display($time,"\tDEBUG: Autoexec Write Detected to PG index: %h",address[3:0]); `endif + program_Buffer[address[3:0]][1]<=truncate(data); + if(rg_autoexecprogbuf[address[5:0]-`PBSTART + 16] == 1) + begin + `ifdef verbose $display($time,"\tDEBUG: Autoexecuting command based on write to program buffer"); `endif + perform_reg_access[1] <=True; + end + end + else + response[1:0]=2; + end + endcase + end + else if(op==1) begin // READ OPERATION + case (address) + `DMCONTROL : response[33:2]=dm_control; + `DMSTATUS : response[33:2]=dm_status; + `HARTINFO : response[33:2]=hart_info; + `ABSTRACTCNTRL: response[33:2]=abstract_Control_And_Status; + `ABSTRACTCMD : response[33:2]=abstract_Commands; + `ABSTRACTCMDAUTO:response[33:2]=abstract_Command_Autoexe; + `BUSCONTROL :response[33:2]=bus_ctrlstatus; + `BUSADDRESS0 :response[33:2]=busAddr0[1]; + `BUSDATA0 :begin + response[33:2]=busData0[1]; + if(rg_sbautoread == 1)begin + rg_sbsingleread[1] <= 1; + end + end + `BUSDATA1 :response[33:2]=busData1[1]; + default: begin + if(address>=`ABSTRACTDATASTART && address<=`ABSTRACTDATAEND) + begin + `ifdef verbose $display($time,"DEBUG: Autoexec Read Detected"); `endif + response[33:2]=zeroExtend(abstract_Data[address[3:0]-`ABSTRACTDATASTART][1]); + if(abstract_Command_Autoexe[address[3:0]-`ABSTRACTDATASTART] == 1) + begin + `ifdef verbose $display($time,"DEBUG: Autoexecuting command based on read in abstract data "); `endif + perform_reg_access[1] <=True; + end + end + else if(address>=`PBSTART && address<=`PBEND) + begin + `ifdef verbose $display($time,"DEBUG1: Autoexec Read Detected"); `endif + response[33:2]=zeroExtend(program_Buffer[address[3:0]][1]); + if(abstract_Command_Autoexe[address[5:0]-`PBSTART + 16] == 1) + begin + `ifdef verbose $display($time,"DEBUG: Autoexecuting command based on read in program buffer"); `endif + perform_reg_access[1] <=True; + end + end + else + response[1:0]=2; + end + endcase + end + `ifdef verbose $display($time,"\tDebug: Responding with data: %h op: %d",response[33:2],response[1:0]); `endif + response_to_DTM.enq(response); + endmethod + method ActionValue#(Bit#(34)) response_to_dtm; + response_to_DTM.deq; + return response_to_DTM.first; + endmethod + /*====================================================================================================== */ + + interface imem_master=c64.imem_master; + interface dmem_master=c64.dmem_master; + + interface debug_master=master_xactor.axi_side; + interface debug_slave =slave_xactor.axi_side; + method Action boot_sequence(Bit#(1) bootseq)=c64.boot_sequence(bootseq); + method Action set_external_interrupt(Tuple2#(Bool,Bool) i)=c64.set_external_interrupt(i); + `ifdef CLINT + method Action clint_msip(Bit#(1) intrpt)=c64.clint_msip(intrpt); + method Action clint_mtip(Bit#(1) intrpt)=c64.clint_mtip(intrpt); + method Action clint_mtime(Bit#(`Reg_width) c_mtime)=c64.clint_mtime(c_mtime); + `endif + endmodule +endpackage diff --git a/src/uncore/debug/RBB_Shakti.bsv b/src/uncore/debug/RBB_Shakti.bsv new file mode 100644 index 0000000..ee91fdc --- /dev/null +++ b/src/uncore/debug/RBB_Shakti.bsv @@ -0,0 +1,28 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +// RBB_Shakti.bsv +package RBB_Shakti; + +// ================================================================ +// import BDPI declarations for C functions used in BSV modeling of memory +// ================================================================ + +// frame = {NA,NA,NA,reset,request_tdo,tck,tms,tdi} +import "BDPI" function ActionValue #(Bit #(1)) init1(); // Callin this will make the simulator wait for openOCD +import "BDPI" function ActionValue #(Bit #(8))get_frame(); +import "BDPI" function Action send_tdo(Bit #(1) tdo); + +// =================import "BDPI" function Action=============================================== + +endpackage: RBB_Shakti diff --git a/src/uncore/debug/RBB_Shakti.c b/src/uncore/debug/RBB_Shakti.c new file mode 100644 index 0000000..94e3fc8 --- /dev/null +++ b/src/uncore/debug/RBB_Shakti.c @@ -0,0 +1,144 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "RBB_Shakti.h" + +int socket_fd; +int client_fd; +int port = 10000; +char frame = 0; // frame = {NA,NA,NA,reset,request_tdo,tck,tms,tdi} + +char accept_cxn() +{ + client_fd = accept(socket_fd, NULL, NULL); + if (client_fd == -1) { + if (errno == EAGAIN) { + return -1; + // No client waiting to connect right now. + } else { + fprintf(stderr, "failed to accept on socket: %s (%d)\n", strerror(errno), + errno); + } + } else { + fcntl(client_fd, F_SETFL, O_NONBLOCK); + return 1; + } + return -1; +} + + +char init1(){ + socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if (socket_fd == -1) { + fprintf(stderr, "remote_bitbang failed to make socket: %s (%d)\n", + strerror(errno), errno); + return -1; + } + + fcntl(socket_fd, F_SETFL, O_NONBLOCK); + int reuseaddr = 1; + if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, + sizeof(int)) == -1) { + fprintf(stderr, "remote_bitbang failed setsockopt: %s (%d)\n", + strerror(errno), errno); + return -1; + } + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(port); + + if (bind(socket_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) { + fprintf(stderr, "remote_bitbang failed to bind socket: %s (%d)\n", + strerror(errno), errno); + return -1; + } + + if (listen(socket_fd, 1) == -1) { + fprintf(stderr, "remote_bitbang failed to listen on socket: %s (%d)\n", + strerror(errno), errno); + return -1; + } + + socklen_t addrlen = sizeof(addr); + if (getsockname(socket_fd, (struct sockaddr *) &addr, &addrlen) == -1) { + fprintf(stderr, "remote_bitbang getsockname failed: %s (%d)\n", + strerror(errno), errno); + return -1; + } + + printf("Listening for remote bitbang connection on port %d.\n", + ntohs(addr.sin_port)); + fflush(stdout); + printf("Waiting for OpenOCD .... \n"); + while (accept_cxn() != 1); + return 0; +} + + +char decode_frame(char command){ +// frame = {NA,NA,NA,reset,request_tdo,tck,tms,tdi} + switch (command) { + case 'B': /* fprintf(stderr, "*BLINK*\n"); */ break; // not supported in spike + case 'b': /* fprintf(stderr, "_______\n"); */ break; // not supported in spike + case 'r': frame &= ~((char)24); frame |= 16 ; break; + case '0': frame = 0; break; + case '1': frame = 1; break; + case '2': frame = 2; break; + case '3': frame = 3; break; + case '4': frame = 4; break; + case '5': frame = 5; break; + case '6': frame = 6; break; + case '7': frame = 7; break; + case 'R': frame &= ~((char)24); frame |= 8 ; break; // push out a word with the previous state held with the read bit enabled maintain previous state and just push enable the read bit + case 'Q': break; // Not Supporting Q right now + default: + frame &= ~((char)24); //fprintf(stderr, "remote_bitbang got unsupported command '%d'\n", +// command); // essentially de assert the read bit if it was ever up; + } + return frame; +} + +// frame = {NA,NA,NA,reset,request_tdo,tck,tms,tdi} +char get_frame(){ + char packet; + read(client_fd,&packet, 1); + //printf("%d\n",decode_frame(packet)); + return decode_frame(packet); +} + +void send_tdo(bool tdo){ + char a = (tdo)? '1' :'0' ; + write(client_fd,&a,1); +}; + + +void main(){ // Test Bench of sorts + init1(); +/* while(1){ + char fr = get_frame(); + if((fr & 8) == 8)send_tdo(1); + if((fr & 16) == 16) printf("Reset Requested \n"); + } +*/ +} diff --git a/src/uncore/debug/RBB_Shakti.h b/src/uncore/debug/RBB_Shakti.h new file mode 100644 index 0000000..693074c --- /dev/null +++ b/src/uncore/debug/RBB_Shakti.h @@ -0,0 +1,23 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +// RBB_Shakti.h + +extern int socket_fd; +extern int client_fd; +extern int port; +extern char frame; // frame = {NA,NA,NA,reset,request_tdo,tck,tms,tdi} + +char init(); +char get_frame(); +void send_tdo(bool tdo); diff --git a/src/uncore/debug/defines.bsv b/src/uncore/debug/defines.bsv new file mode 100644 index 0000000..d1d3765 --- /dev/null +++ b/src/uncore/debug/defines.bsv @@ -0,0 +1,23 @@ +`define ABSTRACTDATASTART 'h04 +`define ABSTRACTDATAEND 'h0f +`define DMCONTROL 'h10 +`define DMSTATUS 'h11 +`define HARTINFO 'h12 +`define ABSTRACTCNTRL 'h16 +`define ABSTRACTCMD 'h17 +`define ABSTRACTCMDAUTO 'h18 +`define CONFIGSTRINGADDR0 'h19 +`define CONFIGSTRINGADDR1 'h1a +`define CONFIGSTRINGADDR2 'h1b +`define CONFIGSTRINGADDR3 'h1c +`define PBSTART 'h20 +`define PBEND 'h2f +`define AUTHENDATA 'h30 +`define SERIALCONTROL 'h34 +`define SERIALTX 'h35 +`define SERIALRX 'h36 +`define BUSCONTROL 'h38 +`define BUSADDRESS0 'h39 +`define BUSADDRESS1 'h3a +`define BUSDATA0 'h3c +`define BUSDATA1 'h3d diff --git a/src/uncore/tilelink/TLMemoryMap.bsv b/src/uncore/tilelink/TLMemoryMap.bsv new file mode 100644 index 0000000..7c5823d --- /dev/null +++ b/src/uncore/tilelink/TLMemoryMap.bsv @@ -0,0 +1,67 @@ +/* +Copyright (c) 2013, IIT Madras +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +*/ +package MemoryMap; + /*=== Project imports ==== */ + import defined_types::*; + `include "defined_parameters.bsv" + /*========================= */ + + +function Tuple2 #(Bool, Bit#(TLog#(Num_Slaves))) fn_addr_to_slave_num (Bit#(`PADDR) addr, Bit#(TLog#(Num_masters)) mj); + + if(addr>=`SDRAMMemBase && addr<=`SDRAMMemEnd) + return tuple2(pack(mj(route_to_SDRAM)),fromInteger(valueOf(Sdram_slave_num))); + else if(addr>=`DebugBase && addr<=`DebugEnd) + return tuple2(pack(mj(route_to_debug)),fromInteger(valueOf(Debug_slave_num))); + `ifdef SDRAM + else if(addr>=`SDRAMCfgBase && addr<=`SDRAMCfgEnd ) + return tuple2(True,fromInteger(valueOf(Sdram_cfg_slave_num))); + `endif + `ifdef BOOTROM + else if(addr>=`BootRomBase && addr<=`BootRomEnd) + return tuple2(pack(mj(route_to_BOOTROM)),fromInteger(valueOf(BootRom_slave_num))); + `endif + else if( (addr>=`UART0Base && addr<=`UART0End) || (addr>=`UART1Base && addr<=`UART1End) || (addr>=`ClintBase && addr<=`ClintEnd) || (addr>=`PLICBase && addr<=`PLICEnd) || (addr>=`GPIOBase && addr<=`GPIOEnd) || (addr>=`I2C1Base && addr<=`I2C1End)|| (addr>=`I2C0Base && addr<=`I2C0End) || (addr>=`QSPI1CfgBase && addr<=`QSPI1CfgEnd) || (addr>=`QSPI1MemBase && addr<=`QSPI1MemEnd)|| (addr>=`QSPI0CfgBase && addr<=`QSPI0CfgEnd) || (addr>=`QSPI0MemBase && addr<=`QSPI0MemEnd) || (addr>=`AxiExp1Base && addr<=`AxiExp1End) ) + return tuple2(pack(mj(route_to_slow_peripherals)),fromInteger(valueOf(SlowPeripheral_slave_num))); + `ifdef DMA + else if(addr>=`DMABase && addr<=`DMAEnd) + return tuple2(pack(mj(route_to_DMA)),fromInteger(valueOf(Dma_slave_num))); + `endif + `ifdef TCMemory + else if(addr>=`TCMBase && addr<=`TCMEnd) + return tuple2(pack(mj(route_to_TCM)),fromInteger(valueOf(TCM_slave_num))); + `endif + else + return tuple2(False,?); +endfunction + +function Bool is_IO_Addr(Bit#(`PADDR) addr); // TODO Shuold be PADDR + if(addr>=`DebugBase && addr<=`DebugEnd) + return (True); + else if(addr>=`SDRAMMemBase && addr<=`SDRAMMemEnd) + return (False); + `ifdef BOOTROM + else if(addr>=`BootRomBase && addr<=`BootRomEnd) + return (False); + `endif + `ifdef TCMemory + else if(addr>=`TCMBase && addr<=`TCMEnd) + return (False); + `endif + else + return True; +endfunction + + +endpackage diff --git a/src/uncore/tilelink/Tilelink.bsv b/src/uncore/tilelink/Tilelink.bsv new file mode 100644 index 0000000..830c2ef --- /dev/null +++ b/src/uncore/tilelink/Tilelink.bsv @@ -0,0 +1,70 @@ +package Tilelink; + +import Tilelink_Types.bsv ::*; +import defined_types.bsv ::*; + +// ================================================================ +// The interface for the fabric module + +interface Tilelink_Fabric_IFC #(numeric type num_masters, + numeric type num_slaves); + + method Action reset; + method Action set_verbosity (Bit #(4) verbosity); + + // From masters + interface Vector #(num_masters, Ifc_Master_tilelink) v_from_masters; + + // To slaves + interface Vector #(num_slaves, Ifc_Slave_link) v_to_slaves; +endinterface + +module mkTilelinkFabric(Tilelink_Fabric_IFC); + + // Transactors facing masters + Vector #(num_masters, AXI4_Slave_Xactor_IFC #(wd_addr, wd_data, wd_user)) + xactors_masters <- replicateM (mkMasterFabric); + + // Transactors facing slaves + Vector #(num_slaves, AXI4_Master_Xactor_IFC #(wd_addr, wd_data, wd_user)) + xactors_slaves <- replicateM (mkSizedFIFO); + + //These rules connect the masters and the slaves. If the sender is valid and the receiver is ready the + //the packet is exchanged. In addition the route must valid. + + //The slave destination is determined by address map function + for(Integer m = 0; m < Num_masters; m = m+1) begin + for(Integer s = 0; s < Num_masters; s = s+1) begin + rule rl_fabric_requests; + let req = xactors_masters[m].fabric_side_request.fabric_a_channel; + {valid, slave_id} = fn_addr_slave_num(req.a_address, fromInteger(m)); //address map function + if(xactors_masters[m].fabric_side_request.fabric_a_channel_valid && + xactors_slaves[s].fabric_side_request.fabric_a_channel_ready && + valid && slave_id==s) begin + xactors_masters[m].fabric_side_request.fabric_a_channel_ready(True); + xactors_slaves[s].fabric_side_request.fabric_a_channel(req); + end + else if() //TODO send the slave error + endrule + end + end + + //The master destination is determined by the signal in the D channel - d_source + for(Integer m = 0; m < Num_masters; m = m+1) begin + for(Integer s = 0; s < Num_masters; s = s+1) begin + rule rl_fabric_responses; + let resp = xactors_slaves[s].fabric_side_request.fabric_d_channel; + if(xactors_slaves[s].fabric_side_request.fabric_d_channel_valid && + xactors_masters[m].fabric_side_request.fabric_d_channel_ready && + resp.d_source==m) begin + xactors_slaves[s].fabric_side_request.fabric_a_channel_ready(True); + xactors_master[m].fabric_side_request.fabric_a_channel(resp); + end + else if() //TODO send the slave error + endrule + end + end + +endmodule + +endpackage diff --git a/src/uncore/tilelink/Tilelink_Types.bsv b/src/uncore/tilelink/Tilelink_Types.bsv new file mode 100644 index 0000000..b9fdf15 --- /dev/null +++ b/src/uncore/tilelink/Tilelink_Types.bsv @@ -0,0 +1,406 @@ + +`include "defined_parameters" + +`define LANE_WIDTH 8 +`define XLEN 8 + +typedef enum { Get + ,GetWrap + ,PutPartialdata + ,PutFulldata +`ifdef TILEUH + ,ArithmeticData + ,LogicalData + ,Intent +`endif +`ifdef TILEUC + ,Acquire +`endif +} Opcode deriving(Bits, Eq, FShow); + +typedef enum { Min, + Max, + MinU, + MaxU, + ADD +} Param_arith deriving(Bits, Eq, FShow); + +typedef enum { Min, + Max, + MinU, + MaxU, + ADD +} Param_logical deriving(Bits, Eq, FShow); + +typedef Bit#(3) Param +typedef Bit#(4) Data_size //In bytes +typedef Bit#(2) M_source +typedef Bit#(5) S_sink +typedef Bit#(`PADDR) Address_width +typedef Bit#(`LANE_WIDTH) Mask +typedef Bit#(TMul#(8,`LANE_WIDTH)) Data + +/* The A-channel is responsible for the master requests. The channel is A is split in control section(c) +data section(d) where the read masters only use control section and write masters use both. For the slave side +where it receives the request has the channel A intact. +*/ +typedef struct { + Opcode a_opcode; //The opcode specifies if write or read requests +`ifdef TILEUH + Param a_param; //Has the encodings for atomic transfers +`endif + Data_size a_size; //The transfer size in 2^a_size bytes. The burst is calculated from here. if this is >3 then its a burst + M_source a_source; //Master ID + Address_width a_address; //Address for the request +} A_channel_control deriving(Bits, Eq); + +typedef struct { + Mask a_mask; //8x(bytes in data lane) 1 bit mask for each byte + Data a_data; //data for the request +} A_channel_data deriving(Bits, Eq); + +typedef struct { + Opcode a_opcode; +`ifdef TILEUH + Param a_param; +`endif + Data_size a_size; + M_source a_source; + Address_width a_address; + Mask a_mask; + Data a_data; +} A_channel deriving(Bits, Eq); + +//cache-coherence channels +typedef struct { + Opcode b_opcode; + Param b_param; + Data_size b_size; + M_source b_source; + Address_width b_address; + Mask b_mask; + Data b_data; +} B_channel deriving(Bits, Eq); + +//cache-coherence channels +typedef struct { + Opcode c_opcode; + Param c_param; + Data_size c_size; + M_source c_source; + Address_width c_address; + Data c_data; + Bool c_client_error; +} C_channel deriving(Bits, Eq); + +//The channel D is responsible for the slave responses. It has the master ids and slave ids carried through the channel +typedef struct { + Opcode d_opcode; //Opcode encodings for response with data or just ack + Param d_param; + Data_size d_size; + M_source d_source; + S_sink d_sink; + Data d_data; + Bool d_client_error; +} D_channel deriving(Bits, Eq); + +typedef struct { + S_sink d_sink; +} E_channel deriving(Bits, Eq); + + +//--------------------------------------MASTER XACTOR--------------------------------------// +/* This is a xactor interface which connects core and master side of the fabric*/ +interface Ifc_Master_link; + +//Towards the master +interface Put#(A_channel_control) master_request_control; +interface Put#(A_channel_data) master_request_data; +interface Get#(D_channel) master_response; + +//Towards the fabric +interface Get#(A_channel_control) fabric_request_control; +interface Get#(A_channel_data) fabric_request_data; +interface Put#(D_channel) fabric_response; + +endinterface + +/* Master transactor - should be instantiated in the core side and the fabric side interface of +of the xactor should be exposed out of the core*/ +module mkMasterXactor#(Bool xactor_guarded, Bool fabric_guarded)(Ifc_Master_link); + +//Created a pipelined version that will have a critical path all along the bus. If we want to break the path we can +//make the bus stall-less +`ifdef TILELINK_LIGHT + FIFOF#(A_channel_control) ff_xactor_request_c <- mkGFIFOF(xactor_guarded, fabric_guarded, 2); //control split of A-channel + FIFOF#(A_channel_data) ff_xactor_request_d <- mkGFIFOF(xactor_guarded, fabric_guarded, 2); //data split of A-channel + FIFOF#(D_channel) ff_xactor_response <- mkGFIFOF(xactor_guarded, fabric_guarded, 2); //response channel D-channel exposed out +`elsif + FIFO#(A_channel_control) ff_xactor_request_c <- mkSizedFIFO(2); + FIFO#(A_channel_data) ff_xactor_request_d <- mkSizedFIFO(2); + FIFO#(D_channel) ff_xactor_response <- mkSizedFIFO(2); +`endif + + Reg#(Data_size) rg_burst_counter <- mkReg(0); + Reg#(Bool) rg_burst[2] <- mkCReg(2,False); + +// If it is a burst dont ask for address again. This rule about calculating the burst and telling the control split of A-channel to keep +//quite till the burst finishes. + rule rl_xactor_to_fabric_data; + let req_addr = ff_xactor_c_request.first; + Data_size burst_size = 1; //The total number of bursts + Data_size transfer_size = req_addr.a_size; //This is the total transfer size including the bursts + if(!rg_burst[0]) begin + if(transfer_size > 3) begin + rg_burst[0] <= True; + transfer_size = transfer_size - 3; + rg_burst_counter <= burst_size << transfer_size; + end + end + else begin + rg_burst_counter <= rg_burst_counter - 1; + if(rg_burst_counter==1) + rg_burst[0] <= False; + end + + endrule + + interface master_request_control = Get#(ff_xactor_c_request); + interface master_request_data = Get#(ff_xactor_d_request); + interface master_request_control = interface Get + method ActionValue#(A_channel_control) get; //Deque the control split of a channel if only burst is finished + let req_addr = ff_xactor_c_request.first; + if(!rg_burst[1]) + ff_xactor_c_request.deq; + return req_addr; + endmethod + endinterface + interface fabric_request_data = Get#(ff_xactor_d_request); + interface fabric_response = Put#(ff_xactor_d_response); + +endmodule + +//------------------------------------------------------------------------------------------------------------------// + + +//------------------------------------------------------Slave Xactor------------------------------------------------// + +interface Ifc_Slave_link; + +interface Put#(A_channel) xactor_request; +interface Get#(D_channel) xactor_response; + +interface Get#(A_channel) xactor_request; +interface Put#(D_channel) xactor_response; + +endinterface + +module mkSlave_xactor(Ifc_Slave_link); + +`ifdef TILELINK_LIGHT + FIFOF#(A_channel) ff_xactor_request <- mkGFIFOF(xactor_guarded, fabric_guarded, 2); + FIFOF#(D_channel) ff_xactor_response <- mkGFIFOF(xactor_guarded, fabric_guarded, 2); +`elsif + FIFO#(A_channel) ff_xactor_request <- mkSizedFIFO(2); + FIFO#(D_channel) ff_xactor_response <- mkSizedFIFO(2); +`endif + + //rule rl_xactor_to_fabric(!isValid(rg_d_channel)); + // let lv_response = ff_xactor_response.first; + // rg_d_channel <= tagged Valid lv_response; + // ff_xactor_response.deq; + //endrule + + //rule rl_fabric_to_xactor(rg_a_channel matches tagged Valid .req); + // let lv_req = req; + // ff_xactor_request.enq(req); + // rg_a_channel <= tagged Invalid + //endrule + +interface master_request = Put#(ff_xactor_request); +interface master_response = Get#(ff_xactor_response); + +interface fabric_request = Get#(ff_xactor_request); +interface fabric_response = Put#(ff_xactor_response); + +endmodule + +//----------------------------------------------- Master Fabric -------------------------------------// + +interface Ifc_Master_fabric_side_a_channel; + (* always_ready *) + method A_channel fabric_a_channel; + (* always_ready *) + method Bool fabric_a_channel_valid; + (* always_ready, always_enabled *); + method Action fabric_a_channel_ready; +endinterface + +interface Ifc_Master_fabric_side_d_channel; + (* always_ready, always_enabled *); + method Action fabric_d_channel; + (* always_ready *) + method Bool fabric_d_channel_ready; +endinterface + +interface Ifc_Master_tilelink; + + //Communication with the xactor + interface Put#(A_channel_control) xactor_request_control; + interface Put#(A_channel_data) xactor_request_data; + interface Get#(D_channel) xactor_response; + + //communication with the fabric + interface Ifc_Master_fabric_side_d_channel fabric_side_response; + interface Ifc_Master_fabric_side_a_channel fabric_side_request; +endinterface + +module mkMasterFabric(Ifc_Master_Fabric); + + Reg#(A_channel_control) rg_a_channel[3] <- mkCReg(3, A_channel { a_opcode : ?, + a_param : ?, + a_size : ?, + a_source : ?, + a_address : ? }); + Reg#(Maybe#(A_channel_data)) rg_a_channel_d[3] <- mkCReg(3, tagged Invalid); + Reg#(Maybe#(D_channel)) rg_d_channel[3] <- mkCReg(3, tagged Invalid); + + + interface xactor_request_control = interface Put + method Action put(A_channel_control req_control); + rg_a_channel_c <= req_control; + endmethod + endinterface + + interface xactor_request_data = interface Put + method Action put(A_channel_data req_data); + rg_a_channel_d <= req_data; + endmethod + endinterface + + interface xactor_response = interface Get; + method ActionValue#(D_channel) get if(isValid(rg_d_channel)); + let resp = validValue(rg_d_channel); + rg_d_channel <= tagged Invalid; + return resp; + endmethod + + + interface fabric_side_response = interface Ifc_Master_fabric_side_d_channel + (* always_ready, always_enabled *); + method Action fabric_d_channel(D_channel resp); + rg_d_channel <= tagged Valid resp; + endmethod + (* always_ready *) + method Bool fabric_d_channel_ready; + return !isValid(rg_d_channel); + endmethod + endinterface; + //while sending it to the fabric the control section and the data section should be merged + interface fabric_side_request = interface Ifc_Master_fabric_side_a_channel + (* always_ready *) + method A_channel fabric_a_channel; + A_channel req = A_channel {a_opcode : rg_a_channel_c.a_opcode, + a_param : rg_a_channel_c.a_param, + a_size : rg_a_channel_c.a_size, + a_source : rg_a_channel_c.a_source, + a_address : rg_a_channel_c.a_address, + a_mask : rg_c_channel_c.a_mask, + a_data : rg_c_channel_c.a_data}; + return validValue(req); + endmethod + (* always_ready *) + method Bool fabric_a_channel_valid; //master valid signal to the fabric + return isValid(rg_a_channel_d); + endmethod + (* always_ready, always_enabled *); + method Action fabric_a_channel_ready(Bool req_ready); //master ready signal to the fabric + if(req_ready) + rg_a_channel <= tagged Invalid; + endmethod + endinterface +endmodule + + +//----------------------------------------------- Slave Fabric -------------------------------------// + +interface Ifc_Master_fabric_side_a_channel; + (* always_ready, always_enabled *); + method Action fabric_a_channel(A_channel req); + (* always_ready *) + method Bool fabric_a_channel_ready; +endinterface + +interface Ifc_Master_fabric_side_d_channel; + (* always_ready *) + method D_channel fabric_d_channel; + (* always_ready *) + method Bool fabric_d_channel_valid; + (* always_ready, always_enabled *); + method Action fabric_a_channel_ready; +endinterface + +interface Ifc_Slave_tilelink; + + //communication with the xactors + interface Get#(A_channel) xactor_request; + interface Put#(D_channel) xactor_response; + + //communication with the fabric + interface Ifc_slave fabric_side_response; + interface Ifc_Slave_fabric_side_a_channel fabric_side_request; + +endinterface + +module mkSlaveFabric(Ifc_Slave_Fabric); + + Reg#(Maybe#(A_channel)) rg_a_channel_d[3] <- mkCReg(3, tagged Invalid); + Reg#(Maybe#(D_channel)) rg_d_channel[3] <- mkCReg(3, tagged Invalid); + + + interface xactor_request_control = interface Get + method ActionValue#(A_channel) get if(isValid(rg_a_channel); + let req = validValue(rg_a_channel); + rg_a_channel <= tagged Invalid; + return req; + endmethod + endinterface + + interface xactor_response = interface Put; + method Action put(D_channel resp) if(!isValid(rg_d_channel)); + rg_d_channel <= tagged resp; + endmethod + + + interface fabric_side_response = interface Ifc_Slave_fabric_side_d_channel + (* always_ready *) + method D_channel fabric_d_channel(D_channel resp); + return validValue(rg_d_channel); + endmethod + (* always_ready *) + method Bool fabric_d_channel_valid; + return isValid(rg_d_channel); + endmethod + (* always_ready, always_enabled *); + //if the beat has been exchanged the packet can be invalidated on the sending side + method Action fabric_d_channel_ready(Bool req_ready); + if(req_ready) + rg_d_channel <= tagged Invalid; + endmethod + endinterface; + + interface fabric_side_request = interface Ifc_Master_fabric_side_a_channel + //if the beat has been exchanged the packet can be invalidated on the sending side + (* always_ready, always_enabled *); + method Action fabric_a_channel(A_channel req); + rg_a_channel <= req; + endmethod + (* always_ready *) + method Bool fabric_a_channel_ready; + return !isValid(rg_a_channel_d); + endmethod + endinterface +endmodule + + + -- 2.30.2