Repository: CMU-SAFARI/SoftMC Branch: master Commit: 50b09a68f4ab Files: 163 Total size: 1.6 MB Directory structure: gitextract_u_mc_d1s/ ├── LICENSE ├── README.md ├── hw/ │ └── boards/ │ └── ML605/ │ ├── SoftMC.xise │ ├── apply_patches.sh │ ├── autoref_config.v │ ├── instr_decoder.v │ ├── instr_dispatcher.v │ ├── instr_receiver.v │ ├── ipcore_dir/ │ │ ├── instr_fifo.xco │ │ ├── instr_fifo.xise │ │ ├── pcie_endpoint.xco │ │ ├── pcie_endpoint.xise │ │ ├── rdback_fifo.xco │ │ ├── rdback_fifo.xise │ │ ├── riffa/ │ │ │ ├── async_fifo.v │ │ │ ├── async_fifo_fwft.v │ │ │ ├── axi_basic_rx.v │ │ │ ├── axi_basic_rx_null_gen.v │ │ │ ├── axi_basic_rx_pipeline.v │ │ │ ├── axi_basic_top.v │ │ │ ├── axi_basic_tx.v │ │ │ ├── axi_basic_tx_pipeline.v │ │ │ ├── axi_basic_tx_thrtl_ctl.v │ │ │ ├── channel_128.v │ │ │ ├── channel_32.v │ │ │ ├── channel_64.v │ │ │ ├── chnl_tester.v │ │ │ ├── common_functions.v │ │ │ ├── cross_domain_signal.v │ │ │ ├── demux_1_to_n.v │ │ │ ├── ff.v │ │ │ ├── fifo_packer_128.v │ │ │ ├── fifo_packer_32.v │ │ │ ├── fifo_packer_64.v │ │ │ ├── gtx_drp_chanalign_fix_3752_v6.v │ │ │ ├── gtx_rx_valid_filter_v6.v │ │ │ ├── gtx_tx_sync_rate_v6.v │ │ │ ├── gtx_wrapper_v6.v │ │ │ ├── interrupt.v │ │ │ ├── interrupt_controller.v │ │ │ ├── pcie_2_0_v6.v │ │ │ ├── pcie_bram_top_v6.v │ │ │ ├── pcie_bram_v6.v │ │ │ ├── pcie_brams_v6.v │ │ │ ├── pcie_clocking_v6.v │ │ │ ├── pcie_endpoint.v │ │ │ ├── pcie_gtx_v6.v │ │ │ ├── pcie_pipe_lane_v6.v │ │ │ ├── pcie_pipe_misc_v6.v │ │ │ ├── pcie_pipe_v6.v │ │ │ ├── pcie_reset_delay_v6.v │ │ │ ├── pcie_upconfig_fix_3451_v6.v │ │ │ ├── ram_1clk_1w_1r.v │ │ │ ├── ram_2clk_1w_1r.v │ │ │ ├── recv_credit_flow_ctrl.v │ │ │ ├── reorder_queue.v │ │ │ ├── reorder_queue_input.v │ │ │ ├── reorder_queue_output.v │ │ │ ├── riffa_adapter_v6_pcie_v2_5.v │ │ │ ├── riffa_endpoint.v │ │ │ ├── riffa_endpoint_128.v │ │ │ ├── riffa_endpoint_32.v │ │ │ ├── riffa_endpoint_64.v │ │ │ ├── riffa_top_v6_pcie_v2_5.v │ │ │ ├── rx_engine_128.v │ │ │ ├── rx_engine_32.v │ │ │ ├── rx_engine_64.v │ │ │ ├── rx_engine_req.v │ │ │ ├── rx_port_128.v │ │ │ ├── rx_port_32.v │ │ │ ├── rx_port_64.v │ │ │ ├── rx_port_channel_gate.v │ │ │ ├── rx_port_reader.v │ │ │ ├── rx_port_requester_mux.v │ │ │ ├── sg_list_reader_128.v │ │ │ ├── sg_list_reader_32.v │ │ │ ├── sg_list_reader_64.v │ │ │ ├── sg_list_requester.v │ │ │ ├── sync_fifo.v │ │ │ ├── syncff.v │ │ │ ├── translation_layer.v │ │ │ ├── translation_layer_128.v │ │ │ ├── translation_layer_32.v │ │ │ ├── translation_layer_64.v │ │ │ ├── tx_engine_128.v │ │ │ ├── tx_engine_32.v │ │ │ ├── tx_engine_64.v │ │ │ ├── tx_engine_formatter_128.v │ │ │ ├── tx_engine_formatter_32.v │ │ │ ├── tx_engine_formatter_64.v │ │ │ ├── tx_engine_lower_128.v │ │ │ ├── tx_engine_lower_32.v │ │ │ ├── tx_engine_lower_64.v │ │ │ ├── tx_engine_selector.v │ │ │ ├── tx_engine_upper_128.v │ │ │ ├── tx_engine_upper_32.v │ │ │ ├── tx_engine_upper_64.v │ │ │ ├── tx_port_128.v │ │ │ ├── tx_port_32.v │ │ │ ├── tx_port_64.v │ │ │ ├── tx_port_buffer_128.v │ │ │ ├── tx_port_buffer_32.v │ │ │ ├── tx_port_buffer_64.v │ │ │ ├── tx_port_channel_gate_128.v │ │ │ ├── tx_port_channel_gate_32.v │ │ │ ├── tx_port_channel_gate_64.v │ │ │ ├── tx_port_monitor_128.v │ │ │ ├── tx_port_monitor_32.v │ │ │ ├── tx_port_monitor_64.v │ │ │ ├── tx_port_writer.v │ │ │ ├── tx_qword_aligner_128.v │ │ │ └── tx_qword_aligner_64.v │ │ ├── xilinx_mig/ │ │ │ ├── example_design/ │ │ │ │ └── mig.prj │ │ │ └── user_design/ │ │ │ └── mig.prj │ │ ├── xilinx_mig.xco │ │ └── xilinx_mig.xise │ ├── iseq_dispatcher.v │ ├── maint_ctrl.v │ ├── maint_handler.v │ ├── patches/ │ │ ├── iodelay_ctrl.patch │ │ ├── phy_rdctrl_sync.patch │ │ ├── phy_read.patch │ │ └── phy_top.patch │ ├── pipe_reg.v │ ├── read_capturer.v │ ├── softMC.inc │ ├── softMC.v │ ├── softMC_constraints.ucf │ ├── softMC_pcie_app.v │ ├── softMC_top.v │ └── tb_softMC_top.v ├── prebuilt/ │ ├── SoftMC.bit │ └── SoftMC_RetentionTest └── sw/ ├── RetentionTest/ │ ├── Makefile │ └── RetentionTest.cpp ├── SoftMC_API/ │ ├── softmc.cpp │ └── softmc.h └── riffa_2.1/ ├── LICENSE ├── README.txt └── driver/ ├── linux/ │ ├── Makefile │ ├── README.txt │ ├── circ_queue.c │ ├── circ_queue.h │ ├── riffa.c │ ├── riffa.h │ ├── riffa_driver.c │ └── riffa_driver.h └── windows/ ├── README.txt ├── dirs ├── install/ │ ├── install.bat │ ├── license.txt │ └── win7.iss ├── sys/ │ ├── makefile │ ├── makefile.inc │ ├── precomp.h │ ├── riffa.c │ ├── riffa.inx │ ├── riffa.rc │ ├── riffa_driver.h │ ├── riffa_private.h │ ├── sources │ └── trace.h └── win7install.bat ================================================ FILE CONTENTS ================================================ ================================================ FILE: LICENSE ================================================ Copyright (c) [2017] [SAFARI Research Group at Carnegie Mellon University and ETH Zurich] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ ## [DRAM Bender](https://github.com/CMU-SAFARI/DRAM-Bender) (a.k.a. SoftMC v2) supersedes SoftMC. We suggest that you use DRAM Bender instead of SoftMC. # SoftMC v1.0 SoftMC is an experimental FPGA-based memory controller design that could be used to develop tests for DDR3 SODIMMs. SoftMC currently supports only the *Xilinx ML605* board. Soon, we will port SoftMC on other popularly used boards (e.g., *Xilinx VC709*). A paper describing SoftMC in detail is published at HPCA 2017 and is available here: >*Hasan Hassan, Nandita Vijaykumar, Samira Khan, Saugata Ghose, Kevin Chang, Gennady Pekhimenko, Donghyuk Lee, Oguz Ergin, and Onur Mutlu,* **"[SoftMC: A Flexible and Practical Open-Source Infrastructure for Enabling Experimental DRAM Studies](https://people.inf.ethz.ch/omutlu/projects.htm)"** *Proceedings of the 23rd International Symposium on High-Performance Computer Architecture (HPCA), Austin, TX, USA, February 2017.* If you use or build on SoftMC, please cite that paper. We provide a) prebuilt binaries for quick installation and b) the source code (both in Verilog and C++) that you could modify as you wish. ## Prerequisites: - A Xilinx ML605 FPGA or other compatible board (We only tested ML605) - A Linux Host Machine, (We have tested on Ubuntu 12.04/14.04) - SoftMC uses an 8-lane PCIe interface to communicate with the Host Machine. So, you would also need to attach the board to the 8x/16x PCIe slot on the motherboard of the Host Machine - Single Rank DDR3 SODIMM attached to your FPGA board - Xilinx ISE 14.6 (in case you want to build your own bitfile from the source) ## Installation Guide: ### 1) Installing the RIFFA driver: You need to have [RIFFA](http://riffa.ucsd.edu) driver installed on your system to enable the communication with the FPGA via the PCIe bus. Do not forget to attach your FPGA board to a PCIe slot. First switch to the directory of the source files of the RIFFA driver: ```$ cd sw/riffa_2.1/driver/linux``` Then run make to build the driver ```$ make``` Then install the driver to your system ```$ sudo make install``` ### 2) Creating and Downloading the SoftMC bitfile to the FPGA: **a) Quick Installation using Prebuilt Binaries** You will find all that you need inside "prebuilt" folder (including an executable for the Retention Time test). - You need to download the bitfile into your FPGA using an appropriate tool (Xilinx *Impact* does the job for ML605) - After restarting the machine that the FPGA is connected to via PCIe, you should be able to run the Retention Time test application by typing to command below: ```$ ./SoftMC_RetentionTime [Target Retention Time in milliseconds]``` **b) Installation from the Source Code** Generating the SoftMC bitfile is straightforward: - Use Xilinx ISE 14.6 to open the project, which is located located at *hw/boards/ML605/SoftMC.xise*. Ignore *missing files* pop-up windows by clicking the "Cancel" button. The missing files will be generated once the steps below are followed. - Double-click on *xilinx_mig* IPCore file to open Memory Interface Generator's (MIG) configuration window. Keep clicking the "Next" button until the windows closes. Doing this will generate the necessary files required by SoftMC in ```hw/boards/ML605/ipcore_dir/xilinx_mig```. - Open a terminal and go to hw/boards/ML605. Run: ```$ sh apply_patches.sh``` This will apply modifications to the files generated by MIG. - Go back to Xilinx ISE and click "Generate Programming File" and then click "Yes" on the dialogs that ask for IPCore to be compiled - If you get the following error during synthesis: `hw/boards/ML605/ipcore_dir/pcie_endpoint/source/gtx_wrapper_v6.v" Line 277: Instantiating from unknown module ` 1. Add `` `include "gtx_drp_chanalign_fix_3752_v6.v" `` before the module declaration in `` "gtx_wrapper_v6.v" ``. Save the file. 2. Comment-out the line that you have just added. Save the file again. 3. Click Synthesize again The error occurs due to a bug in Xilinx ISE software. A workaround for it is doing the steps that we listed above. - After the operation completes successfully, you will find the generated bitfile in the project folder - Then follow the steps in **a)** *(Where necessary to simulate the SoftMC hardware, we provide a sample testbench module ("tb_softMC_top.v") that you can start with. To enable simulation, you will need to uncomment the SIM definition in "softMC.inc". This will change the I/O interface of the top module to exclude the PCIe signals and let you easily issue instructions to SoftMC)* To compile the sample application (retention time test) that we provide: ``` $ cd sw/RetentionTest $ make $ ./SoftMC_RetentionTest [Target Retention Time in milliseconds] ``` ## Known Issues: - Multi Rank SODIMMs are currently not supported. - An instruction sequence could consist maximum of 8192 instructions (see our HPCA 2017 paper for details). - Motherboards with B75 Chipset seems to be incompatible with ML605's PCIe endpoint. You are welcome to contribute to the project. If you find/solve any issues or port SoftMC to a new FPGA board, please contact the people below. ## Contacts: Hasan Hassan (hhasan [at] inf [dot] ethz [dot] ch) ================================================ FILE: hw/boards/ML605/SoftMC.xise ================================================
================================================ FILE: hw/boards/ML605/apply_patches.sh ================================================ for f in ./patches/*.patch do patch -p0 < $f done ================================================ FILE: hw/boards/ML605/autoref_config.v ================================================ `timescale 1ns / 1ps //Hasan module autoref_config( input clk, input rst, input set_interval, input[27:0] interval_in, input set_trfc, input[27:0] trfc_in, output reg aref_en, output reg[27:0] aref_interval, output reg[27:0] trfc ); always@(posedge clk) begin if(rst) begin aref_en <= 0; aref_interval <= 0; trfc <= 0; end else begin if(set_interval) begin aref_en <= |interval_in; aref_interval <= interval_in; end //set_interval if(set_trfc) begin trfc <= trfc_in; end end end endmodule ================================================ FILE: hw/boards/ML605/instr_decoder.v ================================================ `timescale 1ns / 1ps `include "softMC.inc" module instr_decoder #(parameter ROW_WIDTH = 15, BANK_WIDTH = 3, CS_WIDTH = 1)( input en, input[31:0] instr, output reg[ROW_WIDTH - 1:0] dfi_address, output reg[BANK_WIDTH - 1:0] dfi_bank, output reg dfi_cas_n, output reg[CS_WIDTH - 1:0] dfi_cs_n, output reg dfi_ras_n, output reg dfi_we_n ); localparam LOW = 1'b0; localparam HIGH = 1'b1; always@* begin dfi_address = {ROW_WIDTH{1'bx}}; dfi_bank = {BANK_WIDTH{1'bx}}; dfi_cas_n = HIGH; dfi_cs_n = {CS_WIDTH{HIGH}}; dfi_ras_n = HIGH; dfi_we_n = HIGH; if(en) begin dfi_address = instr[ROW_WIDTH - 1:0]; dfi_bank = instr[`ROW_OFFSET +: BANK_WIDTH]; dfi_we_n = instr[`WE_OFFSET]; dfi_cas_n = instr[`CAS_OFFSET]; dfi_ras_n = instr[`RAS_OFFSET]; dfi_cs_n = instr[`CS_OFFSET +: CS_WIDTH]; end //en end endmodule ================================================ FILE: hw/boards/ML605/instr_dispatcher.v ================================================ `timescale 1ns / 1ps `include "softMC.inc" module instr_dispatcher #(parameter ROW_WIDTH = 15, BANK_WIDTH = 3, CKE_WIDTH = 1, RANK_WIDTH = 1, CS_WIDTH = 1, nCS_PER_RANK = 1, DQ_WIDTH = 64) ( input clk, input rst, input periodic_read_lock, //There are two instructions queues to fetch from. Since PHY issues DDR commands at both pos and neg edges, //we dispatch two instructions in the same cycle, running at half of the frequency of the DDR bus input en_in0, output en_ack0, input[31:0] instr_in0, input en_in1, output en_ack1, input[31:0] instr_in1, //DFI Interface // DFI Control/Address input dfi_ready, output[ROW_WIDTH-1:0] dfi_address0, output[ROW_WIDTH-1:0] dfi_address1, output[BANK_WIDTH-1:0] dfi_bank0, output[BANK_WIDTH-1:0] dfi_bank1, output dfi_cke0, output dfi_cke1, output dfi_cas_n0, output dfi_cas_n1, output[CS_WIDTH*nCS_PER_RANK-1:0] dfi_cs_n0, output[CS_WIDTH*nCS_PER_RANK-1:0] dfi_cs_n1, output[CS_WIDTH*nCS_PER_RANK-1:0] dfi_odt0, output[CS_WIDTH*nCS_PER_RANK-1:0] dfi_odt1, output dfi_ras_n0, output dfi_ras_n1, output dfi_we_n0, output dfi_we_n1, // DFI Write output reg dfi_wrdata_en, output [4*DQ_WIDTH-1:0] dfi_wrdata, output [4*(DQ_WIDTH/8)-1:0] dfi_wrdata_mask, // DFI Read output reg dfi_rddata_en, output reg dfi_rddata_en_even, output reg dfi_rddata_en_odd, //Bus Command output reg io_config_strobe, output reg[1:0] io_config, //Misc. output pr_rd_ack, //auto-refresh output reg aref_set_interval, output reg[27:0] aref_interval, output reg aref_set_trfc, output reg[27:0] aref_trfc ); localparam ONE = 1; localparam TWO = 2; localparam HIGH = 1'b1; localparam LOW = 1'b0; reg[9:0] wait_cycles_r = ONE[0 +: 10], wait_cycles_ns; reg read_burst_r, read_burst_ns; reg read_burst_even_r, read_burst_even_ns; reg read_burst_odd_r, read_burst_odd_ns; reg write_burst_r, write_burst_ns; reg[7:0] write_burst_data_r, write_burst_data_ns; reg bus_write, bus_write_r; reg pr_rd_ack_r, pr_rd_ack_ns; reg ack0, ack1; reg instr_src_r, instr_src_ns; reg dec0_en; wire[31:0] dec0_instr; reg dec1_en; wire[31:0] dec1_instr; wire en0 = instr_src_r ? en_in1 : en_in0; wire[31:0] instr0 = instr_src_r ? instr_in1 : instr_in0; assign en_ack0 = instr_src_r ? ack1 : ack0; wire en1 = instr_src_r ? en_in0 : en_in1; wire[31:0] instr1 = instr_src_r ? instr_in0 : instr_in1; assign en_ack1 = instr_src_r ? ack0 : ack1; assign dec0_instr = instr0; assign dec1_instr = instr1; reg block_other_slot; reg cke0, cke0_r, cke1, cke1_r; //auto-refresh reg aref_set_interval_ns, aref_set_trfc_ns; reg[27:0] aref_interval_ns, aref_trfc_ns; //Counter saturating at zero reg load_counter; always@(posedge clk) begin if(rst) wait_cycles_r <= 10'd0; else begin if(load_counter) begin wait_cycles_r <= wait_cycles_ns; end //load_counter else begin if(|wait_cycles_r[9:1]) wait_cycles_r <= wait_cycles_r - TWO[0 +: 10]; else wait_cycles_r <= 10'd0; end end end always@* begin io_config_strobe = LOW; io_config = 2'b00; bus_write = bus_write_r; instr_src_ns = ~(en_in0 | en_in1) ? LOW : instr_src_r; ack0 = HIGH; ack1 = HIGH; dec0_en = LOW; dec1_en = LOW; read_burst_ns = LOW; read_burst_even_ns = LOW; read_burst_odd_ns = LOW; write_burst_ns = LOW; write_burst_data_ns = write_burst_data_r; dfi_rddata_en = read_burst_r; dfi_rddata_en_even = read_burst_even_r; dfi_rddata_en_odd = read_burst_odd_r; dfi_wrdata_en = write_burst_r; pr_rd_ack_ns = LOW; aref_set_interval_ns = 1'b0; aref_interval_ns = {28{1'bx}}; aref_set_trfc_ns = 1'b0; aref_trfc_ns = {28{1'bx}}; wait_cycles_ns = 10'dx; load_counter = LOW; block_other_slot = LOW; cke0 = cke0_r; cke1 = cke1_r; if(dfi_ready & (wait_cycles_r <= 10'd1)) begin if(en0) begin casex(instr0[31:28]) `SET_BUSDIR: begin io_config_strobe = HIGH; io_config = instr0[1:0]; if(instr0[1:0] == `BUS_DIR_WRITE) bus_write = 1'b1; else bus_write = 1'b0; end //SET_BUSDIR `DDR_INSTR: begin dec0_en = HIGH; cke0 = instr0[`CKE_OFFSET]; if(~|instr0[`CS_OFFSET +: CS_WIDTH] && instr0[`RAS_OFFSET] && ~instr0[`CAS_OFFSET] && instr0[`WE_OFFSET] && cke0 && cke0_r) begin //check whether we have a read instruction dfi_rddata_en = HIGH; dfi_rddata_en_even = HIGH; read_burst_ns = HIGH; read_burst_even_ns = HIGH; dfi_rddata_en_odd = periodic_read_lock; //to indicate periodic read response read_burst_odd_ns = periodic_read_lock; pr_rd_ack_ns = HIGH; end if(~|instr0[`CS_OFFSET +: CS_WIDTH] && instr0[`RAS_OFFSET] && ~instr0[`CAS_OFFSET] && ~instr0[`WE_OFFSET] && cke0 && cke0_r) begin //check whether we have a write instruction dfi_wrdata_en = HIGH; write_burst_ns = HIGH; write_burst_data_ns = {instr0[30:25], instr0[(`ROW_OFFSET - 1) -:2]}; end end //DDR_INSTR `WAIT: begin load_counter = HIGH; wait_cycles_ns = instr0[9:0] - 10'd1; //reducing by one for the second slot if(instr0[9:0] > 10'd1) block_other_slot = HIGH; if(~instr0[0]) instr_src_ns = ~instr_src_r; end //WAIT `SET_TREFI: begin aref_set_interval_ns = 1'b1; aref_interval_ns = instr0[27:0]; end //SET_TREFI `SET_TRFC: begin aref_set_trfc_ns = 1'b1; aref_trfc_ns = instr0[27:0]; end //SET_TRFC endcase //instr0 end //en0 end else begin ack0 = LOW; end if(~(en0 & block_other_slot) & dfi_ready & (wait_cycles_r <= 10'd2)) begin if(en1) begin casex(instr1[31:28]) `SET_BUSDIR: begin io_config_strobe = HIGH; io_config = instr1[1:0]; if(instr1[1:0] == `BUS_DIR_WRITE) bus_write = 1'b1; else bus_write = 1'b0; end //SET_BUSDIR `DDR_INSTR: begin dec1_en = HIGH; cke1 = instr1[`CKE_OFFSET]; if(~|instr1[`CS_OFFSET +: CS_WIDTH] && instr1[`RAS_OFFSET] && ~instr1[`CAS_OFFSET] && instr1[`WE_OFFSET] && cke1 && cke1_r) begin //check whether we have a read command dfi_rddata_en = HIGH; read_burst_ns = HIGH; dfi_rddata_en_odd = periodic_read_lock; //to indicate periodic read response read_burst_odd_ns = periodic_read_lock; pr_rd_ack_ns = HIGH; end if(~|instr1[`CS_OFFSET +: CS_WIDTH] && instr1[`RAS_OFFSET] && ~instr1[`CAS_OFFSET] && ~instr1[`WE_OFFSET] && cke1 && cke1_r) begin //check whether we have a write command dfi_wrdata_en = HIGH; write_burst_ns = HIGH; write_burst_data_ns = {instr1[30:25], instr1[(`ROW_OFFSET - 1) -:2]}; end end //DDR_INSTR `WAIT: begin wait_cycles_ns = instr1[9:0]; load_counter = HIGH; if(~instr1[0]) instr_src_ns = ~instr_src_r; end //WAIT `SET_TREFI: begin aref_set_interval_ns = 1'b1; aref_interval_ns = instr1[27:0]; end //SET_TREFI `SET_TRFC: begin aref_set_trfc_ns = 1'b1; aref_trfc_ns = instr1[27:0]; end //SET_TRFC endcase //instr1 end //en1 end else begin ack1 = LOW; end end instr_decoder #(.ROW_WIDTH(ROW_WIDTH), .BANK_WIDTH(BANK_WIDTH), .CS_WIDTH(CS_WIDTH)) instr_dec0( .en(dec0_en), .instr(dec0_instr), .dfi_address(dfi_address0), .dfi_bank(dfi_bank0), .dfi_cas_n(dfi_cas_n0), .dfi_cs_n(dfi_cs_n0), .dfi_ras_n(dfi_ras_n0), .dfi_we_n(dfi_we_n0) ); instr_decoder #(.ROW_WIDTH(ROW_WIDTH), .BANK_WIDTH(BANK_WIDTH), .CS_WIDTH(CS_WIDTH)) i_instr_dec1( .en(dec1_en), .instr(dec1_instr), .dfi_address(dfi_address1), .dfi_bank(dfi_bank1), .dfi_cas_n(dfi_cas_n1), .dfi_cs_n(dfi_cs_n1), .dfi_ras_n(dfi_ras_n1), .dfi_we_n(dfi_we_n1) ); assign dfi_wrdata_mask = 0; assign dfi_wrdata = dfi_cas_n0 ? {4*(DQ_WIDTH/8){write_burst_data_r}} : {4*(DQ_WIDTH/8){write_burst_data_ns}}; always@(posedge clk) begin pr_rd_ack_r <= pr_rd_ack_ns; end assign pr_rd_ack = pr_rd_ack_r; always@(posedge clk) begin if(rst) begin aref_set_interval <= 0; aref_set_trfc <= 0; aref_interval <= 0; aref_trfc <= 0; cke0_r <= 1'b1; //not sure what would happen if the clock is disabled on reset cke1_r <= 1'b1; end else begin aref_set_interval <= aref_set_interval_ns; aref_set_trfc <= aref_set_trfc_ns; aref_interval <= aref_interval_ns; aref_trfc <= aref_trfc_ns; cke0_r <= cke0; cke1_r <= cke1; end end always@(posedge clk) begin if(rst) begin read_burst_r <= LOW; read_burst_even_r <= LOW; read_burst_odd_r <= LOW; write_burst_r <= LOW; write_burst_data_r <= 0; bus_write_r <= LOW; instr_src_r <= LOW; end else begin read_burst_r <= read_burst_ns; read_burst_even_r <= read_burst_even_ns; read_burst_odd_r <= read_burst_odd_ns; write_burst_r <= write_burst_ns; write_burst_data_r <= write_burst_data_ns; bus_write_r <= bus_write; instr_src_r <= instr_src_ns; end //!rst end assign dfi_odt0 = bus_write_r; assign dfi_odt1 = bus_write_r; assign dfi_cke0 = cke0_r; assign dfi_cke1 = cke1_r; endmodule ================================================ FILE: hw/boards/ML605/instr_receiver.v ================================================ `timescale 1ns / 1ps `include "softMC.inc" module instr_receiver ( input clk, input rst, input dispatcher_ready, input app_en, output reg app_ack, input[31:0] app_instr, input maint_en, output reg maint_ack, input[31:0] maint_instr, output instr0_fifo_en, output[31:0] instr0_fifo_data, output instr1_fifo_en, output[31:0] instr1_fifo_data, output process_iseq ); reg process_iseq_r = 1'b0, process_iseq_ns; localparam STATE_IDLE = 2'b00; localparam STATE_APP = 2'b01; localparam STATE_MAINT = 2'b10; reg[1:0] state_ns, state_r; reg sel_fifo = 1'b0; reg instr_en_ns, instr_en_r; reg[31:0] instr_ns, instr_r; always@* begin process_iseq_ns = 1'b0; state_ns = state_r; instr_en_ns = 1'b0; instr_ns = instr_r; app_ack = 1'b0; maint_ack = 1'b0; case(state_r) STATE_IDLE: begin if(dispatcher_ready & ~process_iseq_r) begin if(app_en) begin state_ns = STATE_APP; instr_en_ns = app_en; instr_ns = app_instr; app_ack = 1'b1; end else if(maint_en) begin state_ns = STATE_MAINT; instr_en_ns = maint_en; instr_ns = maint_instr; maint_ack = 1'b1; end end //dispatcher_ready end //STATE_IDLE STATE_APP: begin app_ack = 1'b1; instr_en_ns = app_en; instr_ns = app_instr; if(instr_en_ns & (instr_ns[31:28] == `END_ISEQ)) begin process_iseq_ns = 1'b1; state_ns = STATE_IDLE; end end //STATE_APP STATE_MAINT: begin maint_ack = 1'b1; instr_en_ns = maint_en; instr_ns = maint_instr; if(instr_en_ns & (instr_ns[31:28] == `END_ISEQ)) begin instr_en_ns = 1'b0; process_iseq_ns = 1'b1; state_ns = STATE_IDLE; end end //STATE_MAINT endcase //state_r end //always assign instr0_fifo_en = ~sel_fifo & instr_en_r; assign instr0_fifo_data = instr_r; assign instr1_fifo_en = sel_fifo & instr_en_r; assign instr1_fifo_data = instr_r; always@(posedge clk) begin if(rst) begin process_iseq_r <= 1'b0; sel_fifo <= 1'b0; state_r <= STATE_IDLE; instr_en_r <= 1'b0; instr_r <= 0; end else begin state_r <= state_ns; process_iseq_r <= process_iseq_ns; instr_en_r <= instr_en_ns; instr_r <= instr_ns; if(process_iseq_r) sel_fifo <= 1'b0; else if(instr_en_r) sel_fifo <= ~sel_fifo; end //!rst end assign process_iseq = process_iseq_r; endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/instr_fifo.xco ================================================ ############################################################## # # Xilinx Core Generator version 14.6 # Date: Fri Feb 3 17:08:40 2017 # ############################################################## # # This file contains the customisation parameters for a # Xilinx CORE Generator IP GUI. It is strongly recommended # that you do not manually alter this file as it may cause # unexpected and unsupported behavior. # ############################################################## # # Generated from component: xilinx.com:ip:fifo_generator:9.3 # ############################################################## # # BEGIN Project Options SET addpads = false SET asysymbol = true SET busformat = BusFormatAngleBracketNotRipped SET createndf = false SET designentry = Verilog SET device = xc6vlx240t SET devicefamily = virtex6 SET flowvendor = Other SET formalverification = false SET foundationsym = false SET implementationfiletype = Ngc SET package = ff1156 SET removerpms = false SET simulationfiles = Behavioral SET speedgrade = -1 SET verilogsim = true SET vhdlsim = false # END Project Options # BEGIN Select SELECT FIFO_Generator xilinx.com:ip:fifo_generator:9.3 # END Select # BEGIN Parameters CSET add_ngc_constraint_axi=false CSET almost_empty_flag=false CSET almost_full_flag=false CSET aruser_width=1 CSET awuser_width=1 CSET axi_address_width=32 CSET axi_data_width=64 CSET axi_type=AXI4_Stream CSET axis_type=FIFO CSET buser_width=1 CSET clock_enable_type=Slave_Interface_Clock_Enable CSET clock_type_axi=Common_Clock CSET component_name=instr_fifo CSET data_count=false CSET data_count_width=11 CSET disable_timing_violations=false CSET disable_timing_violations_axi=false CSET dout_reset_value=0 CSET empty_threshold_assert_value=4 CSET empty_threshold_assert_value_axis=1022 CSET empty_threshold_assert_value_rach=1022 CSET empty_threshold_assert_value_rdch=1022 CSET empty_threshold_assert_value_wach=1022 CSET empty_threshold_assert_value_wdch=1022 CSET empty_threshold_assert_value_wrch=1022 CSET empty_threshold_negate_value=5 CSET enable_aruser=false CSET enable_awuser=false CSET enable_buser=false CSET enable_common_overflow=false CSET enable_common_underflow=false CSET enable_data_counts_axis=false CSET enable_data_counts_rach=false CSET enable_data_counts_rdch=false CSET enable_data_counts_wach=false CSET enable_data_counts_wdch=false CSET enable_data_counts_wrch=false CSET enable_ecc=false CSET enable_ecc_axis=false CSET enable_ecc_rach=false CSET enable_ecc_rdch=false CSET enable_ecc_wach=false CSET enable_ecc_wdch=false CSET enable_ecc_wrch=false CSET enable_read_channel=false CSET enable_read_pointer_increment_by2=false CSET enable_reset_synchronization=true CSET enable_ruser=false CSET enable_tdata=false CSET enable_tdest=false CSET enable_tid=false CSET enable_tkeep=false CSET enable_tlast=false CSET enable_tready=true CSET enable_tstrobe=false CSET enable_tuser=false CSET enable_write_channel=false CSET enable_wuser=false CSET fifo_application_type_axis=Data_FIFO CSET fifo_application_type_rach=Data_FIFO CSET fifo_application_type_rdch=Data_FIFO CSET fifo_application_type_wach=Data_FIFO CSET fifo_application_type_wdch=Data_FIFO CSET fifo_application_type_wrch=Data_FIFO CSET fifo_implementation=Common_Clock_Block_RAM CSET fifo_implementation_axis=Common_Clock_Block_RAM CSET fifo_implementation_rach=Common_Clock_Block_RAM CSET fifo_implementation_rdch=Common_Clock_Block_RAM CSET fifo_implementation_wach=Common_Clock_Block_RAM CSET fifo_implementation_wdch=Common_Clock_Block_RAM CSET fifo_implementation_wrch=Common_Clock_Block_RAM CSET full_flags_reset_value=0 CSET full_threshold_assert_value=1023 CSET full_threshold_assert_value_axis=1023 CSET full_threshold_assert_value_rach=1023 CSET full_threshold_assert_value_rdch=1023 CSET full_threshold_assert_value_wach=1023 CSET full_threshold_assert_value_wdch=1023 CSET full_threshold_assert_value_wrch=1023 CSET full_threshold_negate_value=1022 CSET id_width=4 CSET inject_dbit_error=false CSET inject_dbit_error_axis=false CSET inject_dbit_error_rach=false CSET inject_dbit_error_rdch=false CSET inject_dbit_error_wach=false CSET inject_dbit_error_wdch=false CSET inject_dbit_error_wrch=false CSET inject_sbit_error=false CSET inject_sbit_error_axis=false CSET inject_sbit_error_rach=false CSET inject_sbit_error_rdch=false CSET inject_sbit_error_wach=false CSET inject_sbit_error_wdch=false CSET inject_sbit_error_wrch=false CSET input_data_width=32 CSET input_depth=1024 CSET input_depth_axis=1024 CSET input_depth_rach=16 CSET input_depth_rdch=1024 CSET input_depth_wach=16 CSET input_depth_wdch=1024 CSET input_depth_wrch=16 CSET interface_type=Native CSET output_data_width=32 CSET output_depth=1024 CSET overflow_flag=false CSET overflow_flag_axi=false CSET overflow_sense=Active_High CSET overflow_sense_axi=Active_High CSET performance_options=First_Word_Fall_Through CSET programmable_empty_type=No_Programmable_Empty_Threshold CSET programmable_empty_type_axis=No_Programmable_Empty_Threshold CSET programmable_empty_type_rach=No_Programmable_Empty_Threshold CSET programmable_empty_type_rdch=No_Programmable_Empty_Threshold CSET programmable_empty_type_wach=No_Programmable_Empty_Threshold CSET programmable_empty_type_wdch=No_Programmable_Empty_Threshold CSET programmable_empty_type_wrch=No_Programmable_Empty_Threshold CSET programmable_full_type=No_Programmable_Full_Threshold CSET programmable_full_type_axis=No_Programmable_Full_Threshold CSET programmable_full_type_rach=No_Programmable_Full_Threshold CSET programmable_full_type_rdch=No_Programmable_Full_Threshold CSET programmable_full_type_wach=No_Programmable_Full_Threshold CSET programmable_full_type_wdch=No_Programmable_Full_Threshold CSET programmable_full_type_wrch=No_Programmable_Full_Threshold CSET rach_type=FIFO CSET rdch_type=FIFO CSET read_clock_frequency=1 CSET read_data_count=false CSET read_data_count_width=11 CSET register_slice_mode_axis=Fully_Registered CSET register_slice_mode_rach=Fully_Registered CSET register_slice_mode_rdch=Fully_Registered CSET register_slice_mode_wach=Fully_Registered CSET register_slice_mode_wdch=Fully_Registered CSET register_slice_mode_wrch=Fully_Registered CSET reset_pin=true CSET reset_type=Synchronous_Reset CSET ruser_width=1 CSET synchronization_stages=2 CSET synchronization_stages_axi=2 CSET tdata_width=64 CSET tdest_width=4 CSET tid_width=8 CSET tkeep_width=4 CSET tstrb_width=4 CSET tuser_width=4 CSET underflow_flag=false CSET underflow_flag_axi=false CSET underflow_sense=Active_High CSET underflow_sense_axi=Active_High CSET use_clock_enable=false CSET use_dout_reset=true CSET use_embedded_registers=true CSET use_extra_logic=true CSET valid_flag=false CSET valid_sense=Active_High CSET wach_type=FIFO CSET wdch_type=FIFO CSET wrch_type=FIFO CSET write_acknowledge_flag=false CSET write_acknowledge_sense=Active_High CSET write_clock_frequency=1 CSET write_data_count=false CSET write_data_count_width=11 CSET wuser_width=1 # END Parameters # BEGIN Extra information MISC pkg_timestamp=2012-11-19T12:39:56Z # END Extra information GENERATE # CRC: 944578b5 ================================================ FILE: hw/boards/ML605/ipcore_dir/instr_fifo.xise ================================================
================================================ FILE: hw/boards/ML605/ipcore_dir/pcie_endpoint.xco ================================================ ############################################################## # # Xilinx Core Generator version 14.6 # Date: Fri Feb 3 17:11:58 2017 # ############################################################## # # This file contains the customisation parameters for a # Xilinx CORE Generator IP GUI. It is strongly recommended # that you do not manually alter this file as it may cause # unexpected and unsupported behavior. # ############################################################## # # Generated from component: xilinx.com:ip:v6_pcie:2.5 # ############################################################## # # BEGIN Project Options SET addpads = false SET asysymbol = true SET busformat = BusFormatAngleBracketNotRipped SET createndf = false SET designentry = Verilog SET device = xc6vlx240t SET devicefamily = virtex6 SET flowvendor = Other SET formalverification = false SET foundationsym = false SET implementationfiletype = Ngc SET package = ff1156 SET removerpms = false SET simulationfiles = Behavioral SET speedgrade = -1 SET verilogsim = true SET vhdlsim = false # END Project Options # BEGIN Select SELECT Virtex-6_Integrated_Block_for_PCI_Express xilinx.com:ip:v6_pcie:2.5 # END Select # BEGIN Parameters CSET acceptable_l0s_latency=Maximum_of_64_ns CSET acceptable_l1_latency=No_limit CSET ack_nak_timeout_func=Absolute CSET ack_nak_timeout_value=0000 CSET bar0_64bit=false CSET bar0_enabled=true CSET bar0_prefetchable=false CSET bar0_scale=Kilobytes CSET bar0_size=1 CSET bar0_type=Memory CSET bar1_64bit=false CSET bar1_enabled=false CSET bar1_prefetchable=false CSET bar1_scale=Kilobytes CSET bar1_size=2 CSET bar1_type=N/A CSET bar2_64bit=false CSET bar2_enabled=false CSET bar2_prefetchable=false CSET bar2_scale=Bytes CSET bar2_size=128 CSET bar2_type=N/A CSET bar3_64bit=false CSET bar3_enabled=false CSET bar3_prefetchable=false CSET bar3_scale=Kilobytes CSET bar3_size=2 CSET bar3_type=N/A CSET bar4_64bit=false CSET bar4_enabled=false CSET bar4_prefetchable=false CSET bar4_scale=Kilobytes CSET bar4_size=2 CSET bar4_type=N/A CSET bar5_enabled=false CSET bar5_prefetchable=false CSET bar5_scale=Kilobytes CSET bar5_size=2 CSET bar5_type=N/A CSET base_class_menu=Simple_communication_controllers CSET buf_opt_bma=true CSET cardbus_cis_pointer=00000000 CSET class_code_base=05 CSET class_code_interface=00 CSET class_code_sub=00 CSET component_name=pcie_endpoint CSET cost_table=1 CSET cpl_finite=false CSET cpl_timeout_disable_sup=false CSET cpl_timeout_range=Range_B CSET d0_pme_support=true CSET d0_power_consumed=0 CSET d0_power_consumed_factor=0 CSET d0_power_dissipated=0 CSET d0_power_dissipated_factor=0 CSET d1_pme_support=true CSET d1_power_consumed=0 CSET d1_power_consumed_factor=0 CSET d1_power_dissipated=0 CSET d1_power_dissipated_factor=0 CSET d1_support=false CSET d2_pme_support=true CSET d2_power_consumed=0 CSET d2_power_consumed_factor=0 CSET d2_power_dissipated=0 CSET d2_power_dissipated_factor=0 CSET d2_support=false CSET d3_power_consumed=0 CSET d3_power_consumed_factor=0 CSET d3_power_dissipated=0 CSET d3_power_dissipated_factor=0 CSET d3cold_pme_support=false CSET d3hot_pme_support=true CSET de_emph=0 CSET device_id=6018 CSET device_port_type=PCI_Express_Endpoint_device CSET device_specific_initialization=false CSET disable_tx_aspm_l0s=false CSET dll_link_active_cap=false CSET downstream_link_num=00 CSET dsn_enabled=true CSET en_route_err_cor=false CSET en_route_err_ftl=false CSET en_route_err_nfl=false CSET en_route_inta=false CSET en_route_intb=false CSET en_route_intc=false CSET en_route_intd=false CSET en_route_pm_pme=false CSET en_route_pme_to=false CSET en_route_pme_to_ack=false CSET en_route_unlock=false CSET enable_ack_nak_timer=false CSET enable_lane_reversal=false CSET enable_replay_timer=true CSET enable_slot_clock_cfg=false CSET expansion_rom_enabled=false CSET expansion_rom_scale=Kilobytes CSET expansion_rom_size=2 CSET ext_pci_cfg_space=false CSET ext_pci_cfg_space_addr=3FF CSET extended_tag_field=false CSET force_no_scrambling=false CSET hw_auton_spd_disable=false CSET intx_generation=true CSET io_base_limit_registers=Disabled CSET legacy_interrupt=INTA CSET link_speed=2.5_GT/s CSET max_payload_size=512_bytes CSET maximum_link_width=X8 CSET msi_64b=true CSET msi_enabled=true CSET msi_vec_mask=false CSET msix_enabled=false CSET msix_pba_bir=BAR_0 CSET msix_pba_offset=0 CSET msix_table_bir=BAR_0 CSET msix_table_offset=0 CSET msix_table_size=1 CSET multiple_message_capable=1_vector CSET no_soft_reset=true CSET pci_cfg_space=false CSET pci_cfg_space_addr=3F CSET pcie_blk_locn=X0Y0 CSET pcie_cap_slot_implemented=false CSET pcie_debug_ports=false CSET perf_level=High CSET phantom_functions=No_function_number_bits_used CSET pipe_pipeline=None CSET prefetchable_memory_base_limit_registers=Disabled CSET rcb=64_byte CSET ref_clk_freq=100_MHz CSET replay_timeout_func=Add CSET replay_timeout_value=0026 CSET revision_id=00 CSET root_cap_crs=false CSET slot_cap_attn_butn=false CSET slot_cap_attn_ind=false CSET slot_cap_elec_interlock=false CSET slot_cap_hotplug_cap=false CSET slot_cap_hotplug_surprise=false CSET slot_cap_mrl=false CSET slot_cap_no_cmd_comp_sup=false CSET slot_cap_physical_slot_num=0 CSET slot_cap_pwr_ctrl=false CSET slot_cap_pwr_ind=false CSET slot_cap_pwr_limit_scale=0 CSET slot_cap_pwr_limit_value=0 CSET sub_class_interface_menu=Generic_XT_compatible_serial_controller CSET subsystem_id=0007 CSET subsystem_vendor_id=10EE CSET trans_buf_pipeline=None CSET trgt_link_speed=4'h1 CSET trim_tlp_digest=false CSET upconfigure_capable=true CSET user_clk_freq=250_default CSET vc_cap_enabled=false CSET vc_cap_reject_snoop=false CSET vendor_id=10EE CSET vsec_enabled=false CSET xlnx_ref_board=ML_605 # END Parameters # BEGIN Extra information MISC pkg_timestamp=2013-06-08T22:50:04Z # END Extra information GENERATE # CRC: 2cdb8933 ================================================ FILE: hw/boards/ML605/ipcore_dir/pcie_endpoint.xise ================================================
================================================ FILE: hw/boards/ML605/ipcore_dir/rdback_fifo.xco ================================================ ############################################################## # # Xilinx Core Generator version 14.6 # Date: Fri Feb 3 17:12:17 2017 # ############################################################## # # This file contains the customisation parameters for a # Xilinx CORE Generator IP GUI. It is strongly recommended # that you do not manually alter this file as it may cause # unexpected and unsupported behavior. # ############################################################## # # Generated from component: xilinx.com:ip:fifo_generator:9.3 # ############################################################## # # BEGIN Project Options SET addpads = false SET asysymbol = true SET busformat = BusFormatAngleBracketNotRipped SET createndf = false SET designentry = Verilog SET device = xc6vlx240t SET devicefamily = virtex6 SET flowvendor = Other SET formalverification = false SET foundationsym = false SET implementationfiletype = Ngc SET package = ff1156 SET removerpms = false SET simulationfiles = Behavioral SET speedgrade = -1 SET verilogsim = true SET vhdlsim = false # END Project Options # BEGIN Select SELECT FIFO_Generator xilinx.com:ip:fifo_generator:9.3 # END Select # BEGIN Parameters CSET add_ngc_constraint_axi=false CSET almost_empty_flag=false CSET almost_full_flag=true CSET aruser_width=1 CSET awuser_width=1 CSET axi_address_width=32 CSET axi_data_width=64 CSET axi_type=AXI4_Stream CSET axis_type=FIFO CSET buser_width=1 CSET clock_enable_type=Slave_Interface_Clock_Enable CSET clock_type_axi=Common_Clock CSET component_name=rdback_fifo CSET data_count=false CSET data_count_width=11 CSET disable_timing_violations=false CSET disable_timing_violations_axi=false CSET dout_reset_value=0 CSET empty_threshold_assert_value=4 CSET empty_threshold_assert_value_axis=1022 CSET empty_threshold_assert_value_rach=1022 CSET empty_threshold_assert_value_rdch=1022 CSET empty_threshold_assert_value_wach=1022 CSET empty_threshold_assert_value_wdch=1022 CSET empty_threshold_assert_value_wrch=1022 CSET empty_threshold_negate_value=5 CSET enable_aruser=false CSET enable_awuser=false CSET enable_buser=false CSET enable_common_overflow=false CSET enable_common_underflow=false CSET enable_data_counts_axis=false CSET enable_data_counts_rach=false CSET enable_data_counts_rdch=false CSET enable_data_counts_wach=false CSET enable_data_counts_wdch=false CSET enable_data_counts_wrch=false CSET enable_ecc=false CSET enable_ecc_axis=false CSET enable_ecc_rach=false CSET enable_ecc_rdch=false CSET enable_ecc_wach=false CSET enable_ecc_wdch=false CSET enable_ecc_wrch=false CSET enable_read_channel=false CSET enable_read_pointer_increment_by2=false CSET enable_reset_synchronization=true CSET enable_ruser=false CSET enable_tdata=false CSET enable_tdest=false CSET enable_tid=false CSET enable_tkeep=false CSET enable_tlast=false CSET enable_tready=true CSET enable_tstrobe=false CSET enable_tuser=false CSET enable_write_channel=false CSET enable_wuser=false CSET fifo_application_type_axis=Data_FIFO CSET fifo_application_type_rach=Data_FIFO CSET fifo_application_type_rdch=Data_FIFO CSET fifo_application_type_wach=Data_FIFO CSET fifo_application_type_wdch=Data_FIFO CSET fifo_application_type_wrch=Data_FIFO CSET fifo_implementation=Common_Clock_Block_RAM CSET fifo_implementation_axis=Common_Clock_Block_RAM CSET fifo_implementation_rach=Common_Clock_Block_RAM CSET fifo_implementation_rdch=Common_Clock_Block_RAM CSET fifo_implementation_wach=Common_Clock_Block_RAM CSET fifo_implementation_wdch=Common_Clock_Block_RAM CSET fifo_implementation_wrch=Common_Clock_Block_RAM CSET full_flags_reset_value=0 CSET full_threshold_assert_value=1023 CSET full_threshold_assert_value_axis=1023 CSET full_threshold_assert_value_rach=1023 CSET full_threshold_assert_value_rdch=1023 CSET full_threshold_assert_value_wach=1023 CSET full_threshold_assert_value_wdch=1023 CSET full_threshold_assert_value_wrch=1023 CSET full_threshold_negate_value=1022 CSET id_width=4 CSET inject_dbit_error=false CSET inject_dbit_error_axis=false CSET inject_dbit_error_rach=false CSET inject_dbit_error_rdch=false CSET inject_dbit_error_wach=false CSET inject_dbit_error_wdch=false CSET inject_dbit_error_wrch=false CSET inject_sbit_error=false CSET inject_sbit_error_axis=false CSET inject_sbit_error_rach=false CSET inject_sbit_error_rdch=false CSET inject_sbit_error_wach=false CSET inject_sbit_error_wdch=false CSET inject_sbit_error_wrch=false CSET input_data_width=256 CSET input_depth=1024 CSET input_depth_axis=1024 CSET input_depth_rach=16 CSET input_depth_rdch=1024 CSET input_depth_wach=16 CSET input_depth_wdch=1024 CSET input_depth_wrch=16 CSET interface_type=Native CSET output_data_width=256 CSET output_depth=1024 CSET overflow_flag=false CSET overflow_flag_axi=false CSET overflow_sense=Active_High CSET overflow_sense_axi=Active_High CSET performance_options=First_Word_Fall_Through CSET programmable_empty_type=No_Programmable_Empty_Threshold CSET programmable_empty_type_axis=No_Programmable_Empty_Threshold CSET programmable_empty_type_rach=No_Programmable_Empty_Threshold CSET programmable_empty_type_rdch=No_Programmable_Empty_Threshold CSET programmable_empty_type_wach=No_Programmable_Empty_Threshold CSET programmable_empty_type_wdch=No_Programmable_Empty_Threshold CSET programmable_empty_type_wrch=No_Programmable_Empty_Threshold CSET programmable_full_type=No_Programmable_Full_Threshold CSET programmable_full_type_axis=No_Programmable_Full_Threshold CSET programmable_full_type_rach=No_Programmable_Full_Threshold CSET programmable_full_type_rdch=No_Programmable_Full_Threshold CSET programmable_full_type_wach=No_Programmable_Full_Threshold CSET programmable_full_type_wdch=No_Programmable_Full_Threshold CSET programmable_full_type_wrch=No_Programmable_Full_Threshold CSET rach_type=FIFO CSET rdch_type=FIFO CSET read_clock_frequency=1 CSET read_data_count=false CSET read_data_count_width=11 CSET register_slice_mode_axis=Fully_Registered CSET register_slice_mode_rach=Fully_Registered CSET register_slice_mode_rdch=Fully_Registered CSET register_slice_mode_wach=Fully_Registered CSET register_slice_mode_wdch=Fully_Registered CSET register_slice_mode_wrch=Fully_Registered CSET reset_pin=true CSET reset_type=Synchronous_Reset CSET ruser_width=1 CSET synchronization_stages=2 CSET synchronization_stages_axi=2 CSET tdata_width=64 CSET tdest_width=4 CSET tid_width=8 CSET tkeep_width=4 CSET tstrb_width=4 CSET tuser_width=4 CSET underflow_flag=false CSET underflow_flag_axi=false CSET underflow_sense=Active_High CSET underflow_sense_axi=Active_High CSET use_clock_enable=false CSET use_dout_reset=true CSET use_embedded_registers=false CSET use_extra_logic=true CSET valid_flag=false CSET valid_sense=Active_High CSET wach_type=FIFO CSET wdch_type=FIFO CSET wrch_type=FIFO CSET write_acknowledge_flag=false CSET write_acknowledge_sense=Active_High CSET write_clock_frequency=1 CSET write_data_count=false CSET write_data_count_width=11 CSET wuser_width=1 # END Parameters # BEGIN Extra information MISC pkg_timestamp=2012-11-19T12:39:56Z # END Extra information GENERATE # CRC: 38434af1 ================================================ FILE: hw/boards/ML605/ipcore_dir/rdback_fifo.xise ================================================
================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/async_fifo.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: async_fifo.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Asynchronous capable parameterized FIFO. As with all // traditional FIFOs, the RD_DATA will be valid one cycle following a RD_EN // assertion. RD_EMPTY will remain low until the cycle following the last RD_EN // assertion. Note, that RD_EMPTY may actually be high on the same cycle that // RD_DATA contains valid data. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: Based on design by CE Cummings in Simulation and // Synthesis Techniques for Asynchronous FIFO Design with Asynchronous Pointer // Comparisons //----------------------------------------------------------------------------- module async_fifo #( parameter C_WIDTH = 32, // Data bus width parameter C_DEPTH = 1024, // Depth of the FIFO // Local parameters parameter C_REAL_DEPTH = 2**clog2(C_DEPTH), parameter C_DEPTH_BITS = clog2(C_REAL_DEPTH), parameter C_DEPTH_P1_BITS = clog2(C_REAL_DEPTH+1) ) ( input RD_CLK, // Read clock input RD_RST, // Read synchronous reset input WR_CLK, // Write clock input WR_RST, // Write synchronous reset input [C_WIDTH-1:0] WR_DATA, // Write data input (WR_CLK) input WR_EN, // Write enable, high active (WR_CLK) output [C_WIDTH-1:0] RD_DATA, // Read data output (RD_CLK) input RD_EN, // Read enable, high active (RD_CLK) output WR_FULL, // Full condition (WR_CLK) output RD_EMPTY // Empty condition (RD_CLK) ); `include "common_functions.v" wire wCmpEmpty; wire wCmpFull; wire [C_DEPTH_BITS-1:0] wWrPtr; wire [C_DEPTH_BITS-1:0] wRdPtr; wire [C_DEPTH_BITS-1:0] wWrPtrP1; wire [C_DEPTH_BITS-1:0] wRdPtrP1; // Memory block (synthesis attributes applied to this module will // determine the memory option). ram_2clk_1w_1r #(.C_RAM_WIDTH(C_WIDTH), .C_RAM_DEPTH(C_REAL_DEPTH)) mem ( .CLKA(WR_CLK), .ADDRA(wWrPtr), .WEA(WR_EN & !WR_FULL), .DINA(WR_DATA), .CLKB(RD_CLK), .ADDRB(wRdPtr), .DOUTB(RD_DATA) ); // Compare the pointers. async_cmp #(.C_DEPTH_BITS(C_DEPTH_BITS)) asyncCompare ( .WR_RST(WR_RST), .WR_CLK(WR_CLK), .RD_RST(RD_RST), .RD_CLK(RD_CLK), .RD_VALID(RD_EN & !RD_EMPTY), .WR_VALID(WR_EN & !WR_FULL), .EMPTY(wCmpEmpty), .FULL(wCmpFull), .WR_PTR(wWrPtr), .WR_PTR_P1(wWrPtrP1), .RD_PTR(wRdPtr), .RD_PTR_P1(wRdPtrP1) ); // Calculate empty rd_ptr_empty #(.C_DEPTH_BITS(C_DEPTH_BITS)) rdPtrEmpty ( .RD_EMPTY(RD_EMPTY), .RD_PTR(wRdPtr), .RD_PTR_P1(wRdPtrP1), .CMP_EMPTY(wCmpEmpty), .RD_EN(RD_EN), .RD_CLK(RD_CLK), .RD_RST(RD_RST) ); // Calculate full wr_ptr_full #(.C_DEPTH_BITS(C_DEPTH_BITS)) wrPtrFull ( .WR_CLK(WR_CLK), .WR_RST(WR_RST), .WR_EN(WR_EN), .WR_FULL(WR_FULL), .WR_PTR(wWrPtr), .WR_PTR_P1(wWrPtrP1), .CMP_FULL(wCmpFull) ); endmodule module async_cmp #( parameter C_DEPTH_BITS = 4, // Local parameters parameter N = C_DEPTH_BITS-1 ) ( input WR_RST, input WR_CLK, input RD_RST, input RD_CLK, input RD_VALID, input WR_VALID, output EMPTY, output FULL, input [C_DEPTH_BITS-1:0] WR_PTR, input [C_DEPTH_BITS-1:0] RD_PTR, input [C_DEPTH_BITS-1:0] WR_PTR_P1, input [C_DEPTH_BITS-1:0] RD_PTR_P1 ); reg rDir=0; wire wDirSet = ( (WR_PTR[N]^RD_PTR[N-1]) & ~(WR_PTR[N-1]^RD_PTR[N])); wire wDirClr = ((~(WR_PTR[N]^RD_PTR[N-1]) & (WR_PTR[N-1]^RD_PTR[N])) | WR_RST); reg rRdValid=0; reg rEmpty=1; reg rFull=0; wire wATBEmpty = ((WR_PTR == RD_PTR_P1) && (RD_VALID | rRdValid)); wire wATBFull = ((WR_PTR_P1 == RD_PTR) && WR_VALID); wire wEmpty = ((WR_PTR == RD_PTR) && !rDir); wire wFull = ((WR_PTR == RD_PTR) && rDir); assign EMPTY = wATBEmpty || rEmpty; assign FULL = wATBFull || rFull; always @(posedge wDirSet or posedge wDirClr) if (wDirClr) rDir <= 1'b0; else rDir <= 1'b1; always @(posedge RD_CLK) begin rEmpty <= (RD_RST ? 1'd1 : wEmpty); rRdValid <= (RD_RST ? 1'd0 : RD_VALID); end always @(posedge WR_CLK) begin rFull <= (WR_RST ? 1'd0 : wFull); end endmodule module rd_ptr_empty #( parameter C_DEPTH_BITS = 4 ) ( input RD_CLK, input RD_RST, input RD_EN, output RD_EMPTY, output [C_DEPTH_BITS-1:0] RD_PTR, output [C_DEPTH_BITS-1:0] RD_PTR_P1, input CMP_EMPTY ); reg rEmpty=1; reg rEmpty2=1; reg [C_DEPTH_BITS-1:0] rRdPtr=0; reg [C_DEPTH_BITS-1:0] rRdPtrP1=0; reg [C_DEPTH_BITS-1:0] rBin=0; reg [C_DEPTH_BITS-1:0] rBinP1=1; wire [C_DEPTH_BITS-1:0] wGrayNext; wire [C_DEPTH_BITS-1:0] wGrayNextP1; wire [C_DEPTH_BITS-1:0] wBinNext; wire [C_DEPTH_BITS-1:0] wBinNextP1; assign RD_EMPTY = rEmpty; assign RD_PTR = rRdPtr; assign RD_PTR_P1 = rRdPtrP1; // Gray coded pointer always @(posedge RD_CLK or posedge RD_RST) begin if (RD_RST) begin rBin <= #1 0; rBinP1 <= #1 1; rRdPtr <= #1 0; rRdPtrP1 <= #1 0; end else begin rBin <= #1 wBinNext; rBinP1 <= #1 wBinNextP1; rRdPtr <= #1 wGrayNext; rRdPtrP1 <= #1 wGrayNextP1; end end // Increment the binary count if not empty assign wBinNext = (!rEmpty ? rBin + RD_EN : rBin); assign wBinNextP1 = (!rEmpty ? rBinP1 + RD_EN : rBinP1); assign wGrayNext = ((wBinNext>>1) ^ wBinNext); // binary-to-gray conversion assign wGrayNextP1 = ((wBinNextP1>>1) ^ wBinNextP1); // binary-to-gray conversion always @(posedge RD_CLK) begin if (CMP_EMPTY) {rEmpty, rEmpty2} <= #1 2'b11; else {rEmpty, rEmpty2} <= #1 {rEmpty2, CMP_EMPTY}; end endmodule module wr_ptr_full #( parameter C_DEPTH_BITS = 4 ) ( input WR_CLK, input WR_RST, input WR_EN, output WR_FULL, output [C_DEPTH_BITS-1:0] WR_PTR, output [C_DEPTH_BITS-1:0] WR_PTR_P1, input CMP_FULL ); reg rFull=0; reg rFull2=0; reg [C_DEPTH_BITS-1:0] rPtr=0; reg [C_DEPTH_BITS-1:0] rPtrP1=0; reg [C_DEPTH_BITS-1:0] rBin=0; reg [C_DEPTH_BITS-1:0] rBinP1=1; wire [C_DEPTH_BITS-1:0] wGrayNext; wire [C_DEPTH_BITS-1:0] wGrayNextP1; wire [C_DEPTH_BITS-1:0] wBinNext; wire [C_DEPTH_BITS-1:0] wBinNextP1; assign WR_FULL = rFull; assign WR_PTR = rPtr; assign WR_PTR_P1 = rPtrP1; // Gray coded pointer always @(posedge WR_CLK or posedge WR_RST) begin if (WR_RST) begin rBin <= #1 0; rBinP1 <= #1 1; rPtr <= #1 0; rPtrP1 <= #1 0; end else begin rBin <= #1 wBinNext; rBinP1 <= #1 wBinNextP1; rPtr <= #1 wGrayNext; rPtrP1 <= #1 wGrayNextP1; end end // Increment the binary count if not full assign wBinNext = (!rFull ? rBin + WR_EN : rBin); assign wBinNextP1 = (!rFull ? rBinP1 + WR_EN : rBinP1); assign wGrayNext = ((wBinNext>>1) ^ wBinNext); // binary-to-gray conversion assign wGrayNextP1 = ((wBinNextP1>>1) ^ wBinNextP1); // binary-to-gray conversion always @(posedge WR_CLK) begin if (WR_RST) {rFull, rFull2} <= #1 2'b00; else if (CMP_FULL) {rFull, rFull2} <= #1 2'b11; else {rFull, rFull2} <= #1 {rFull2, CMP_FULL}; end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/async_fifo_fwft.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: async_fifo_fwft.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: An asynchronous capable parameterized FIFO. As with all // first word fall through FIFOs, the RD_DATA will be valid when RD_EMPTY is // low. Asserting RD_EN will consume the current RD_DATA value and cause the // next value (if it exists) to appear on RD_DATA on the following cycle. Be sure // to check if RD_EMPTY is low each cycle to determine if RD_DATA is valid. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module async_fifo_fwft #( parameter C_WIDTH = 32, // Data bus width parameter C_DEPTH = 1024, // Depth of the FIFO // Local parameters parameter C_REAL_DEPTH = 2**clog2(C_DEPTH), parameter C_DEPTH_BITS = clog2s(C_REAL_DEPTH), parameter C_DEPTH_P1_BITS = clog2s(C_REAL_DEPTH+1) ) ( input RD_CLK, // Read clock input RD_RST, // Read synchronous reset input WR_CLK, // Write clock input WR_RST, // Write synchronous reset input [C_WIDTH-1:0] WR_DATA, // Write data input (WR_CLK) input WR_EN, // Write enable, high active (WR_CLK) output [C_WIDTH-1:0] RD_DATA, // Read data output (RD_CLK) input RD_EN, // Read enable, high active (RD_CLK) output WR_FULL, // Full condition (WR_CLK) output RD_EMPTY // Empty condition (RD_CLK) ); `include "common_functions.v" reg [C_WIDTH-1:0] rData=0; reg [C_WIDTH-1:0] rCache=0; reg [1:0] rCount=0; reg rFifoDataValid=0; reg rDataValid=0; reg rCacheValid=0; wire [C_WIDTH-1:0] wData; wire wEmpty; wire wRen = RD_EN || (rCount < 2'd2); assign RD_DATA = rData; assign RD_EMPTY = !rDataValid; // Wrapped non-FWFT FIFO (synthesis attributes applied to this module will // determine the memory option). async_fifo #(.C_WIDTH(C_WIDTH), .C_DEPTH(C_DEPTH)) fifo ( .WR_CLK(WR_CLK), .WR_RST(WR_RST), .RD_CLK(RD_CLK), .RD_RST(RD_RST), .WR_EN(WR_EN), .WR_DATA(WR_DATA), .WR_FULL(WR_FULL), .RD_EN(wRen), .RD_DATA(wData), .RD_EMPTY(wEmpty) ); always @ (posedge RD_CLK) begin if (RD_RST) begin rCount <= #1 0; rDataValid <= #1 0; rCacheValid <= #1 0; rFifoDataValid <= #1 0; end else begin // Keep track of the count rCount <= #1 rCount + (wRen & !wEmpty) - (!RD_EMPTY & RD_EN); // Signals when wData from FIFO is valid rFifoDataValid <= #1 (wRen & !wEmpty); // Keep rData up to date if (rFifoDataValid) begin if (RD_EN | !rDataValid) begin rData <= #1 wData; rDataValid <= #1 1'd1; rCacheValid <= #1 1'd0; end else begin rCacheValid <= #1 1'd1; end rCache <= #1 wData; end else begin if (RD_EN | !rDataValid) begin rData <= #1 rCache; rDataValid <= #1 rCacheValid; rCacheValid <= #1 1'd0; end end end end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/axi_basic_rx.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : axi_basic_rx.v // Version : 2.4 //----------------------------------------------------------------------------// // File: axi_basic_rx.v // // // // Description: // // TRN to AXI RX module. Instantiates pipeline and null generator RX // // submodules. // // // // Notes: // // Optional notes section. // // // // Hierarchical: // // axi_basic_top // // axi_basic_rx // // // //----------------------------------------------------------------------------// `timescale 1ps/1ps module axi_basic_rx #( parameter C_DATA_WIDTH = 128, // RX/TX interface data width parameter C_FAMILY = "X7", // Targeted FPGA family parameter C_ROOT_PORT = "FALSE", // PCIe block is in root port mode parameter C_PM_PRIORITY = "FALSE", // Disable TX packet boundary thrtl parameter TCQ = 1, // Clock to Q time // Do not override parameters below this line parameter REM_WIDTH = (C_DATA_WIDTH == 128) ? 2 : 1, // trem/rrem width parameter KEEP_WIDTH = C_DATA_WIDTH / 8 // KEEP width ) ( //---------------------------------------------// // User Design I/O // //---------------------------------------------// // AXI RX //----------- output [C_DATA_WIDTH-1:0] m_axis_rx_tdata, // RX data to user output m_axis_rx_tvalid, // RX data is valid input m_axis_rx_tready, // RX ready for data output [KEEP_WIDTH-1:0] m_axis_rx_tkeep, // RX strobe byte enables output m_axis_rx_tlast, // RX data is last output [21:0] m_axis_rx_tuser, // RX user signals //---------------------------------------------// // PCIe Block I/O // //---------------------------------------------// // TRN RX //----------- input [C_DATA_WIDTH-1:0] trn_rd, // RX data from block input trn_rsof, // RX start of packet input trn_reof, // RX end of packet input trn_rsrc_rdy, // RX source ready output trn_rdst_rdy, // RX destination ready input trn_rsrc_dsc, // RX source discontinue input [REM_WIDTH-1:0] trn_rrem, // RX remainder input trn_rerrfwd, // RX error forward input [6:0] trn_rbar_hit, // RX BAR hit input trn_recrc_err, // RX ECRC error // System //----------- output [2:0] np_counter, // Non-posted counter input user_clk, // user clock from block input user_rst // user reset from block ); // Wires wire null_rx_tvalid; wire null_rx_tlast; wire [KEEP_WIDTH-1:0] null_rx_tkeep; wire null_rdst_rdy; wire [4:0] null_is_eof; //---------------------------------------------// // RX Data Pipeline // //---------------------------------------------// axi_basic_rx_pipeline #( .C_DATA_WIDTH( C_DATA_WIDTH ), .C_FAMILY( C_FAMILY ), .TCQ( TCQ ), .REM_WIDTH( REM_WIDTH ), .KEEP_WIDTH( KEEP_WIDTH ) ) rx_pipeline_inst ( // Outgoing AXI TX //----------- .m_axis_rx_tdata( m_axis_rx_tdata ), .m_axis_rx_tvalid( m_axis_rx_tvalid ), .m_axis_rx_tready( m_axis_rx_tready ), .m_axis_rx_tkeep( m_axis_rx_tkeep ), .m_axis_rx_tlast( m_axis_rx_tlast ), .m_axis_rx_tuser( m_axis_rx_tuser ), // Incoming TRN RX //----------- .trn_rd( trn_rd ), .trn_rsof( trn_rsof ), .trn_reof( trn_reof ), .trn_rsrc_rdy( trn_rsrc_rdy ), .trn_rdst_rdy( trn_rdst_rdy ), .trn_rsrc_dsc( trn_rsrc_dsc ), .trn_rrem( trn_rrem ), .trn_rerrfwd( trn_rerrfwd ), .trn_rbar_hit( trn_rbar_hit ), .trn_recrc_err( trn_recrc_err ), // Null Inputs //----------- .null_rx_tvalid( null_rx_tvalid ), .null_rx_tlast( null_rx_tlast ), .null_rx_tkeep( null_rx_tkeep ), .null_rdst_rdy( null_rdst_rdy ), .null_is_eof( null_is_eof ), // System //----------- .np_counter( np_counter ), .user_clk( user_clk ), .user_rst( user_rst ) ); //---------------------------------------------// // RX Null Packet Generator // //---------------------------------------------// axi_basic_rx_null_gen #( .C_DATA_WIDTH( C_DATA_WIDTH ), .TCQ( TCQ ), .KEEP_WIDTH( KEEP_WIDTH ) ) rx_null_gen_inst ( // Inputs //----------- .m_axis_rx_tdata( m_axis_rx_tdata ), .m_axis_rx_tvalid( m_axis_rx_tvalid ), .m_axis_rx_tready( m_axis_rx_tready ), .m_axis_rx_tlast( m_axis_rx_tlast ), .m_axis_rx_tuser( m_axis_rx_tuser ), // Null Outputs //----------- .null_rx_tvalid( null_rx_tvalid ), .null_rx_tlast( null_rx_tlast ), .null_rx_tkeep( null_rx_tkeep ), .null_rdst_rdy( null_rdst_rdy ), .null_is_eof( null_is_eof ), // System //----------- .user_clk( user_clk ), .user_rst( user_rst ) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/axi_basic_rx_null_gen.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : axi_basic_rx_null_gen.v // Version : 2.4 //----------------------------------------------------------------------------// // File: axi_basic_rx_null_gen.v // // // // Description: // // TRN to AXI RX null generator. Generates null packets for use in // // discontinue situations. // // // // Notes: // // Optional notes section. // // // // Hierarchical: // // axi_basic_top // // axi_basic_rx // // axi_basic_rx_null_gen // // // //----------------------------------------------------------------------------// `timescale 1ps/1ps module axi_basic_rx_null_gen # ( parameter C_DATA_WIDTH = 128, // RX/TX interface data width parameter TCQ = 1, // Clock to Q time // Do not override parameters below this line parameter KEEP_WIDTH = C_DATA_WIDTH / 8 // KEEP width ) ( // AXI RX //----------- input [C_DATA_WIDTH-1:0] m_axis_rx_tdata, // RX data to user input m_axis_rx_tvalid, // RX data is valid input m_axis_rx_tready, // RX ready for data input m_axis_rx_tlast, // RX data is last input [21:0] m_axis_rx_tuser, // RX user signals // Null Inputs //----------- output null_rx_tvalid, // NULL generated tvalid output null_rx_tlast, // NULL generated tlast output [KEEP_WIDTH-1:0] null_rx_tkeep, // NULL generated tkeep output null_rdst_rdy, // NULL generated rdst_rdy output reg [4:0] null_is_eof, // NULL generated is_eof // System //----------- input user_clk, // user clock from block input user_rst // user reset from block ); localparam INTERFACE_WIDTH_DWORDS = (C_DATA_WIDTH == 128) ? 11'd4 : (C_DATA_WIDTH == 64) ? 11'd2 : 11'd1; //----------------------------------------------------------------------------// // NULL packet generator state machine // // This state machine shadows the AXI RX interface, tracking each packet as // // it's passed to the AXI user. When a multi-cycle packet is detected, the // // state machine automatically generates a "null" packet. In the event of a // // discontinue, the RX pipeline can switch over to this null packet as // // necessary. // //----------------------------------------------------------------------------// // State machine variables and states localparam IDLE = 0; localparam IN_PACKET = 1; reg cur_state; reg next_state; // Signals for tracking a packet on the AXI interface reg [11:0] reg_pkt_len_counter; reg [11:0] pkt_len_counter; wire [11:0] pkt_len_counter_dec; wire pkt_done; // Calculate packet fields, which are needed to determine total packet length. wire [11:0] new_pkt_len; wire [9:0] payload_len; wire [1:0] packet_fmt; wire packet_td; reg [3:0] packet_overhead; // Misc. wire [KEEP_WIDTH-1:0] eof_tkeep; wire straddle_sof; wire eof; // Create signals to detect sof and eof situations. These signals vary depending // on data width. assign eof = m_axis_rx_tuser[21]; generate if(C_DATA_WIDTH == 128) begin : sof_eof_128 assign straddle_sof = (m_axis_rx_tuser[14:13] == 2'b11); end else begin : sof_eof_64_32 assign straddle_sof = 1'b0; end endgenerate //----------------------------------------------------------------------------// // Calculate the length of the packet being presented on the RX interface. To // // do so, we need the relevent packet fields that impact total packet length. // // These are: // // - Header length: obtained from bit 1 of FMT field in 1st DWORD of header // // - Payload length: obtained from LENGTH field in 1st DWORD of header // // - TLP digist: obtained from TD field in 1st DWORD of header // // - Current data: the number of bytes that have already been presented // // on the data interface // // // // packet length = header + payload + tlp digest - # of DWORDS already // // transmitted // // // // packet_overhead is where we calculate everything except payload. // //----------------------------------------------------------------------------// generate if(C_DATA_WIDTH == 128) begin : len_calc_128 assign packet_fmt = straddle_sof ? m_axis_rx_tdata[94:93] : m_axis_rx_tdata[30:29]; assign packet_td = straddle_sof ? m_axis_rx_tdata[79] : m_axis_rx_tdata[15]; assign payload_len = packet_fmt[1] ? (straddle_sof ? m_axis_rx_tdata[73:64] : m_axis_rx_tdata[9:0]) : 10'h0; always @(*) begin // In 128-bit mode, the amount of data currently on the interface // depends on whether we're straddling or not. If so, 2 DWORDs have been // seen. If not, 4 DWORDs. case({packet_fmt[0], packet_td, straddle_sof}) // Header + TD - Data currently on interface 3'b0_0_0: packet_overhead = 4'd3 + 4'd0 - 4'd4; 3'b0_0_1: packet_overhead = 4'd3 + 4'd0 - 4'd2; 3'b0_1_0: packet_overhead = 4'd3 + 4'd1 - 4'd4; 3'b0_1_1: packet_overhead = 4'd3 + 4'd1 - 4'd2; 3'b1_0_0: packet_overhead = 4'd4 + 4'd0 - 4'd4; 3'b1_0_1: packet_overhead = 4'd4 + 4'd0 - 4'd2; 3'b1_1_0: packet_overhead = 4'd4 + 4'd1 - 4'd4; 3'b1_1_1: packet_overhead = 4'd4 + 4'd1 - 4'd2; endcase end end else if(C_DATA_WIDTH == 64) begin : len_calc_64 assign packet_fmt = m_axis_rx_tdata[30:29]; assign packet_td = m_axis_rx_tdata[15]; assign payload_len = packet_fmt[1] ? m_axis_rx_tdata[9:0] : 10'h0; always @(*) begin // 64-bit mode: no straddling, so always 2 DWORDs case({packet_fmt[0], packet_td}) // Header + TD - Data currently on interface 2'b0_0: packet_overhead = 4'd3 + 4'd0 - 4'd2; 2'b0_1: packet_overhead = 4'd3 + 4'd1 - 4'd2; 2'b1_0: packet_overhead = 4'd4 + 4'd0 - 4'd2; 2'b1_1: packet_overhead = 4'd4 + 4'd1 - 4'd2; endcase end end else begin : len_calc_32 assign packet_fmt = m_axis_rx_tdata[30:29]; assign packet_td = m_axis_rx_tdata[15]; assign payload_len = packet_fmt[1] ? m_axis_rx_tdata[9:0] : 10'h0; always @(*) begin // 32-bit mode: no straddling, so always 1 DWORD case({packet_fmt[0], packet_td}) // Header + TD - Data currently on interface 2'b0_0: packet_overhead = 4'd3 + 4'd0 - 4'd1; 2'b0_1: packet_overhead = 4'd3 + 4'd1 - 4'd1; 2'b1_0: packet_overhead = 4'd4 + 4'd0 - 4'd1; 2'b1_1: packet_overhead = 4'd4 + 4'd1 - 4'd1; endcase end end endgenerate // Now calculate actual packet length, adding the packet overhead and the // payload length. This is signed math, so sign-extend packet_overhead. // NOTE: a payload length of zero means 1024 DW in the PCIe spec, but this // behavior isn't supported in our block. assign new_pkt_len = {{9{packet_overhead[3]}}, packet_overhead[2:0]} + {2'b0, payload_len}; // Math signals needed in the state machine below. These are seperate wires to // help ensure synthesis tools sre smart about optimizing them. assign pkt_len_counter_dec = reg_pkt_len_counter - INTERFACE_WIDTH_DWORDS; assign pkt_done = (reg_pkt_len_counter <= INTERFACE_WIDTH_DWORDS); //----------------------------------------------------------------------------// // Null generator Mealy state machine. Determine outputs based on: // // 1) current st // // 2) current inp // //----------------------------------------------------------------------------// always @(*) begin case (cur_state) // IDLE state: the interface is IDLE and we're waiting for a packet to // start. If a packet starts, move to state IN_PACKET and begin tracking // it as long as it's NOT a single cycle packet (indicated by assertion of // eof at packet start) IDLE: begin if(m_axis_rx_tvalid && m_axis_rx_tready && !eof) begin next_state = IN_PACKET; end else begin next_state = IDLE; end pkt_len_counter = new_pkt_len; end // IN_PACKET: a mutli-cycle packet is in progress and we're tracking it. We // are in lock-step with the AXI interface decrementing our packet length // tracking reg, and waiting for the packet to finish. // // * If packet finished and a new one starts, this is a straddle situation. // Next state is IN_PACKET (128-bit only). // * If the current packet is done, next state is IDLE. // * Otherwise, next state is IN_PACKET. IN_PACKET: begin // Straddle packet if((C_DATA_WIDTH == 128) && straddle_sof && m_axis_rx_tvalid) begin pkt_len_counter = new_pkt_len; next_state = IN_PACKET; end // Current packet finished else if(m_axis_rx_tready && pkt_done) begin pkt_len_counter = new_pkt_len; next_state = IDLE; end // Packet in progress else begin if(m_axis_rx_tready) begin // Not throttled pkt_len_counter = pkt_len_counter_dec; end else begin // Throttled pkt_len_counter = reg_pkt_len_counter; end next_state = IN_PACKET; end end default: begin pkt_len_counter = reg_pkt_len_counter; next_state = IDLE; end endcase end // Synchronous NULL packet generator state machine logic always @(posedge user_clk) begin if(user_rst) begin cur_state <= #TCQ IDLE; reg_pkt_len_counter <= #TCQ 12'h0; end else begin cur_state <= #TCQ next_state; reg_pkt_len_counter <= #TCQ pkt_len_counter; end end // Generate tkeep/is_eof for an end-of-packet situation. generate if(C_DATA_WIDTH == 128) begin : strb_calc_128 always @(*) begin // Assign null_is_eof depending on how many DWORDs are left in the // packet. case(pkt_len_counter) 10'd1: null_is_eof = 5'b10011; 10'd2: null_is_eof = 5'b10111; 10'd3: null_is_eof = 5'b11011; 10'd4: null_is_eof = 5'b11111; default: null_is_eof = 5'b00011; endcase end // tkeep not used in 128-bit interface assign eof_tkeep = {KEEP_WIDTH{1'b0}}; end else if(C_DATA_WIDTH == 64) begin : strb_calc_64 always @(*) begin // Assign null_is_eof depending on how many DWORDs are left in the // packet. case(pkt_len_counter) 10'd1: null_is_eof = 5'b10011; 10'd2: null_is_eof = 5'b10111; default: null_is_eof = 5'b00011; endcase end // Assign tkeep to 0xFF or 0x0F depending on how many DWORDs are left in // the current packet. assign eof_tkeep = { ((pkt_len_counter == 12'd2) ? 4'hF:4'h0), 4'hF }; end else begin : strb_calc_32 always @(*) begin // is_eof is either on or off for 32-bit if(pkt_len_counter == 12'd1) begin null_is_eof = 5'b10011; end else begin null_is_eof = 5'b00011; end end // The entire DWORD is always valid in 32-bit mode, so tkeep is always 0xF assign eof_tkeep = 4'hF; end endgenerate // Finally, use everything we've generated to calculate our NULL outputs assign null_rx_tvalid = 1'b1; assign null_rx_tlast = (pkt_len_counter <= INTERFACE_WIDTH_DWORDS); assign null_rx_tkeep = null_rx_tlast ? eof_tkeep : {KEEP_WIDTH{1'b1}}; assign null_rdst_rdy = null_rx_tlast; endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/axi_basic_rx_pipeline.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : axi_basic_rx_pipeline.v // Version : 2.4 //----------------------------------------------------------------------------// // File: axi_basic_rx_pipeline.v // // // // Description: // // TRN to AXI RX pipeline. Converts received data from TRN protocol to AXI. // // // // Notes: // // Optional notes section. // // // // Hierarchical: // // axi_basic_top // // axi_basic_rx // // axi_basic_rx_pipeline // // // //----------------------------------------------------------------------------// `timescale 1ps/1ps module axi_basic_rx_pipeline #( parameter C_DATA_WIDTH = 128, // RX/TX interface data width parameter C_FAMILY = "X7", // Targeted FPGA family parameter TCQ = 1, // Clock to Q time // Do not override parameters below this line parameter REM_WIDTH = (C_DATA_WIDTH == 128) ? 2 : 1, // trem/rrem width parameter KEEP_WIDTH = C_DATA_WIDTH / 8 // KEEP width ) ( // AXI RX //----------- output reg [C_DATA_WIDTH-1:0] m_axis_rx_tdata, // RX data to user output reg m_axis_rx_tvalid, // RX data is valid input m_axis_rx_tready, // RX ready for data output [KEEP_WIDTH-1:0] m_axis_rx_tkeep, // RX strobe byte enables output m_axis_rx_tlast, // RX data is last output reg [21:0] m_axis_rx_tuser, // RX user signals // TRN RX //----------- input [C_DATA_WIDTH-1:0] trn_rd, // RX data from block input trn_rsof, // RX start of packet input trn_reof, // RX end of packet input trn_rsrc_rdy, // RX source ready output reg trn_rdst_rdy, // RX destination ready input trn_rsrc_dsc, // RX source discontinue input [REM_WIDTH-1:0] trn_rrem, // RX remainder input trn_rerrfwd, // RX error forward input [6:0] trn_rbar_hit, // RX BAR hit input trn_recrc_err, // RX ECRC error // Null Inputs //----------- input null_rx_tvalid, // NULL generated tvalid input null_rx_tlast, // NULL generated tlast input [KEEP_WIDTH-1:0] null_rx_tkeep, // NULL generated tkeep input null_rdst_rdy, // NULL generated rdst_rdy input [4:0] null_is_eof, // NULL generated is_eof // System //----------- output [2:0] np_counter, // Non-posted counter input user_clk, // user clock from block input user_rst // user reset from block ); // Wires and regs for creating AXI signals wire [4:0] is_sof; wire [4:0] is_sof_prev; wire [4:0] is_eof; wire [4:0] is_eof_prev; reg [KEEP_WIDTH-1:0] reg_tkeep; wire [KEEP_WIDTH-1:0] tkeep; wire [KEEP_WIDTH-1:0] tkeep_prev; reg reg_tlast; wire rsrc_rdy_filtered; // Wires and regs for previous value buffer wire [C_DATA_WIDTH-1:0] trn_rd_DW_swapped; reg [C_DATA_WIDTH-1:0] trn_rd_prev; wire data_hold; reg data_prev; reg trn_reof_prev; reg [REM_WIDTH-1:0] trn_rrem_prev; reg trn_rsrc_rdy_prev; reg trn_rsrc_dsc_prev; reg trn_rsof_prev; reg [6:0] trn_rbar_hit_prev; reg trn_rerrfwd_prev; reg trn_recrc_err_prev; // Null packet handling signals reg null_mux_sel; reg trn_in_packet; wire dsc_flag; wire dsc_detect; reg reg_dsc_detect; reg trn_rsrc_dsc_d; // Create "filtered" version of rsrc_rdy, where discontinued SOFs are removed. assign rsrc_rdy_filtered = trn_rsrc_rdy && (trn_in_packet || (trn_rsof && !trn_rsrc_dsc)); //----------------------------------------------------------------------------// // Previous value buffer // // --------------------- // // We are inserting a pipeline stage in between TRN and AXI, which causes // // some issues with handshaking signals m_axis_rx_tready/trn_rdst_rdy. The // // added cycle of latency in the path causes the user design to fall behind // // the TRN interface whenever it throttles. // // // // To avoid loss of data, we must keep the previous value of all trn_r* // // signals in case the user throttles. // //----------------------------------------------------------------------------// always @(posedge user_clk) begin if(user_rst) begin trn_rd_prev <= #TCQ {C_DATA_WIDTH{1'b0}}; trn_rsof_prev <= #TCQ 1'b0; trn_rrem_prev <= #TCQ {REM_WIDTH{1'b0}}; trn_rsrc_rdy_prev <= #TCQ 1'b0; trn_rbar_hit_prev <= #TCQ 7'h00; trn_rerrfwd_prev <= #TCQ 1'b0; trn_recrc_err_prev <= #TCQ 1'b0; trn_reof_prev <= #TCQ 1'b0; trn_rsrc_dsc_prev <= #TCQ 1'b0; end else begin // prev buffer works by checking trn_rdst_rdy. When trn_rdst_rdy is // asserted, a new value is present on the interface. if(trn_rdst_rdy) begin trn_rd_prev <= #TCQ trn_rd_DW_swapped; trn_rsof_prev <= #TCQ trn_rsof; trn_rrem_prev <= #TCQ trn_rrem; trn_rbar_hit_prev <= #TCQ trn_rbar_hit; trn_rerrfwd_prev <= #TCQ trn_rerrfwd; trn_recrc_err_prev <= #TCQ trn_recrc_err; trn_rsrc_rdy_prev <= #TCQ rsrc_rdy_filtered; trn_reof_prev <= #TCQ trn_reof; trn_rsrc_dsc_prev <= #TCQ trn_rsrc_dsc || dsc_flag; end end end //----------------------------------------------------------------------------// // Create TDATA // //----------------------------------------------------------------------------// // Convert TRN data format to AXI data format. AXI is DWORD swapped from TRN // 128-bit: 64-bit: 32-bit: // TRN DW0 maps to AXI DW3 TRN DW0 maps to AXI DW1 TNR DW0 maps to AXI DW0 // TRN DW1 maps to AXI DW2 TRN DW1 maps to AXI DW0 // TRN DW2 maps to AXI DW1 // TRN DW3 maps to AXI DW0 generate if(C_DATA_WIDTH == 128) begin : rd_DW_swap_128 assign trn_rd_DW_swapped = {trn_rd[31:0], trn_rd[63:32], trn_rd[95:64], trn_rd[127:96]}; end else if(C_DATA_WIDTH == 64) begin : rd_DW_swap_64 assign trn_rd_DW_swapped = {trn_rd[31:0], trn_rd[63:32]}; end else begin : rd_DW_swap_32 assign trn_rd_DW_swapped = trn_rd; end endgenerate // Create special buffer which locks in the proper value of TDATA depending // on whether the user is throttling or not. This buffer has three states: // // HOLD state: TDATA maintains its current value // - the user has throttled the PCIe block // PREVIOUS state: the buffer provides the previous value on trn_rd // - the user has finished throttling, and is a little behind // the PCIe block // CURRENT state: the buffer passes the current value on trn_rd // - the user is caught up and ready to receive the latest // data from the PCIe block always @(posedge user_clk) begin if(user_rst) begin m_axis_rx_tdata <= #TCQ {C_DATA_WIDTH{1'b0}}; end else begin if(!data_hold) begin // PREVIOUS state if(data_prev) begin m_axis_rx_tdata <= #TCQ trn_rd_prev; end // CURRENT state else begin m_axis_rx_tdata <= #TCQ trn_rd_DW_swapped; end end // else HOLD state end end // Logic to instruct pipeline to hold its value assign data_hold = (!m_axis_rx_tready && m_axis_rx_tvalid); // Logic to instruct pipeline to use previous bus values. Always use previous // value after holding a value. always @(posedge user_clk) begin if(user_rst) begin data_prev <= #TCQ 1'b0; end else begin data_prev <= #TCQ data_hold; end end //----------------------------------------------------------------------------// // Create TVALID, TLAST, tkeep, TUSER // // ----------------------------------- // // Use the same strategy for these signals as for TDATA, except here we need // // an extra provision for null packets. // //----------------------------------------------------------------------------// always @(posedge user_clk) begin if(user_rst) begin m_axis_rx_tvalid <= #TCQ 1'b0; reg_tlast <= #TCQ 1'b0; reg_tkeep <= #TCQ {KEEP_WIDTH{1'b1}}; m_axis_rx_tuser <= #TCQ 22'h0; end else begin if(!data_hold) begin // If in a null packet, use null generated value if(null_mux_sel) begin m_axis_rx_tvalid <= #TCQ null_rx_tvalid; reg_tlast <= #TCQ null_rx_tlast; reg_tkeep <= #TCQ null_rx_tkeep; m_axis_rx_tuser <= #TCQ {null_is_eof, 17'h0000}; end // PREVIOUS state else if(data_prev) begin m_axis_rx_tvalid <= #TCQ (trn_rsrc_rdy_prev || dsc_flag); reg_tlast <= #TCQ trn_reof_prev; reg_tkeep <= #TCQ tkeep_prev; m_axis_rx_tuser <= #TCQ {is_eof_prev, // TUSER bits [21:17] 2'b00, // TUSER bits [16:15] is_sof_prev, // TUSER bits [14:10] 1'b0, // TUSER bit [9] trn_rbar_hit_prev, // TUSER bits [8:2] trn_rerrfwd_prev, // TUSER bit [1] trn_recrc_err_prev}; // TUSER bit [0] end // CURRENT state else begin m_axis_rx_tvalid <= #TCQ (rsrc_rdy_filtered || dsc_flag); reg_tlast <= #TCQ trn_reof; reg_tkeep <= #TCQ tkeep; m_axis_rx_tuser <= #TCQ {is_eof, // TUSER bits [21:17] 2'b00, // TUSER bits [16:15] is_sof, // TUSER bits [14:10] 1'b0, // TUSER bit [9] trn_rbar_hit, // TUSER bits [8:2] trn_rerrfwd, // TUSER bit [1] trn_recrc_err}; // TUSER bit [0] end end // else HOLD state end end // Hook up TLAST and tkeep depending on interface width generate // For 128-bit interface, don't pass TLAST and tkeep to user (is_eof and // is_data passed to user instead). reg_tlast is still used internally. if(C_DATA_WIDTH == 128) begin : tlast_tkeep_hookup_128 assign m_axis_rx_tlast = 1'b0; assign m_axis_rx_tkeep = {KEEP_WIDTH{1'b1}}; end // For 64/32-bit interface, pass TLAST to user. else begin : tlast_tkeep_hookup_64_32 assign m_axis_rx_tlast = reg_tlast; assign m_axis_rx_tkeep = reg_tkeep; end endgenerate //----------------------------------------------------------------------------// // Create tkeep // // ------------ // // Convert RREM to STRB. Here, we are converting the encoding method for the // // location of the EOF from TRN flavor (rrem) to AXI (tkeep). // // // // NOTE: for each configuration, we need two values of tkeep, the current and // // previous values. The need for these two values is described below. // //----------------------------------------------------------------------------// generate if(C_DATA_WIDTH == 128) begin : rrem_to_tkeep_128 // TLAST and tkeep not used in 128-bit interface. is_sof and is_eof used // instead. assign tkeep = 16'h0000; assign tkeep_prev = 16'h0000; end else if(C_DATA_WIDTH == 64) begin : rrem_to_tkeep_64 // 64-bit interface: contains 2 DWORDs per cycle, for a total of 8 bytes // - tkeep has only two possible values here, 0xFF or 0x0F assign tkeep = trn_rrem ? 8'hFF : 8'h0F; assign tkeep_prev = trn_rrem_prev ? 8'hFF : 8'h0F; end else begin : rrem_to_tkeep_32 // 32-bit interface: contains 1 DWORD per cycle, for a total of 4 bytes // - tkeep is always 0xF in this case, due to the nature of the PCIe block assign tkeep = 4'hF; assign tkeep_prev = 4'hF; end endgenerate //----------------------------------------------------------------------------// // Create is_sof // // ------------- // // is_sof is a signal to the user indicating the location of SOF in TDATA . // // Due to inherent 64-bit alignment of packets from the block, the only // // possible values are: // // Value Valid data widths // // 5'b11000 (sof @ byte 8) 128 // // 5'b10000 (sof @ byte 0) 128, 64, 32 // // 5'b00000 (sof not present) 128, 64, 32 // //----------------------------------------------------------------------------// generate if(C_DATA_WIDTH == 128) begin : is_sof_128 assign is_sof = {(trn_rsof && !trn_rsrc_dsc), // bit 4: enable (trn_rsof && !trn_rrem[1]), // bit 3: sof @ byte 8? 3'b000}; // bit 2-0: hardwired 0 assign is_sof_prev = {(trn_rsof_prev && !trn_rsrc_dsc_prev), // bit 4 (trn_rsof_prev && !trn_rrem_prev[1]), // bit 3 3'b000}; // bit 2-0 end else begin : is_sof_64_32 assign is_sof = {(trn_rsof && !trn_rsrc_dsc), // bit 4: enable 4'b0000}; // bit 3-0: hardwired 0 assign is_sof_prev = {(trn_rsof_prev && !trn_rsrc_dsc_prev), // bit 4 4'b0000}; // bit 3-0 end endgenerate //----------------------------------------------------------------------------// // Create is_eof // // ------------- // // is_eof is a signal to the user indicating the location of EOF in TDATA . // // Due to DWORD granularity of packets from the block, the only // // possible values are: // // Value Valid data widths // // 5'b11111 (eof @ byte 15) 128 // // 5'b11011 (eof @ byte 11) 128 // // 5'b10111 (eof @ byte 7) 128, 64 // // 5'b10011 (eof @ byte 3)` 128, 64, 32 // // 5'b00011 (eof not present) 128, 64, 32 // //----------------------------------------------------------------------------// generate if(C_DATA_WIDTH == 128) begin : is_eof_128 assign is_eof = {trn_reof, // bit 4: enable trn_rrem, // bit 3-2: encoded eof loc rom block 2'b11}; // bit 1-0: hardwired 1 assign is_eof_prev = {trn_reof_prev, // bit 4: enable trn_rrem_prev, // bit 3-2: encoded eof loc from block 2'b11}; // bit 1-0: hardwired 1 end else if(C_DATA_WIDTH == 64) begin : is_eof_64 assign is_eof = {trn_reof, // bit 4: enable 1'b0, // bit 3: hardwired 0 trn_rrem, // bit 2: encoded eof loc from block 2'b11}; // bit 1-0: hardwired 1 assign is_eof_prev = {trn_reof_prev, // bit 4: enable 1'b0, // bit 3: hardwired 0 trn_rrem_prev, // bit 2: encoded eof loc from block 2'b11}; // bit 1-0: hardwired 1 end else begin : is_eof_32 assign is_eof = {trn_reof, // bit 4: enable 4'b0011}; // bit 3-0: hardwired to byte 3 assign is_eof_prev = {trn_reof_prev, // bit 4: enable 4'b0011}; // bit 3-0: hardwired to byte 3 end endgenerate //----------------------------------------------------------------------------// // Create trn_rdst_rdy // //----------------------------------------------------------------------------// always @(posedge user_clk) begin if(user_rst) begin trn_rdst_rdy <= #TCQ 1'b0; end else begin // If in a null packet, use null generated value if(null_mux_sel && m_axis_rx_tready) begin trn_rdst_rdy <= #TCQ null_rdst_rdy; end // If a discontinue needs to be serviced, throttle the block until we are // ready to pad out the packet. else if(dsc_flag) begin trn_rdst_rdy <= #TCQ 1'b0; end // If in a packet, pass user back-pressure directly to block else if(m_axis_rx_tvalid) begin trn_rdst_rdy <= #TCQ m_axis_rx_tready; end // If idle, default to no back-pressure. We need to default to the // "ready to accept data" state to make sure we catch the first // clock of data of a new packet. else begin trn_rdst_rdy <= #TCQ 1'b1; end end end //----------------------------------------------------------------------------// // Create null_mux_sel // // null_mux_sel is the signal used to detect a discontinue situation and // // mux in the null packet generated in rx_null_gen. Only mux in null data // // when not at the beginningof a packet. SOF discontinues do not require // // padding, as the whole packet is simply squashed instead. // //----------------------------------------------------------------------------// always @(posedge user_clk) begin if(user_rst) begin null_mux_sel <= #TCQ 1'b0; end else begin // NULL packet done if(null_mux_sel && null_rx_tlast && m_axis_rx_tready) begin null_mux_sel <= #TCQ 1'b0; end // Discontinue detected and we're in packet, so switch to NULL packet else if(dsc_flag && !data_hold) begin null_mux_sel <= #TCQ 1'b1; end end end //----------------------------------------------------------------------------// // Create discontinue tracking signals // //----------------------------------------------------------------------------// // Create signal trn_in_packet, which is needed to validate trn_rsrc_dsc. We // should ignore trn_rsrc_dsc when it's asserted out-of-packet. always @(posedge user_clk) begin if(user_rst) begin trn_in_packet <= #TCQ 1'b0; end else begin if(trn_rsof && !trn_reof && rsrc_rdy_filtered && trn_rdst_rdy) begin trn_in_packet <= #TCQ 1'b1; end else if(trn_rsrc_dsc) begin trn_in_packet <= #TCQ 1'b0; end else if(trn_reof && !trn_rsof && trn_rsrc_rdy && trn_rdst_rdy) begin trn_in_packet <= #TCQ 1'b0; end end end // Create dsc_flag, which identifies and stores mid-packet discontinues that // require null packet padding. This signal is edge sensitive to trn_rsrc_dsc, // to make sure we don't service the same dsc twice in the event that // trn_rsrc_dsc stays asserted for longer than it takes to pad out the packet. assign dsc_detect = trn_rsrc_dsc && !trn_rsrc_dsc_d && trn_in_packet && (!trn_rsof || trn_reof) && !(trn_rdst_rdy && trn_reof); always @(posedge user_clk) begin if(user_rst) begin reg_dsc_detect <= #TCQ 1'b0; trn_rsrc_dsc_d <= #TCQ 1'b0; end else begin if(dsc_detect) begin reg_dsc_detect <= #TCQ 1'b1; end else if(null_mux_sel) begin reg_dsc_detect <= #TCQ 1'b0; end trn_rsrc_dsc_d <= #TCQ trn_rsrc_dsc; end end assign dsc_flag = dsc_detect || reg_dsc_detect; //----------------------------------------------------------------------------// // Create np_counter (V6 128-bit only). This counter tells the V6 128-bit // // interface core how many NP packets have left the RX pipeline. The V6 // // 128-bit interface uses this count to perform rnp_ok modulation. // //----------------------------------------------------------------------------// generate if(C_FAMILY == "V6" && C_DATA_WIDTH == 128) begin : np_cntr_to_128_enabled reg [2:0] reg_np_counter; // Look for NP packets beginning on lower (i.e. unaligned) start wire mrd_lower = (!(|m_axis_rx_tdata[92:88]) && !m_axis_rx_tdata[94]); wire mrd_lk_lower = (m_axis_rx_tdata[92:88] == 5'b00001); wire io_rdwr_lower = (m_axis_rx_tdata[92:88] == 5'b00010); wire cfg_rdwr_lower = (m_axis_rx_tdata[92:89] == 4'b0010); wire atomic_lower = ((&m_axis_rx_tdata[91:90]) && m_axis_rx_tdata[94]); wire np_pkt_lower = (mrd_lower || mrd_lk_lower || io_rdwr_lower || cfg_rdwr_lower || atomic_lower) && m_axis_rx_tuser[13]; // Look for NP packets beginning on upper (i.e. aligned) start wire mrd_upper = (!(|m_axis_rx_tdata[28:24]) && !m_axis_rx_tdata[30]); wire mrd_lk_upper = (m_axis_rx_tdata[28:24] == 5'b00001); wire io_rdwr_upper = (m_axis_rx_tdata[28:24] == 5'b00010); wire cfg_rdwr_upper = (m_axis_rx_tdata[28:25] == 4'b0010); wire atomic_upper = ((&m_axis_rx_tdata[27:26]) && m_axis_rx_tdata[30]); wire np_pkt_upper = (mrd_upper || mrd_lk_upper || io_rdwr_upper || cfg_rdwr_upper || atomic_upper) && !m_axis_rx_tuser[13]; wire pkt_accepted = m_axis_rx_tuser[14] && m_axis_rx_tready && m_axis_rx_tvalid; // Increment counter whenever an NP packet leaves the RX pipeline always @(posedge user_clk) begin if (user_rst) begin reg_np_counter <= #TCQ 0; end else begin if((np_pkt_lower || np_pkt_upper) && pkt_accepted) begin reg_np_counter <= #TCQ reg_np_counter + 3'h1; end end end assign np_counter = reg_np_counter; end else begin : np_cntr_to_128_disabled assign np_counter = 3'h0; end endgenerate endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/axi_basic_top.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : axi_basic_top.v // Version : 2.4 //----------------------------------------------------------------------------// // File: axi_basic_top.v // // // // Description: // // TRN/AXI4-S Bridge top level module. Instantiates RX and TX modules. // // // // Notes: // // Optional notes section. // // // // Hierarchical: // // axi_basic_top // // // //----------------------------------------------------------------------------// `timescale 1ps/1ps module axi_basic_top #( parameter C_DATA_WIDTH = 128, // RX/TX interface data width parameter C_FAMILY = "X7", // Targeted FPGA family parameter C_ROOT_PORT = "FALSE", // PCIe block is in root port mode parameter C_PM_PRIORITY = "FALSE", // Disable TX packet boundary thrtl parameter TCQ = 1, // Clock to Q time // Do not override parameters below this line parameter REM_WIDTH = (C_DATA_WIDTH == 128) ? 2 : 1, // trem/rrem width parameter KEEP_WIDTH = C_DATA_WIDTH / 8 // KEEP width ) ( //---------------------------------------------// // User Design I/O // //---------------------------------------------// // AXI TX //----------- input [C_DATA_WIDTH-1:0] s_axis_tx_tdata, // TX data from user input s_axis_tx_tvalid, // TX data is valid output s_axis_tx_tready, // TX ready for data input [KEEP_WIDTH-1:0] s_axis_tx_tkeep, // TX strobe byte enables input s_axis_tx_tlast, // TX data is last input [3:0] s_axis_tx_tuser, // TX user signals // AXI RX //----------- output [C_DATA_WIDTH-1:0] m_axis_rx_tdata, // RX data to user output m_axis_rx_tvalid, // RX data is valid input m_axis_rx_tready, // RX ready for data output [KEEP_WIDTH-1:0] m_axis_rx_tkeep, // RX strobe byte enables output m_axis_rx_tlast, // RX data is last output [21:0] m_axis_rx_tuser, // RX user signals // User Misc. //----------- input user_turnoff_ok, // Turnoff OK from user input user_tcfg_gnt, // Send cfg OK from user //---------------------------------------------// // PCIe Block I/O // //---------------------------------------------// // TRN TX //----------- output [C_DATA_WIDTH-1:0] trn_td, // TX data from block output trn_tsof, // TX start of packet output trn_teof, // TX end of packet output trn_tsrc_rdy, // TX source ready input trn_tdst_rdy, // TX destination ready output trn_tsrc_dsc, // TX source discontinue output [REM_WIDTH-1:0] trn_trem, // TX remainder output trn_terrfwd, // TX error forward output trn_tstr, // TX streaming enable input [5:0] trn_tbuf_av, // TX buffers available output trn_tecrc_gen, // TX ECRC generate // TRN RX //----------- input [C_DATA_WIDTH-1:0] trn_rd, // RX data from block input trn_rsof, // RX start of packet input trn_reof, // RX end of packet input trn_rsrc_rdy, // RX source ready output trn_rdst_rdy, // RX destination ready input trn_rsrc_dsc, // RX source discontinue input [REM_WIDTH-1:0] trn_rrem, // RX remainder input trn_rerrfwd, // RX error forward input [6:0] trn_rbar_hit, // RX BAR hit input trn_recrc_err, // RX ECRC error // TRN Misc. //----------- input trn_tcfg_req, // TX config request output trn_tcfg_gnt, // RX config grant input trn_lnk_up, // PCIe link up // 7 Series/Virtex6 PM //----------- input [2:0] cfg_pcie_link_state, // Encoded PCIe link state // Virtex6 PM //----------- input cfg_pm_send_pme_to, // PM send PME turnoff msg input [1:0] cfg_pmcsr_powerstate, // PMCSR power state input [31:0] trn_rdllp_data, // RX DLLP data input trn_rdllp_src_rdy, // RX DLLP source ready // Virtex6/Spartan6 PM //----------- input cfg_to_turnoff, // Turnoff request output cfg_turnoff_ok, // Turnoff grant // System //----------- output [2:0] np_counter, // Non-posted counter input user_clk, // user clock from block input user_rst // user reset from block ); //---------------------------------------------// // RX Data Pipeline // //---------------------------------------------// axi_basic_rx #( .C_DATA_WIDTH( C_DATA_WIDTH ), .C_FAMILY( C_FAMILY ), .TCQ( TCQ ), .REM_WIDTH( REM_WIDTH ), .KEEP_WIDTH( KEEP_WIDTH ) ) rx_inst ( // Outgoing AXI TX //----------- .m_axis_rx_tdata( m_axis_rx_tdata ), .m_axis_rx_tvalid( m_axis_rx_tvalid ), .m_axis_rx_tready( m_axis_rx_tready ), .m_axis_rx_tkeep( m_axis_rx_tkeep ), .m_axis_rx_tlast( m_axis_rx_tlast ), .m_axis_rx_tuser( m_axis_rx_tuser ), // Incoming TRN RX //----------- .trn_rd( trn_rd ), .trn_rsof( trn_rsof ), .trn_reof( trn_reof ), .trn_rsrc_rdy( trn_rsrc_rdy ), .trn_rdst_rdy( trn_rdst_rdy ), .trn_rsrc_dsc( trn_rsrc_dsc ), .trn_rrem( trn_rrem ), .trn_rerrfwd( trn_rerrfwd ), .trn_rbar_hit( trn_rbar_hit ), .trn_recrc_err( trn_recrc_err ), // System //----------- .np_counter( np_counter ), .user_clk( user_clk ), .user_rst( user_rst ) ); //---------------------------------------------// // TX Data Pipeline // //---------------------------------------------// axi_basic_tx #( .C_DATA_WIDTH( C_DATA_WIDTH ), .C_FAMILY( C_FAMILY ), .C_ROOT_PORT( C_ROOT_PORT ), .C_PM_PRIORITY( C_PM_PRIORITY ), .TCQ( TCQ ), .REM_WIDTH( REM_WIDTH ), .KEEP_WIDTH( KEEP_WIDTH ) ) tx_inst ( // Incoming AXI RX //----------- .s_axis_tx_tdata( s_axis_tx_tdata ), .s_axis_tx_tvalid( s_axis_tx_tvalid ), .s_axis_tx_tready( s_axis_tx_tready ), .s_axis_tx_tkeep( s_axis_tx_tkeep ), .s_axis_tx_tlast( s_axis_tx_tlast ), .s_axis_tx_tuser( s_axis_tx_tuser ), // User Misc. //----------- .user_turnoff_ok( user_turnoff_ok ), .user_tcfg_gnt( user_tcfg_gnt ), // Outgoing TRN TX //----------- .trn_td( trn_td ), .trn_tsof( trn_tsof ), .trn_teof( trn_teof ), .trn_tsrc_rdy( trn_tsrc_rdy ), .trn_tdst_rdy( trn_tdst_rdy ), .trn_tsrc_dsc( trn_tsrc_dsc ), .trn_trem( trn_trem ), .trn_terrfwd( trn_terrfwd ), .trn_tstr( trn_tstr ), .trn_tbuf_av( trn_tbuf_av ), .trn_tecrc_gen( trn_tecrc_gen ), // TRN Misc. //----------- .trn_tcfg_req( trn_tcfg_req ), .trn_tcfg_gnt( trn_tcfg_gnt ), .trn_lnk_up( trn_lnk_up ), // 7 Series/Virtex6 PM //----------- .cfg_pcie_link_state( cfg_pcie_link_state ), // Virtex6 PM //----------- .cfg_pm_send_pme_to( cfg_pm_send_pme_to ), .cfg_pmcsr_powerstate( cfg_pmcsr_powerstate ), .trn_rdllp_data( trn_rdllp_data ), .trn_rdllp_src_rdy( trn_rdllp_src_rdy ), // Spartan6 PM //----------- .cfg_to_turnoff( cfg_to_turnoff ), .cfg_turnoff_ok( cfg_turnoff_ok ), // System //----------- .user_clk( user_clk ), .user_rst( user_rst ) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/axi_basic_tx.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : axi_basic_tx.v // Version : 2.4 //----------------------------------------------------------------------------// // File: axi_basic_tx.v // // // // Description: // // AXI to TRN TX module. Instantiates pipeline and throttle control TX // // submodules. // // // // Notes: // // Optional notes section. // // // // Hierarchical: // // axi_basic_top // // axi_basic_tx // // // //----------------------------------------------------------------------------// `timescale 1ps/1ps module axi_basic_tx #( parameter C_DATA_WIDTH = 128, // RX/TX interface data width parameter C_FAMILY = "X7", // Targeted FPGA family parameter C_ROOT_PORT = "FALSE", // PCIe block is in root port mode parameter C_PM_PRIORITY = "FALSE", // Disable TX packet boundary thrtl parameter TCQ = 1, // Clock to Q time // Do not override parameters below this line parameter REM_WIDTH = (C_DATA_WIDTH == 128) ? 2 : 1, // trem/rrem width parameter KEEP_WIDTH = C_DATA_WIDTH / 8 // KEEP width ) ( //---------------------------------------------// // User Design I/O // //---------------------------------------------// // AXI TX //----------- input [C_DATA_WIDTH-1:0] s_axis_tx_tdata, // TX data from user input s_axis_tx_tvalid, // TX data is valid output s_axis_tx_tready, // TX ready for data input [KEEP_WIDTH-1:0] s_axis_tx_tkeep, // TX strobe byte enables input s_axis_tx_tlast, // TX data is last input [3:0] s_axis_tx_tuser, // TX user signals // User Misc. //----------- input user_turnoff_ok, // Turnoff OK from user input user_tcfg_gnt, // Send cfg OK from user //---------------------------------------------// // PCIe Block I/O // //---------------------------------------------// // TRN TX //----------- output [C_DATA_WIDTH-1:0] trn_td, // TX data from block output trn_tsof, // TX start of packet output trn_teof, // TX end of packet output trn_tsrc_rdy, // TX source ready input trn_tdst_rdy, // TX destination ready output trn_tsrc_dsc, // TX source discontinue output [REM_WIDTH-1:0] trn_trem, // TX remainder output trn_terrfwd, // TX error forward output trn_tstr, // TX streaming enable input [5:0] trn_tbuf_av, // TX buffers available output trn_tecrc_gen, // TX ECRC generate // TRN Misc. //----------- input trn_tcfg_req, // TX config request output trn_tcfg_gnt, // RX config grant input trn_lnk_up, // PCIe link up // 7 Series/Virtex6 PM //----------- input [2:0] cfg_pcie_link_state, // Encoded PCIe link state // Virtex6 PM //----------- input cfg_pm_send_pme_to, // PM send PME turnoff msg input [1:0] cfg_pmcsr_powerstate, // PMCSR power state input [31:0] trn_rdllp_data, // RX DLLP data input trn_rdllp_src_rdy, // RX DLLP source ready // Virtex6/Spartan6 PM //----------- input cfg_to_turnoff, // Turnoff request output cfg_turnoff_ok, // Turnoff grant // System //----------- input user_clk, // user clock from block input user_rst // user reset from block ); wire tready_thrtl; //---------------------------------------------// // TX Data Pipeline // //---------------------------------------------// axi_basic_tx_pipeline #( .C_DATA_WIDTH( C_DATA_WIDTH ), .C_PM_PRIORITY( C_PM_PRIORITY ), .TCQ( TCQ ), .REM_WIDTH( REM_WIDTH ), .KEEP_WIDTH( KEEP_WIDTH ) ) tx_pipeline_inst ( // Incoming AXI RX //----------- .s_axis_tx_tdata( s_axis_tx_tdata ), .s_axis_tx_tready( s_axis_tx_tready ), .s_axis_tx_tvalid( s_axis_tx_tvalid ), .s_axis_tx_tkeep( s_axis_tx_tkeep ), .s_axis_tx_tlast( s_axis_tx_tlast ), .s_axis_tx_tuser( s_axis_tx_tuser ), // Outgoing TRN TX //----------- .trn_td( trn_td ), .trn_tsof( trn_tsof ), .trn_teof( trn_teof ), .trn_tsrc_rdy( trn_tsrc_rdy ), .trn_tdst_rdy( trn_tdst_rdy ), .trn_tsrc_dsc( trn_tsrc_dsc ), .trn_trem( trn_trem ), .trn_terrfwd( trn_terrfwd ), .trn_tstr( trn_tstr ), .trn_tecrc_gen( trn_tecrc_gen ), .trn_lnk_up( trn_lnk_up ), // System //----------- .tready_thrtl( tready_thrtl ), .user_clk( user_clk ), .user_rst( user_rst ) ); //---------------------------------------------// // TX Throttle Controller // //---------------------------------------------// generate if(C_PM_PRIORITY == "FALSE") begin : thrtl_ctl_enabled axi_basic_tx_thrtl_ctl #( .C_DATA_WIDTH( C_DATA_WIDTH ), .C_FAMILY( C_FAMILY ), .C_ROOT_PORT( C_ROOT_PORT ), .TCQ( TCQ ) ) tx_thrl_ctl_inst ( // Outgoing AXI TX //----------- .s_axis_tx_tdata( s_axis_tx_tdata ), .s_axis_tx_tvalid( s_axis_tx_tvalid ), .s_axis_tx_tuser( s_axis_tx_tuser ), .s_axis_tx_tlast( s_axis_tx_tlast ), // User Misc. //----------- .user_turnoff_ok( user_turnoff_ok ), .user_tcfg_gnt( user_tcfg_gnt ), // Incoming TRN RX //----------- .trn_tbuf_av( trn_tbuf_av ), .trn_tdst_rdy( trn_tdst_rdy ), // TRN Misc. //----------- .trn_tcfg_req( trn_tcfg_req ), .trn_tcfg_gnt( trn_tcfg_gnt ), .trn_lnk_up( trn_lnk_up ), // 7 Seriesq/Virtex6 PM //----------- .cfg_pcie_link_state( cfg_pcie_link_state ), // Virtex6 PM //----------- .cfg_pm_send_pme_to( cfg_pm_send_pme_to ), .cfg_pmcsr_powerstate( cfg_pmcsr_powerstate ), .trn_rdllp_data( trn_rdllp_data ), .trn_rdllp_src_rdy( trn_rdllp_src_rdy ), // Spartan6 PM //----------- .cfg_to_turnoff( cfg_to_turnoff ), .cfg_turnoff_ok( cfg_turnoff_ok ), // System //----------- .tready_thrtl( tready_thrtl ), .user_clk( user_clk ), .user_rst( user_rst ) ); end else begin : thrtl_ctl_disabled assign tready_thrtl = 1'b0; assign cfg_turnoff_ok = user_turnoff_ok; assign trn_tcfg_gnt = user_tcfg_gnt; end endgenerate endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/axi_basic_tx_pipeline.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : axi_basic_tx_pipeline.v // Version : 2.4 //----------------------------------------------------------------------------// // File: axi_basic_tx_pipeline.v // // // // Description: // // AXI to TRN TX pipeline. Converts transmitted data from AXI protocol to // // TRN. // // // // Notes: // // Optional notes section. // // // // Hierarchical: // // axi_basic_top // // axi_basic_tx // // axi_basic_tx_pipeline // // // //----------------------------------------------------------------------------// `timescale 1ps/1ps module axi_basic_tx_pipeline #( parameter C_DATA_WIDTH = 128, // RX/TX interface data width parameter C_PM_PRIORITY = "FALSE", // Disable TX packet boundary thrtl parameter TCQ = 1, // Clock to Q time // Do not override parameters below this line parameter REM_WIDTH = (C_DATA_WIDTH == 128) ? 2 : 1, // trem/rrem width parameter KEEP_WIDTH = C_DATA_WIDTH / 8 // KEEP width ) ( //---------------------------------------------// // User Design I/O // //---------------------------------------------// // AXI TX //----------- input [C_DATA_WIDTH-1:0] s_axis_tx_tdata, // TX data from user input s_axis_tx_tvalid, // TX data is valid output s_axis_tx_tready, // TX ready for data input [KEEP_WIDTH-1:0] s_axis_tx_tkeep, // TX strobe byte enables input s_axis_tx_tlast, // TX data is last input [3:0] s_axis_tx_tuser, // TX user signals //---------------------------------------------// // PCIe Block I/O // //---------------------------------------------// // TRN TX //----------- output [C_DATA_WIDTH-1:0] trn_td, // TX data from block output trn_tsof, // TX start of packet output trn_teof, // TX end of packet output trn_tsrc_rdy, // TX source ready input trn_tdst_rdy, // TX destination ready output trn_tsrc_dsc, // TX source discontinue output [REM_WIDTH-1:0] trn_trem, // TX remainder output trn_terrfwd, // TX error forward output trn_tstr, // TX streaming enable output trn_tecrc_gen, // TX ECRC generate input trn_lnk_up, // PCIe link up // System //----------- input tready_thrtl, // TREADY from thrtl ctl input user_clk, // user clock from block input user_rst // user reset from block ); // Input register stage reg [C_DATA_WIDTH-1:0] reg_tdata; reg reg_tvalid; reg [KEEP_WIDTH-1:0] reg_tkeep; reg [3:0] reg_tuser; reg reg_tlast; reg reg_tready; // Pipeline utility signals reg trn_in_packet; reg axi_in_packet; reg flush_axi; wire disable_trn; reg reg_disable_trn; wire axi_beat_live = s_axis_tx_tvalid && s_axis_tx_tready; wire axi_end_packet = axi_beat_live && s_axis_tx_tlast; //----------------------------------------------------------------------------// // Convert TRN data format to AXI data format. AXI is DWORD swapped from TRN. // // 128-bit: 64-bit: 32-bit: // // TRN DW0 maps to AXI DW3 TRN DW0 maps to AXI DW1 TNR DW0 maps to AXI DW0 // // TRN DW1 maps to AXI DW2 TRN DW1 maps to AXI DW0 // // TRN DW2 maps to AXI DW1 // // TRN DW3 maps to AXI DW0 // //----------------------------------------------------------------------------// generate if(C_DATA_WIDTH == 128) begin : td_DW_swap_128 assign trn_td = {reg_tdata[31:0], reg_tdata[63:32], reg_tdata[95:64], reg_tdata[127:96]}; end else if(C_DATA_WIDTH == 64) begin : td_DW_swap_64 assign trn_td = {reg_tdata[31:0], reg_tdata[63:32]}; end else begin : td_DW_swap_32 assign trn_td = reg_tdata; end endgenerate //----------------------------------------------------------------------------// // Create trn_tsof. If we're not currently in a packet and TVALID goes high, // // assert TSOF. // //----------------------------------------------------------------------------// assign trn_tsof = reg_tvalid && !trn_in_packet; //----------------------------------------------------------------------------// // Create trn_in_packet. This signal tracks if the TRN interface is currently // // in the middle of a packet, which is needed to generate trn_tsof // //----------------------------------------------------------------------------// always @(posedge user_clk) begin if(user_rst) begin trn_in_packet <= #TCQ 1'b0; end else begin if(trn_tsof && trn_tsrc_rdy && trn_tdst_rdy && !trn_teof) begin trn_in_packet <= #TCQ 1'b1; end else if((trn_in_packet && trn_teof && trn_tsrc_rdy) || !trn_lnk_up) begin trn_in_packet <= #TCQ 1'b0; end end end //----------------------------------------------------------------------------// // Create axi_in_packet. This signal tracks if the AXI interface is currently // // in the middle of a packet, which is needed in case the link goes down. // //----------------------------------------------------------------------------// always @(posedge user_clk) begin if(user_rst) begin axi_in_packet <= #TCQ 1'b0; end else begin if(axi_beat_live && !s_axis_tx_tlast) begin axi_in_packet <= #TCQ 1'b1; end else if(axi_beat_live) begin axi_in_packet <= #TCQ 1'b0; end end end //----------------------------------------------------------------------------// // Create disable_trn. This signal asserts when the link goes down and // // triggers the deassertiong of trn_tsrc_rdy. The deassertion of disable_trn // // depends on C_PM_PRIORITY, as described below. // //----------------------------------------------------------------------------// generate // In the C_PM_PRIORITY pipeline, we disable the TRN interfacefrom the time // the link goes down until the the AXI interface is ready to accept packets // again (via assertion of TREADY). By waiting for TREADY, we allow the // previous value buffer to fill, so we're ready for any throttling by the // user or the block. if(C_PM_PRIORITY == "TRUE") begin : pm_priority_trn_flush always @(posedge user_clk) begin if(user_rst) begin reg_disable_trn <= #TCQ 1'b1; end else begin // When the link goes down, disable the TRN interface. if(!trn_lnk_up) begin reg_disable_trn <= #TCQ 1'b1; end // When the link comes back up and the AXI interface is ready, we can // release the pipeline and return to normal operation. else if(!flush_axi && s_axis_tx_tready) begin reg_disable_trn <= #TCQ 1'b0; end end end assign disable_trn = reg_disable_trn; end // In the throttle-controlled pipeline, we don't have a previous value buffer. // The throttle control mechanism handles TREADY, so all we need to do is // detect when the link goes down and disable the TRN interface until the link // comes back up and the AXI interface is finished flushing any packets. else begin : thrtl_ctl_trn_flush always @(posedge user_clk) begin if(user_rst) begin reg_disable_trn <= #TCQ 1'b0; end else begin // If the link is down and AXI is in packet, disable TRN and look for // the end of the packet if(axi_in_packet && !trn_lnk_up && !axi_end_packet) begin reg_disable_trn <= #TCQ 1'b1; end // AXI packet is ending, so we're done flushing else if(axi_end_packet) begin reg_disable_trn <= #TCQ 1'b0; end end end // Disable the TRN interface if link is down or we're still flushing the AXI // interface. assign disable_trn = reg_disable_trn || !trn_lnk_up; end endgenerate //----------------------------------------------------------------------------// // Convert STRB to RREM. Here, we are converting the encoding method for the // // location of the EOF from AXI (tkeep) to TRN flavor (rrem). // //----------------------------------------------------------------------------// generate if(C_DATA_WIDTH == 128) begin : tkeep_to_trem_128 //---------------------------------------// // Conversion table: // // trem | tkeep // // [1] [0] | [15:12] [11:8] [7:4] [3:0] // // ------------------------------------- // // 1 1 | D3 D2 D1 D0 // // 1 0 | -- D2 D1 D0 // // 0 1 | -- -- D1 D0 // // 0 0 | -- -- -- D0 // //---------------------------------------// wire axi_DW_1 = reg_tkeep[7]; wire axi_DW_2 = reg_tkeep[11]; wire axi_DW_3 = reg_tkeep[15]; assign trn_trem[1] = axi_DW_2; assign trn_trem[0] = axi_DW_3 || (axi_DW_1 && !axi_DW_2); end else if(C_DATA_WIDTH == 64) begin : tkeep_to_trem_64 assign trn_trem = reg_tkeep[7]; end else begin : tkeep_to_trem_32 assign trn_trem = 1'b0; end endgenerate //----------------------------------------------------------------------------// // Create remaining TRN signals // //----------------------------------------------------------------------------// assign trn_teof = reg_tlast; assign trn_tecrc_gen = reg_tuser[0]; assign trn_terrfwd = reg_tuser[1]; assign trn_tstr = reg_tuser[2]; assign trn_tsrc_dsc = reg_tuser[3]; //----------------------------------------------------------------------------// // Pipeline stage // //----------------------------------------------------------------------------// // We need one of two approaches for the pipeline stage depending on the // C_PM_PRIORITY parameter. generate reg reg_tsrc_rdy; // If set to FALSE, that means the user wants to use the TX packet boundary // throttling feature. Since all Block throttling will now be predicted, we // can use a simple straight-through pipeline. if(C_PM_PRIORITY == "FALSE") begin : throttle_ctl_pipeline always @(posedge user_clk) begin if(user_rst) begin reg_tdata <= #TCQ {C_DATA_WIDTH{1'b0}}; reg_tvalid <= #TCQ 1'b0; reg_tkeep <= #TCQ {KEEP_WIDTH{1'b0}}; reg_tlast <= #TCQ 1'b0; reg_tuser <= #TCQ 4'h0; reg_tsrc_rdy <= #TCQ 1'b0; end else begin reg_tdata <= #TCQ s_axis_tx_tdata; reg_tvalid <= #TCQ s_axis_tx_tvalid; reg_tkeep <= #TCQ s_axis_tx_tkeep; reg_tlast <= #TCQ s_axis_tx_tlast; reg_tuser <= #TCQ s_axis_tx_tuser; // Hold trn_tsrc_rdy low when flushing a packet. reg_tsrc_rdy <= #TCQ axi_beat_live && !disable_trn; end end assign trn_tsrc_rdy = reg_tsrc_rdy; // With TX packet boundary throttling, TREADY is pipelined in // axi_basic_tx_thrtl_ctl and wired through here. assign s_axis_tx_tready = tready_thrtl; end //**************************************************************************// // If C_PM_PRIORITY is set to TRUE, that means the user prefers to have all PM // functionality intact isntead of TX packet boundary throttling. Now the // Block could back-pressure at any time, which creates the standard problem // of potential data loss due to the handshaking latency. Here we need a // previous value buffer, just like the RX data path. else begin : pm_prioity_pipeline reg [C_DATA_WIDTH-1:0] tdata_prev; reg tvalid_prev; reg [KEEP_WIDTH-1:0] tkeep_prev; reg tlast_prev; reg [3:0] tuser_prev; reg reg_tdst_rdy; wire data_hold; reg data_prev; //------------------------------------------------------------------------// // Previous value buffer // // --------------------- // // We are inserting a pipeline stage in between AXI and TRN, which causes // // some issues with handshaking signals trn_tsrc_rdy/s_axis_tx_tready. // // The added cycle of latency in the path causes the Block to fall behind // // the AXI interface whenever it throttles. // // // // To avoid loss of data, we must keep the previous value of all // // s_axis_tx_* signals in case the Block throttles. // //------------------------------------------------------------------------// always @(posedge user_clk) begin if(user_rst) begin tdata_prev <= #TCQ {C_DATA_WIDTH{1'b0}}; tvalid_prev <= #TCQ 1'b0; tkeep_prev <= #TCQ {KEEP_WIDTH{1'b0}}; tlast_prev <= #TCQ 1'b0; tuser_prev <= #TCQ 4'h 0; end else begin // prev buffer works by checking s_axis_tx_tready. When // s_axis_tx_tready is asserted, a new value is present on the // interface. if(!s_axis_tx_tready) begin tdata_prev <= #TCQ tdata_prev; tvalid_prev <= #TCQ tvalid_prev; tkeep_prev <= #TCQ tkeep_prev; tlast_prev <= #TCQ tlast_prev; tuser_prev <= #TCQ tuser_prev; end else begin tdata_prev <= #TCQ s_axis_tx_tdata; tvalid_prev <= #TCQ s_axis_tx_tvalid; tkeep_prev <= #TCQ s_axis_tx_tkeep; tlast_prev <= #TCQ s_axis_tx_tlast; tuser_prev <= #TCQ s_axis_tx_tuser; end end end // Create special buffer which locks in the proper value of TDATA depending // on whether the user is throttling or not. This buffer has three states: // // HOLD state: TDATA maintains its current value // - the Block has throttled the PCIe block // PREVIOUS state: the buffer provides the previous value on TDATA // - the Block has finished throttling, and is a little // behind the user // CURRENT state: the buffer passes the current value on TDATA // - the Block is caught up and ready to receive the // latest data from the user always @(posedge user_clk) begin if(user_rst) begin reg_tdata <= #TCQ {C_DATA_WIDTH{1'b0}}; reg_tvalid <= #TCQ 1'b0; reg_tkeep <= #TCQ {KEEP_WIDTH{1'b0}}; reg_tlast <= #TCQ 1'b0; reg_tuser <= #TCQ 4'h0; reg_tdst_rdy <= #TCQ 1'b0; end else begin reg_tdst_rdy <= #TCQ trn_tdst_rdy; if(!data_hold) begin // PREVIOUS state if(data_prev) begin reg_tdata <= #TCQ tdata_prev; reg_tvalid <= #TCQ tvalid_prev; reg_tkeep <= #TCQ tkeep_prev; reg_tlast <= #TCQ tlast_prev; reg_tuser <= #TCQ tuser_prev; end // CURRENT state else begin reg_tdata <= #TCQ s_axis_tx_tdata; reg_tvalid <= #TCQ s_axis_tx_tvalid; reg_tkeep <= #TCQ s_axis_tx_tkeep; reg_tlast <= #TCQ s_axis_tx_tlast; reg_tuser <= #TCQ s_axis_tx_tuser; end end // else HOLD state end end // Logic to instruct pipeline to hold its value assign data_hold = trn_tsrc_rdy && !trn_tdst_rdy; // Logic to instruct pipeline to use previous bus values. Always use // previous value after holding a value. always @(posedge user_clk) begin if(user_rst) begin data_prev <= #TCQ 1'b0; end else begin data_prev <= #TCQ data_hold; end end //------------------------------------------------------------------------// // Create trn_tsrc_rdy. If we're flushing the TRN hold trn_tsrc_rdy low. // //------------------------------------------------------------------------// assign trn_tsrc_rdy = reg_tvalid && !disable_trn; //------------------------------------------------------------------------// // Create TREADY // //------------------------------------------------------------------------// always @(posedge user_clk) begin if(user_rst) begin reg_tready <= #TCQ 1'b0; end else begin // If the link went down and we need to flush a packet in flight, hold // TREADY high if(flush_axi && !axi_end_packet) begin reg_tready <= #TCQ 1'b1; end // If the link is up, TREADY is as follows: // TREADY = 1 when trn_tsrc_rdy == 0 // - While idle, keep the pipeline primed and ready for the next // packet // // TREADY = trn_tdst_rdy when trn_tsrc_rdy == 1 // - While in packet, throttle pipeline based on state of TRN else if(trn_lnk_up) begin reg_tready <= #TCQ trn_tdst_rdy || !trn_tsrc_rdy; end // If the link is down and we're not flushing a packet, hold TREADY low // wait for link to come back up else begin reg_tready <= #TCQ 1'b0; end end end assign s_axis_tx_tready = reg_tready; end //--------------------------------------------------------------------------// // Create flush_axi. This signal detects if the link goes down while the // // AXI interface is in packet. In this situation, we need to flush the // // packet through the AXI interface and discard it. // //--------------------------------------------------------------------------// always @(posedge user_clk) begin if(user_rst) begin flush_axi <= #TCQ 1'b0; end else begin // If the AXI interface is in packet and the link goes down, purge it. if(axi_in_packet && !trn_lnk_up && !axi_end_packet) begin flush_axi <= #TCQ 1'b1; end // The packet is finished, so we're done flushing. else if(axi_end_packet) begin flush_axi <= #TCQ 1'b0; end end end endgenerate endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/axi_basic_tx_thrtl_ctl.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : axi_basic_tx_thrtl_ctl.v // Version : 2.4 //----------------------------------------------------------------------------// // File: axi_basic_tx_thrtl_ctl.v // // // // Description: // // TX throttle controller. Anticipates back-pressure from PCIe block and // // preemptively back-pressures user design (packet boundary throttling). // // // // Notes: // // Optional notes section. // // // // Hierarchical: // // axi_basic_top // // axi_basic_tx // // axi_basic_tx_thrtl_ctl // // // //----------------------------------------------------------------------------// `timescale 1ps/1ps module axi_basic_tx_thrtl_ctl #( parameter C_DATA_WIDTH = 128, // RX/TX interface data width parameter C_FAMILY = "X7", // Targeted FPGA family parameter C_ROOT_PORT = "FALSE", // PCIe block is in root port mode parameter TCQ = 1 // Clock to Q time ) ( // AXI TX //----------- input [C_DATA_WIDTH-1:0] s_axis_tx_tdata, // TX data from user input s_axis_tx_tvalid, // TX data is valid input [3:0] s_axis_tx_tuser, // TX user signals input s_axis_tx_tlast, // TX data is last // User Misc. //----------- input user_turnoff_ok, // Turnoff OK from user input user_tcfg_gnt, // Send cfg OK from user // TRN TX //----------- input [5:0] trn_tbuf_av, // TX buffers available input trn_tdst_rdy, // TX destination ready // TRN Misc. //----------- input trn_tcfg_req, // TX config request output trn_tcfg_gnt, // TX config grant input trn_lnk_up, // PCIe link up // 7 Series/Virtex6 PM //----------- input [2:0] cfg_pcie_link_state, // Encoded PCIe link state // Virtex6 PM //----------- input cfg_pm_send_pme_to, // PM send PME turnoff msg input [1:0] cfg_pmcsr_powerstate, // PMCSR power state input [31:0] trn_rdllp_data, // RX DLLP data input trn_rdllp_src_rdy, // RX DLLP source ready // Virtex6/Spartan6 PM //----------- input cfg_to_turnoff, // Turnoff request output reg cfg_turnoff_ok, // Turnoff grant // System //----------- output reg tready_thrtl, // TREADY to pipeline input user_clk, // user clock from block input user_rst // user reset from block ); // Thrtl user when TBUF hits this val localparam TBUF_AV_MIN = (C_DATA_WIDTH == 128) ? 5 : (C_DATA_WIDTH == 64) ? 1 : 0; // Pause user when TBUF hits this val localparam TBUF_AV_GAP = TBUF_AV_MIN + 1; // GAP pause time - the latency from the time a packet is accepted on the TRN // interface to the time trn_tbuf_av from the Block will decrement. localparam TBUF_GAP_TIME = (C_DATA_WIDTH == 128) ? 4 : 1; // Latency time from when tcfg_gnt is asserted to when PCIe block will throttle localparam TCFG_LATENCY_TIME = 2'd2; // Number of pipeline stages to delay trn_tcfg_gnt. For V6 128-bit only localparam TCFG_GNT_PIPE_STAGES = 3; // Throttle condition registers and constants reg lnk_up_thrtl; wire lnk_up_trig; wire lnk_up_exit; reg tbuf_av_min_thrtl; wire tbuf_av_min_trig; reg tbuf_av_gap_thrtl; reg [2:0] tbuf_gap_cnt; wire tbuf_av_gap_trig; wire tbuf_av_gap_exit; wire gap_trig_tlast; wire gap_trig_decr; reg [5:0] tbuf_av_d; reg tcfg_req_thrtl; reg [1:0] tcfg_req_cnt; reg trn_tdst_rdy_d; wire tcfg_req_trig; wire tcfg_req_exit; reg tcfg_gnt_log; wire pre_throttle; wire reg_throttle; wire exit_crit; reg reg_tcfg_gnt; reg trn_tcfg_req_d; reg tcfg_gnt_pending; wire wire_to_turnoff; reg reg_turnoff_ok; reg tready_thrtl_mux; localparam LINKSTATE_L0 = 3'b000; localparam LINKSTATE_PPM_L1 = 3'b001; localparam LINKSTATE_PPM_L1_TRANS = 3'b101; localparam LINKSTATE_PPM_L23R_TRANS = 3'b110; localparam PM_ENTER_L1 = 8'h20; localparam POWERSTATE_D0 = 2'b00; reg ppm_L1_thrtl; wire ppm_L1_trig; wire ppm_L1_exit; reg [2:0] cfg_pcie_link_state_d; reg trn_rdllp_src_rdy_d; reg ppm_L23_thrtl; wire ppm_L23_trig; reg cfg_turnoff_ok_pending; reg reg_tlast; // Throttle control state machine states and registers localparam IDLE = 0; localparam THROTTLE = 1; reg cur_state; reg next_state; reg reg_axi_in_pkt; wire axi_in_pkt; wire axi_pkt_ending; wire axi_throttled; wire axi_thrtl_ok; wire tx_ecrc_pause; //----------------------------------------------------------------------------// // THROTTLE REASON: PCIe link is down // // - When to throttle: trn_lnk_up deasserted // // - When to stop: trn_tdst_rdy assesrted // //----------------------------------------------------------------------------// assign lnk_up_trig = !trn_lnk_up; assign lnk_up_exit = trn_tdst_rdy; always @(posedge user_clk) begin if(user_rst) begin lnk_up_thrtl <= #TCQ 1'b1; end else begin if(lnk_up_trig) begin lnk_up_thrtl <= #TCQ 1'b1; end else if(lnk_up_exit) begin lnk_up_thrtl <= #TCQ 1'b0; end end end //----------------------------------------------------------------------------// // THROTTLE REASON: Transmit buffers depleted // // - When to throttle: trn_tbuf_av falls to 0 // // - When to stop: trn_tbuf_av rises above 0 again // //----------------------------------------------------------------------------// assign tbuf_av_min_trig = (trn_tbuf_av <= TBUF_AV_MIN); always @(posedge user_clk) begin if(user_rst) begin tbuf_av_min_thrtl <= #TCQ 1'b0; end else begin if(tbuf_av_min_trig) begin tbuf_av_min_thrtl <= #TCQ 1'b1; end // The exit condition for tbuf_av_min_thrtl is !tbuf_av_min_trig else begin tbuf_av_min_thrtl <= #TCQ 1'b0; end end end //----------------------------------------------------------------------------// // THROTTLE REASON: Transmit buffers getting low // // - When to throttle: trn_tbuf_av falls below "gap" threshold TBUF_AV_GAP // // - When to stop: after TBUF_GAP_TIME cycles elapse // // // // If we're about to run out of transmit buffers, throttle the user for a // // few clock cycles to give the PCIe block time to catch up. This is // // needed to compensate for latency in decrementing trn_tbuf_av in the PCIe // // Block transmit path. // //----------------------------------------------------------------------------// // Detect two different scenarios for buffers getting low: // 1) If we see a TLAST. a new packet has been inserted into the buffer, and // we need to pause and let that packet "soak in" assign gap_trig_tlast = (trn_tbuf_av <= TBUF_AV_GAP) && s_axis_tx_tvalid && tready_thrtl && s_axis_tx_tlast; // 2) Any time tbug_avail decrements to the TBUF_AV_GAP threshold, we need to // pause and make sure no other packets are about to soak in and cause the // buffer availability to drop further. assign gap_trig_decr = (trn_tbuf_av == (TBUF_AV_GAP)) && (tbuf_av_d == (TBUF_AV_GAP+1)); assign gap_trig_tcfg = (tcfg_req_thrtl && tcfg_req_exit); assign tbuf_av_gap_trig = gap_trig_tlast || gap_trig_decr || gap_trig_tcfg; assign tbuf_av_gap_exit = (tbuf_gap_cnt == 0); always @(posedge user_clk) begin if(user_rst) begin tbuf_av_gap_thrtl <= #TCQ 1'b0; tbuf_gap_cnt <= #TCQ 3'h0; tbuf_av_d <= #TCQ 6'h00; end else begin if(tbuf_av_gap_trig) begin tbuf_av_gap_thrtl <= #TCQ 1'b1; end else if(tbuf_av_gap_exit) begin tbuf_av_gap_thrtl <= #TCQ 1'b0; end // tbuf gap counter: // This logic controls the length of the throttle condition when tbufs are // getting low. if(tbuf_av_gap_thrtl && (cur_state == THROTTLE)) begin if(tbuf_gap_cnt > 0) begin tbuf_gap_cnt <= #TCQ tbuf_gap_cnt - 3'd1; end end else begin tbuf_gap_cnt <= #TCQ TBUF_GAP_TIME; end tbuf_av_d <= #TCQ trn_tbuf_av; end end //----------------------------------------------------------------------------// // THROTTLE REASON: Block needs to send a CFG response // // - When to throttle: trn_tcfg_req and user_tcfg_gnt asserted // // - When to stop: after trn_tdst_rdy transitions to unasserted // // // // If the block needs to send a response to a CFG packet, this will cause // // the subsequent deassertion of trn_tdst_rdy. When the user design permits, // // grant permission to the block to service request and throttle the user. // //----------------------------------------------------------------------------// assign tcfg_req_trig = trn_tcfg_req && reg_tcfg_gnt; assign tcfg_req_exit = (tcfg_req_cnt == 2'd0) && !trn_tdst_rdy_d && trn_tdst_rdy; always @(posedge user_clk) begin if(user_rst) begin tcfg_req_thrtl <= #TCQ 1'b0; trn_tcfg_req_d <= #TCQ 1'b0; trn_tdst_rdy_d <= #TCQ 1'b1; reg_tcfg_gnt <= #TCQ 1'b0; tcfg_req_cnt <= #TCQ 2'd0; tcfg_gnt_pending <= #TCQ 1'b0; end else begin if(tcfg_req_trig) begin tcfg_req_thrtl <= #TCQ 1'b1; end else if(tcfg_req_exit) begin tcfg_req_thrtl <= #TCQ 1'b0; end // We need to wait the appropriate amount of time for the tcfg_gnt to // "sink in" to the PCIe block. After that, we know that the PCIe block will // not reassert trn_tdst_rdy until the CFG request has been serviced. If a // new request is being service (tcfg_gnt_log == 1), then reset the timer. if((trn_tcfg_req && !trn_tcfg_req_d) || tcfg_gnt_pending) begin tcfg_req_cnt <= #TCQ TCFG_LATENCY_TIME; end else begin if(tcfg_req_cnt > 0) begin tcfg_req_cnt <= #TCQ tcfg_req_cnt - 2'd1; end end // Make sure tcfg_gnt_log pulses once for one clock cycle for every // cfg packet request. if(trn_tcfg_req && !trn_tcfg_req_d) begin tcfg_gnt_pending <= #TCQ 1'b1; end else if(tcfg_gnt_log) begin tcfg_gnt_pending <= #TCQ 1'b0; end trn_tcfg_req_d <= #TCQ trn_tcfg_req; trn_tdst_rdy_d <= #TCQ trn_tdst_rdy; reg_tcfg_gnt <= #TCQ user_tcfg_gnt; end end //----------------------------------------------------------------------------// // THROTTLE REASON: Block needs to transition to low power state PPM L1 // // - When to throttle: appropriate low power state signal asserted // // (architecture dependent) // // - When to stop: cfg_pcie_link_state goes to proper value (C_ROOT_PORT // // dependent) // // // // If the block needs to transition to PM state PPM L1, we need to finish // // up what we're doing and throttle immediately. // //----------------------------------------------------------------------------// generate // PPM L1 signals for 7 Series in RC mode if((C_FAMILY == "X7") && (C_ROOT_PORT == "TRUE")) begin : x7_L1_thrtl_rp assign ppm_L1_trig = (cfg_pcie_link_state_d == LINKSTATE_L0) && (cfg_pcie_link_state == LINKSTATE_PPM_L1_TRANS); assign ppm_L1_exit = cfg_pcie_link_state == LINKSTATE_PPM_L1; end // PPM L1 signals for 7 Series in EP mode else if((C_FAMILY == "X7") && (C_ROOT_PORT == "FALSE")) begin : x7_L1_thrtl_ep assign ppm_L1_trig = (cfg_pcie_link_state_d == LINKSTATE_L0) && (cfg_pcie_link_state == LINKSTATE_PPM_L1_TRANS); assign ppm_L1_exit = cfg_pcie_link_state == LINKSTATE_L0; end // PPM L1 signals for V6 in RC mode else if((C_FAMILY == "V6") && (C_ROOT_PORT == "TRUE")) begin : v6_L1_thrtl_rp assign ppm_L1_trig = (trn_rdllp_data[31:24] == PM_ENTER_L1) && trn_rdllp_src_rdy && !trn_rdllp_src_rdy_d; assign ppm_L1_exit = cfg_pcie_link_state == LINKSTATE_PPM_L1; end // PPM L1 signals for V6 in EP mode else if((C_FAMILY == "V6") && (C_ROOT_PORT == "FALSE")) begin : v6_L1_thrtl_ep assign ppm_L1_trig = (cfg_pmcsr_powerstate != POWERSTATE_D0); assign ppm_L1_exit = cfg_pcie_link_state == LINKSTATE_L0; end // PPM L1 detection not supported for S6 else begin : s6_L1_thrtl assign ppm_L1_trig = 1'b0; assign ppm_L1_exit = 1'b1; end endgenerate always @(posedge user_clk) begin if(user_rst) begin ppm_L1_thrtl <= #TCQ 1'b0; cfg_pcie_link_state_d <= #TCQ 3'b0; trn_rdllp_src_rdy_d <= #TCQ 1'b0; end else begin if(ppm_L1_trig) begin ppm_L1_thrtl <= #TCQ 1'b1; end else if(ppm_L1_exit) begin ppm_L1_thrtl <= #TCQ 1'b0; end cfg_pcie_link_state_d <= #TCQ cfg_pcie_link_state; trn_rdllp_src_rdy_d <= #TCQ trn_rdllp_src_rdy; end end //----------------------------------------------------------------------------// // THROTTLE REASON: Block needs to transition to low power state PPM L2/3 // // - When to throttle: appropriate PM signal indicates a transition to // // L2/3 is pending or in progress (family and role dependent) // // - When to stop: never (the only path out of L2/3 is a full reset) // // // // If the block needs to transition to PM state PPM L2/3, we need to finish // // up what we're doing and throttle when the user gives permission. // //----------------------------------------------------------------------------// generate // PPM L2/3 signals for 7 Series in RC mode if((C_FAMILY == "X7") && (C_ROOT_PORT == "TRUE")) begin : x7_L23_thrtl_rp assign ppm_L23_trig = (cfg_pcie_link_state_d == LINKSTATE_PPM_L23R_TRANS); assign wire_to_turnoff = 1'b0; end // PPM L2/3 signals for V6 in RC mode else if((C_FAMILY == "V6") && (C_ROOT_PORT == "TRUE")) begin : v6_L23_thrtl_rp assign ppm_L23_trig = cfg_pm_send_pme_to; assign wire_to_turnoff = 1'b0; end // PPM L2/3 signals in EP mode else begin : L23_thrtl_ep assign ppm_L23_trig = wire_to_turnoff && reg_turnoff_ok; // PPM L2/3 signals for 7 Series in EP mode // For 7 Series, cfg_to_turnoff pulses once when a turnoff request is // outstanding, so we need a "sticky" register that grabs the request. if(C_FAMILY == "X7") begin : x7_L23_thrtl_ep reg reg_to_turnoff; always @(posedge user_clk) begin if(user_rst) begin reg_to_turnoff <= #TCQ 1'b0; end else begin if(cfg_to_turnoff) begin reg_to_turnoff <= #TCQ 1'b1; end end end assign wire_to_turnoff = reg_to_turnoff; end // PPM L2/3 signals for V6/S6 in EP mode // In V6 and S6, the to_turnoff signal asserts and remains asserted until // turnoff_ok is asserted, so a sticky reg is not necessary. else begin : v6_s6_L23_thrtl_ep assign wire_to_turnoff = cfg_to_turnoff; end always @(posedge user_clk) begin if(user_rst) begin reg_turnoff_ok <= #TCQ 1'b0; end else begin reg_turnoff_ok <= #TCQ user_turnoff_ok; end end end endgenerate always @(posedge user_clk) begin if(user_rst) begin ppm_L23_thrtl <= #TCQ 1'b0; cfg_turnoff_ok_pending <= #TCQ 1'b0; end else begin if(ppm_L23_trig) begin ppm_L23_thrtl <= #TCQ 1'b1; end // Make sure cfg_turnoff_ok pulses once for one clock cycle for every // turnoff request. if(ppm_L23_trig && !ppm_L23_thrtl) begin cfg_turnoff_ok_pending <= #TCQ 1'b1; end else if(cfg_turnoff_ok) begin cfg_turnoff_ok_pending <= #TCQ 1'b0; end end end //----------------------------------------------------------------------------// // Create axi_thrtl_ok. This signal determines if it's OK to throttle the // // user design on the AXI interface. Since TREADY is registered, this signal // // needs to assert on the cycle ~before~ we actually intend to throttle. // // The only time it's OK to throttle when TVALID is asserted is on the first // // beat of a new packet. Therefore, assert axi_thrtl_ok if one of the // // is true: // // 1) The user is not in a packet and is not starting one // // 2) The user is just finishing a packet // // 3) We're already throttled, so it's OK to continue throttling // //----------------------------------------------------------------------------// always @(posedge user_clk) begin if(user_rst) begin reg_axi_in_pkt <= #TCQ 1'b0; end else begin if(s_axis_tx_tvalid && s_axis_tx_tlast) begin reg_axi_in_pkt <= #TCQ 1'b0; end else if(tready_thrtl && s_axis_tx_tvalid) begin reg_axi_in_pkt <= #TCQ 1'b1; end end end assign axi_in_pkt = s_axis_tx_tvalid || reg_axi_in_pkt; assign axi_pkt_ending = s_axis_tx_tvalid && s_axis_tx_tlast; assign axi_throttled = !tready_thrtl; assign axi_thrtl_ok = !axi_in_pkt || axi_pkt_ending || axi_throttled; //----------------------------------------------------------------------------// // Throttle CTL State Machine: // // Throttle user design when a throttle trigger (or triggers) occur. // // Keep user throttled until all exit criteria have been met. // //----------------------------------------------------------------------------// // Immediate throttle signal. Used to "pounce" on a throttle opportunity when // we're seeking one assign pre_throttle = tbuf_av_min_trig || tbuf_av_gap_trig || lnk_up_trig || tcfg_req_trig || ppm_L1_trig || ppm_L23_trig; // Registered throttle signals. Used to control throttle state machine assign reg_throttle = tbuf_av_min_thrtl || tbuf_av_gap_thrtl || lnk_up_thrtl || tcfg_req_thrtl || ppm_L1_thrtl || ppm_L23_thrtl; assign exit_crit = !tbuf_av_min_thrtl && !tbuf_av_gap_thrtl && !lnk_up_thrtl && !tcfg_req_thrtl && !ppm_L1_thrtl && !ppm_L23_thrtl; always @(*) begin case(cur_state) // IDLE: in this state we're waiting for a trigger event to occur. As // soon as an event occurs and the user isn't transmitting a packet, we // throttle the PCIe block and the user and next state is THROTTLE. IDLE: begin if(reg_throttle && axi_thrtl_ok) begin // Throttle user tready_thrtl_mux = 1'b0; next_state = THROTTLE; // Assert appropriate grant signal depending on the throttle type. if(tcfg_req_thrtl) begin tcfg_gnt_log = 1'b1; // For cfg request, grant the request cfg_turnoff_ok = 1'b0; // end else if(ppm_L23_thrtl) begin tcfg_gnt_log = 1'b0; // cfg_turnoff_ok = 1'b1; // For PM request, permit transition end else begin tcfg_gnt_log = 1'b0; // Otherwise do nothing cfg_turnoff_ok = 1'b0; // end end // If there's not throttle event, do nothing else begin // Throttle user as soon as possible tready_thrtl_mux = !(axi_thrtl_ok && pre_throttle); next_state = IDLE; tcfg_gnt_log = 1'b0; cfg_turnoff_ok = 1'b0; end end // THROTTLE: in this state the user is throttle and we're waiting for // exit criteria, which tells us that the throttle event is over. When // the exit criteria is satisfied, de-throttle the user and next state // is IDLE. THROTTLE: begin if(exit_crit) begin // Dethrottle user tready_thrtl_mux = !pre_throttle; next_state = IDLE; end else begin // Throttle user tready_thrtl_mux = 1'b0; next_state = THROTTLE; end // Assert appropriate grant signal depending on the throttle type. if(tcfg_req_thrtl && tcfg_gnt_pending) begin tcfg_gnt_log = 1'b1; // For cfg request, grant the request cfg_turnoff_ok = 1'b0; // end else if(cfg_turnoff_ok_pending) begin tcfg_gnt_log = 1'b0; // cfg_turnoff_ok = 1'b1; // For PM request, permit transition end else begin tcfg_gnt_log = 1'b0; // Otherwise do nothing cfg_turnoff_ok = 1'b0; // end end default: begin tready_thrtl_mux = 1'b0; next_state = IDLE; tcfg_gnt_log = 1'b0; cfg_turnoff_ok = 1'b0; end endcase end // Synchronous logic always @(posedge user_clk) begin if(user_rst) begin // Throttle user by default until link comes up cur_state <= #TCQ THROTTLE; reg_tlast <= #TCQ 1'b0; tready_thrtl <= #TCQ 1'b0; end else begin cur_state <= #TCQ next_state; tready_thrtl <= #TCQ tready_thrtl_mux && !tx_ecrc_pause; reg_tlast <= #TCQ s_axis_tx_tlast; end end // For X7, the PCIe block will generate the ECRC for a packet if trn_tecrc_gen // is asserted at SOF. In this case, the Block needs an extra data beat to // calculate the ECRC, but only if the following conditions are met: // 1) there is no empty DWORDS at the end of the packet // (i.e. packet length % C_DATA_WIDTH == 0) // // 2) There isn't a ECRC in the TLP already, as indicated by the TD bit in the // TLP header // // If both conditions are met, the Block will stall the TRN interface for one // data beat after EOF. We need to predict this stall and preemptively stall the // User for one beat. generate if(C_FAMILY == "X7") begin : ecrc_pause_enabled wire tx_ecrc_pkt; reg reg_tx_ecrc_pkt; wire [1:0] packet_fmt; wire packet_td; wire [2:0] header_len; wire [9:0] payload_len; wire [13:0] packet_len; wire pause_needed; // Grab necessary packet fields assign packet_fmt = s_axis_tx_tdata[30:29]; assign packet_td = s_axis_tx_tdata[15]; // Calculate total packet length assign header_len = packet_fmt[0] ? 3'd4 : 3'd3; assign payload_len = packet_fmt[1] ? s_axis_tx_tdata[9:0] : 10'h0; assign packet_len = {10'h000, header_len} + {4'h0, payload_len}; // Determine if packet a ECRC pause is needed if(C_DATA_WIDTH == 128) begin : packet_len_check_128 assign pause_needed = (packet_len[1:0] == 2'b00) && !packet_td; end else begin : packet_len_check_64 assign pause_needed = (packet_len[0] == 1'b0) && !packet_td; end // Create flag to alert TX pipeline to insert a stall assign tx_ecrc_pkt = s_axis_tx_tuser[0] && pause_needed && tready_thrtl && s_axis_tx_tvalid && !reg_axi_in_pkt; always @(posedge user_clk) begin if(user_rst) begin reg_tx_ecrc_pkt <= #TCQ 1'b0; end else begin if(tx_ecrc_pkt && !s_axis_tx_tlast) begin reg_tx_ecrc_pkt <= #TCQ 1'b1; end else if(tready_thrtl && s_axis_tx_tvalid && s_axis_tx_tlast) begin reg_tx_ecrc_pkt <= #TCQ 1'b0; end end end // Insert the stall now assign tx_ecrc_pause = ((tx_ecrc_pkt || reg_tx_ecrc_pkt) && s_axis_tx_tlast && s_axis_tx_tvalid && tready_thrtl); end else begin : ecrc_pause_disabled assign tx_ecrc_pause = 1'b0; end endgenerate // Logic for 128-bit single cycle bug fix. // This tcfg_gnt pipeline addresses an issue with 128-bit V6 designs where a // single cycle packet transmitted simultaneously with an assertion of tcfg_gnt // from AXI Basic causes the packet to be dropped. The packet drop occurs // because the 128-bit shim doesn't know about the tcfg_req/gnt, and therefor // isn't expecting trn_tdst_rdy to go low. Since the 128-bit shim does throttle // prediction just as we do, it ignores the value of trn_tdst_rdy, and // ultimately drops the packet when transmitting the packet to the block. generate if(C_DATA_WIDTH == 128 && C_FAMILY == "V6") begin : tcfg_gnt_pipeline genvar stage; reg tcfg_gnt_pipe [TCFG_GNT_PIPE_STAGES:0]; // Create a configurable depth FF delay pipeline for(stage = 0; stage < TCFG_GNT_PIPE_STAGES; stage = stage + 1) begin : tcfg_gnt_pipeline_stage always @(posedge user_clk) begin if(user_rst) begin tcfg_gnt_pipe[stage] <= #TCQ 1'b0; end else begin // For stage 0, insert the actual tcfg_gnt signal from logic if(stage == 0) begin tcfg_gnt_pipe[stage] <= #TCQ tcfg_gnt_log; end // For stages 1+, chain together else begin tcfg_gnt_pipe[stage] <= #TCQ tcfg_gnt_pipe[stage - 1]; end end end // tcfg_gnt output to block assigned the last pipeline stage assign trn_tcfg_gnt = tcfg_gnt_pipe[TCFG_GNT_PIPE_STAGES-1]; end end else begin : tcfg_gnt_no_pipeline // For all other architectures, no pipeline delay needed for tcfg_gnt assign trn_tcfg_gnt = tcfg_gnt_log; end endgenerate endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/channel_128.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: channel_128.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Represents a RIFFA channel. Contains a RX port and a // TX port. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module channel_128 #( parameter C_DATA_WIDTH = 9'd128, parameter C_MAX_READ_REQ = 2, // Max read: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B // Local parameters parameter C_RX_FIFO_DEPTH = 1024, parameter C_TX_FIFO_DEPTH = 512, parameter C_SG_FIFO_DEPTH = 1024, parameter C_DATA_WORD_WIDTH = clog2((C_DATA_WIDTH/32)+1) ) ( input CLK, input RST, input [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // Maximum read payload: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B input [2:0] CONFIG_MAX_PAYLOAD_SIZE, // Maximum write payload: 000=128B, 001=256B, 010=512B, 011=1024B input [31:0] PIO_DATA, // Single word programmed I/O data input [C_DATA_WIDTH-1:0] ENG_DATA, // Main incoming data output SG_RX_BUF_RECVD, // Scatter gather RX buffer completely read (ready for next if applicable) input SG_RX_BUF_LEN_VALID, // Scatter gather RX buffer length valid input SG_RX_BUF_ADDR_HI_VALID, // Scatter gather RX buffer high address valid input SG_RX_BUF_ADDR_LO_VALID, // Scatter gather RX buffer low address valid output SG_TX_BUF_RECVD, // Scatter gather TX buffer completely read (ready for next if applicable) input SG_TX_BUF_LEN_VALID, // Scatter gather TX buffer length valid input SG_TX_BUF_ADDR_HI_VALID, // Scatter gather TX buffer high address valid input SG_TX_BUF_ADDR_LO_VALID, // Scatter gather TX buffer low address valid input TXN_RX_LEN_VALID, // Read transaction length valid input TXN_RX_OFF_LAST_VALID, // Read transaction offset/last valid output [31:0] TXN_RX_DONE_LEN, // Read transaction actual transfer length output TXN_RX_DONE, // Read transaction done input TXN_RX_DONE_ACK, // Read transaction actual transfer length read output TXN_TX, // Write transaction notification input TXN_TX_ACK, // Write transaction acknowledged output [31:0] TXN_TX_LEN, // Write transaction length output [31:0] TXN_TX_OFF_LAST, // Write transaction offset/last output [31:0] TXN_TX_DONE_LEN, // Write transaction actual transfer length output TXN_TX_DONE, // Write transaction done input TXN_TX_DONE_ACK, // Write transaction actual transfer length read output RX_REQ, // Read request input RX_REQ_ACK, // Read request accepted output [1:0] RX_REQ_TAG, // Read request data tag output [63:0] RX_REQ_ADDR, // Read request address output [9:0] RX_REQ_LEN, // Read request length output TX_REQ, // Outgoing write request input TX_REQ_ACK, // Outgoing write request acknowledged output [63:0] TX_ADDR, // Outgoing write high address output [9:0] TX_LEN, // Outgoing write length (in 32 bit words) output [C_DATA_WIDTH-1:0] TX_DATA, // Outgoing write data input TX_DATA_REN, // Outgoing write data read enable input TX_SENT, // Outgoing write complete input [C_DATA_WORD_WIDTH-1:0] MAIN_DATA_EN, // Main incoming data enable input MAIN_DONE, // Main incoming data complete input MAIN_ERR, // Main incoming data completed with error input [C_DATA_WORD_WIDTH-1:0] SG_RX_DATA_EN, // Scatter gather for RX incoming data enable input SG_RX_DONE, // Scatter gather for RX incoming data complete input SG_RX_ERR, // Scatter gather for RX incoming data completed with error input [C_DATA_WORD_WIDTH-1:0] SG_TX_DATA_EN, // Scatter gather for TX incoming data enable input SG_TX_DONE, // Scatter gather for TX incoming data complete input SG_TX_ERR, // Scatter gather for TX incoming data completed with error input CHNL_RX_CLK, // Channel read clock output CHNL_RX, // Channel read receive signal input CHNL_RX_ACK, // Channle read received signal output CHNL_RX_LAST, // Channel last read output [31:0] CHNL_RX_LEN, // Channel read length output [30:0] CHNL_RX_OFF, // Channel read offset output [C_DATA_WIDTH-1:0] CHNL_RX_DATA, // Channel read data output CHNL_RX_DATA_VALID, // Channel read data valid input CHNL_RX_DATA_REN, // Channel read data has been recieved input CHNL_TX_CLK, // Channel write clock input CHNL_TX, // Channel write receive signal output CHNL_TX_ACK, // Channel write acknowledgement signal input CHNL_TX_LAST, // Channel last write input [31:0] CHNL_TX_LEN, // Channel write length (in 32 bit words) input [30:0] CHNL_TX_OFF, // Channel write offset input [C_DATA_WIDTH-1:0] CHNL_TX_DATA, // Channel write data input CHNL_TX_DATA_VALID, // Channel write data valid output CHNL_TX_DATA_REN // Channel write data has been recieved ); `include "common_functions.v" wire [C_DATA_WIDTH-1:0] wTxSgData; wire wTxSgDataEmpty; wire wTxSgDataRen; wire wTxSgDataErr; wire wTxSgDataRst; // Receiving port (data to the channel) rx_port_128 #( .C_DATA_WIDTH(C_DATA_WIDTH), .C_MAIN_FIFO_DEPTH(C_RX_FIFO_DEPTH), .C_SG_FIFO_DEPTH(C_SG_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ) ) rxPort ( .RST(RST), .CLK(CLK), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE), .SG_RX_BUF_RECVD(SG_RX_BUF_RECVD), .SG_RX_BUF_DATA(PIO_DATA), .SG_RX_BUF_LEN_VALID(SG_RX_BUF_LEN_VALID), .SG_RX_BUF_ADDR_HI_VALID(SG_RX_BUF_ADDR_HI_VALID), .SG_RX_BUF_ADDR_LO_VALID(SG_RX_BUF_ADDR_LO_VALID), .SG_TX_BUF_RECVD(SG_TX_BUF_RECVD), .SG_TX_BUF_DATA(PIO_DATA), .SG_TX_BUF_LEN_VALID(SG_TX_BUF_LEN_VALID), .SG_TX_BUF_ADDR_HI_VALID(SG_TX_BUF_ADDR_HI_VALID), .SG_TX_BUF_ADDR_LO_VALID(SG_TX_BUF_ADDR_LO_VALID), .SG_DATA(wTxSgData), .SG_DATA_EMPTY(wTxSgDataEmpty), .SG_DATA_REN(wTxSgDataRen), .SG_RST(wTxSgDataRst), .SG_ERR(wTxSgDataErr), .TXN_DATA(PIO_DATA), .TXN_LEN_VALID(TXN_RX_LEN_VALID), .TXN_OFF_LAST_VALID(TXN_RX_OFF_LAST_VALID), .TXN_DONE_LEN(TXN_RX_DONE_LEN), .TXN_DONE(TXN_RX_DONE), .TXN_DONE_ACK(TXN_RX_DONE_ACK), .RX_REQ(RX_REQ), .RX_REQ_ACK(RX_REQ_ACK), .RX_REQ_TAG(RX_REQ_TAG), .RX_REQ_ADDR(RX_REQ_ADDR), .RX_REQ_LEN(RX_REQ_LEN), .MAIN_DATA(ENG_DATA), .MAIN_DATA_EN(MAIN_DATA_EN), .MAIN_DONE(MAIN_DONE), .MAIN_ERR(MAIN_ERR), .SG_RX_DATA(ENG_DATA), .SG_RX_DATA_EN(SG_RX_DATA_EN), .SG_RX_DONE(SG_RX_DONE), .SG_RX_ERR(SG_RX_ERR), .SG_TX_DATA(ENG_DATA), .SG_TX_DATA_EN(SG_TX_DATA_EN), .SG_TX_DONE(SG_TX_DONE), .SG_TX_ERR(SG_TX_ERR), .CHNL_CLK(CHNL_RX_CLK), .CHNL_RX(CHNL_RX), .CHNL_RX_ACK(CHNL_RX_ACK), .CHNL_RX_LAST(CHNL_RX_LAST), .CHNL_RX_LEN(CHNL_RX_LEN), .CHNL_RX_OFF(CHNL_RX_OFF), .CHNL_RX_DATA(CHNL_RX_DATA), .CHNL_RX_DATA_VALID(CHNL_RX_DATA_VALID), .CHNL_RX_DATA_REN(CHNL_RX_DATA_REN) ); // Sending port (data from the channel) tx_port_128 #( .C_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_TX_FIFO_DEPTH) ) txPort ( .CLK(CLK), .RST(RST), .CONFIG_MAX_PAYLOAD_SIZE(CONFIG_MAX_PAYLOAD_SIZE), .TXN(TXN_TX), .TXN_ACK(TXN_TX_ACK), .TXN_LEN(TXN_TX_LEN), .TXN_OFF_LAST(TXN_TX_OFF_LAST), .TXN_DONE_LEN(TXN_TX_DONE_LEN), .TXN_DONE(TXN_TX_DONE), .TXN_DONE_ACK(TXN_TX_DONE_ACK), .SG_DATA(wTxSgData), .SG_DATA_EMPTY(wTxSgDataEmpty), .SG_DATA_REN(wTxSgDataRen), .SG_RST(wTxSgDataRst), .SG_ERR(wTxSgDataErr), .TX_REQ(TX_REQ), .TX_REQ_ACK(TX_REQ_ACK), .TX_ADDR(TX_ADDR), .TX_LEN(TX_LEN), .TX_DATA(TX_DATA), .TX_DATA_REN(TX_DATA_REN), .TX_SENT(TX_SENT), .CHNL_CLK(CHNL_TX_CLK), .CHNL_TX(CHNL_TX), .CHNL_TX_ACK(CHNL_TX_ACK), .CHNL_TX_LAST(CHNL_TX_LAST), .CHNL_TX_LEN(CHNL_TX_LEN), .CHNL_TX_OFF(CHNL_TX_OFF), .CHNL_TX_DATA(CHNL_TX_DATA), .CHNL_TX_DATA_VALID(CHNL_TX_DATA_VALID), .CHNL_TX_DATA_REN(CHNL_TX_DATA_REN) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/channel_32.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: channel_32.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Represents a RIFFA channel. Contains a RX port and a // TX port. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module channel_32 #( parameter C_DATA_WIDTH = 9'd32, parameter C_MAX_READ_REQ = 2, // Max read: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B // Local parameters parameter C_RX_FIFO_DEPTH = 1024, parameter C_TX_FIFO_DEPTH = 512, parameter C_SG_FIFO_DEPTH = 1024, parameter C_DATA_WORD_WIDTH = clog2((C_DATA_WIDTH/32)+1) ) ( input CLK, input RST, input [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // Maximum read payload: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B input [2:0] CONFIG_MAX_PAYLOAD_SIZE, // Maximum write payload: 000=128B, 001=256B, 010=512B, 011=1024B input [31:0] PIO_DATA, // Single word programmed I/O data input [C_DATA_WIDTH-1:0] ENG_DATA, // Main incoming data output SG_RX_BUF_RECVD, // Scatter gather RX buffer completely read (ready for next if applicable) input SG_RX_BUF_LEN_VALID, // Scatter gather RX buffer length valid input SG_RX_BUF_ADDR_HI_VALID, // Scatter gather RX buffer high address valid input SG_RX_BUF_ADDR_LO_VALID, // Scatter gather RX buffer low address valid output SG_TX_BUF_RECVD, // Scatter gather TX buffer completely read (ready for next if applicable) input SG_TX_BUF_LEN_VALID, // Scatter gather TX buffer length valid input SG_TX_BUF_ADDR_HI_VALID, // Scatter gather TX buffer high address valid input SG_TX_BUF_ADDR_LO_VALID, // Scatter gather TX buffer low address valid input TXN_RX_LEN_VALID, // Read transaction length valid input TXN_RX_OFF_LAST_VALID, // Read transaction offset/last valid output [31:0] TXN_RX_DONE_LEN, // Read transaction actual transfer length output TXN_RX_DONE, // Read transaction done input TXN_RX_DONE_ACK, // Read transaction actual transfer length read output TXN_TX, // Write transaction notification input TXN_TX_ACK, // Write transaction acknowledged output [31:0] TXN_TX_LEN, // Write transaction length output [31:0] TXN_TX_OFF_LAST, // Write transaction offset/last output [31:0] TXN_TX_DONE_LEN, // Write transaction actual transfer length output TXN_TX_DONE, // Write transaction done input TXN_TX_DONE_ACK, // Write transaction actual transfer length read output RX_REQ, // Read request input RX_REQ_ACK, // Read request accepted output [1:0] RX_REQ_TAG, // Read request data tag output [63:0] RX_REQ_ADDR, // Read request address output [9:0] RX_REQ_LEN, // Read request length output TX_REQ, // Outgoing write request input TX_REQ_ACK, // Outgoing write request acknowledged output [63:0] TX_ADDR, // Outgoing write high address output [9:0] TX_LEN, // Outgoing write length (in 32 bit words) output [C_DATA_WIDTH-1:0] TX_DATA, // Outgoing write data input TX_DATA_REN, // Outgoing write data read enable input TX_SENT, // Outgoing write complete input [C_DATA_WORD_WIDTH-1:0] MAIN_DATA_EN, // Main incoming data enable input MAIN_DONE, // Main incoming data complete input MAIN_ERR, // Main incoming data completed with error input [C_DATA_WORD_WIDTH-1:0] SG_RX_DATA_EN, // Scatter gather for RX incoming data enable input SG_RX_DONE, // Scatter gather for RX incoming data complete input SG_RX_ERR, // Scatter gather for RX incoming data completed with error input [C_DATA_WORD_WIDTH-1:0] SG_TX_DATA_EN, // Scatter gather for TX incoming data enable input SG_TX_DONE, // Scatter gather for TX incoming data complete input SG_TX_ERR, // Scatter gather for TX incoming data completed with error input CHNL_RX_CLK, // Channel read clock output CHNL_RX, // Channel read receive signal input CHNL_RX_ACK, // Channle read received signal output CHNL_RX_LAST, // Channel last read output [31:0] CHNL_RX_LEN, // Channel read length output [30:0] CHNL_RX_OFF, // Channel read offset output [C_DATA_WIDTH-1:0] CHNL_RX_DATA, // Channel read data output CHNL_RX_DATA_VALID, // Channel read data valid input CHNL_RX_DATA_REN, // Channel read data has been recieved input CHNL_TX_CLK, // Channel write clock input CHNL_TX, // Channel write receive signal output CHNL_TX_ACK, // Channel write acknowledgement signal input CHNL_TX_LAST, // Channel last write input [31:0] CHNL_TX_LEN, // Channel write length (in 32 bit words) input [30:0] CHNL_TX_OFF, // Channel write offset input [C_DATA_WIDTH-1:0] CHNL_TX_DATA, // Channel write data input CHNL_TX_DATA_VALID, // Channel write data valid output CHNL_TX_DATA_REN // Channel write data has been recieved ); `include "common_functions.v" wire [C_DATA_WIDTH-1:0] wTxSgData; wire wTxSgDataEmpty; wire wTxSgDataRen; wire wTxSgDataErr; wire wTxSgDataRst; // Receiving port (data to the channel) rx_port_32 #( .C_DATA_WIDTH(C_DATA_WIDTH), .C_MAIN_FIFO_DEPTH(C_RX_FIFO_DEPTH), .C_SG_FIFO_DEPTH(C_SG_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ) ) rxPort ( .RST(RST), .CLK(CLK), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE), .SG_RX_BUF_RECVD(SG_RX_BUF_RECVD), .SG_RX_BUF_DATA(PIO_DATA), .SG_RX_BUF_LEN_VALID(SG_RX_BUF_LEN_VALID), .SG_RX_BUF_ADDR_HI_VALID(SG_RX_BUF_ADDR_HI_VALID), .SG_RX_BUF_ADDR_LO_VALID(SG_RX_BUF_ADDR_LO_VALID), .SG_TX_BUF_RECVD(SG_TX_BUF_RECVD), .SG_TX_BUF_DATA(PIO_DATA), .SG_TX_BUF_LEN_VALID(SG_TX_BUF_LEN_VALID), .SG_TX_BUF_ADDR_HI_VALID(SG_TX_BUF_ADDR_HI_VALID), .SG_TX_BUF_ADDR_LO_VALID(SG_TX_BUF_ADDR_LO_VALID), .SG_DATA(wTxSgData), .SG_DATA_EMPTY(wTxSgDataEmpty), .SG_DATA_REN(wTxSgDataRen), .SG_RST(wTxSgDataRst), .SG_ERR(wTxSgDataErr), .TXN_DATA(PIO_DATA), .TXN_LEN_VALID(TXN_RX_LEN_VALID), .TXN_OFF_LAST_VALID(TXN_RX_OFF_LAST_VALID), .TXN_DONE_LEN(TXN_RX_DONE_LEN), .TXN_DONE(TXN_RX_DONE), .TXN_DONE_ACK(TXN_RX_DONE_ACK), .RX_REQ(RX_REQ), .RX_REQ_ACK(RX_REQ_ACK), .RX_REQ_TAG(RX_REQ_TAG), .RX_REQ_ADDR(RX_REQ_ADDR), .RX_REQ_LEN(RX_REQ_LEN), .MAIN_DATA(ENG_DATA), .MAIN_DATA_EN(MAIN_DATA_EN), .MAIN_DONE(MAIN_DONE), .MAIN_ERR(MAIN_ERR), .SG_RX_DATA(ENG_DATA), .SG_RX_DATA_EN(SG_RX_DATA_EN), .SG_RX_DONE(SG_RX_DONE), .SG_RX_ERR(SG_RX_ERR), .SG_TX_DATA(ENG_DATA), .SG_TX_DATA_EN(SG_TX_DATA_EN), .SG_TX_DONE(SG_TX_DONE), .SG_TX_ERR(SG_TX_ERR), .CHNL_CLK(CHNL_RX_CLK), .CHNL_RX(CHNL_RX), .CHNL_RX_ACK(CHNL_RX_ACK), .CHNL_RX_LAST(CHNL_RX_LAST), .CHNL_RX_LEN(CHNL_RX_LEN), .CHNL_RX_OFF(CHNL_RX_OFF), .CHNL_RX_DATA(CHNL_RX_DATA), .CHNL_RX_DATA_VALID(CHNL_RX_DATA_VALID), .CHNL_RX_DATA_REN(CHNL_RX_DATA_REN) ); // Sending port (data from the channel) tx_port_32 #( .C_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_TX_FIFO_DEPTH) ) txPort ( .CLK(CLK), .RST(RST), .CONFIG_MAX_PAYLOAD_SIZE(CONFIG_MAX_PAYLOAD_SIZE), .TXN(TXN_TX), .TXN_ACK(TXN_TX_ACK), .TXN_LEN(TXN_TX_LEN), .TXN_OFF_LAST(TXN_TX_OFF_LAST), .TXN_DONE_LEN(TXN_TX_DONE_LEN), .TXN_DONE(TXN_TX_DONE), .TXN_DONE_ACK(TXN_TX_DONE_ACK), .SG_DATA(wTxSgData), .SG_DATA_EMPTY(wTxSgDataEmpty), .SG_DATA_REN(wTxSgDataRen), .SG_RST(wTxSgDataRst), .SG_ERR(wTxSgDataErr), .TX_REQ(TX_REQ), .TX_REQ_ACK(TX_REQ_ACK), .TX_ADDR(TX_ADDR), .TX_LEN(TX_LEN), .TX_DATA(TX_DATA), .TX_DATA_REN(TX_DATA_REN), .TX_SENT(TX_SENT), .CHNL_CLK(CHNL_TX_CLK), .CHNL_TX(CHNL_TX), .CHNL_TX_ACK(CHNL_TX_ACK), .CHNL_TX_LAST(CHNL_TX_LAST), .CHNL_TX_LEN(CHNL_TX_LEN), .CHNL_TX_OFF(CHNL_TX_OFF), .CHNL_TX_DATA(CHNL_TX_DATA), .CHNL_TX_DATA_VALID(CHNL_TX_DATA_VALID), .CHNL_TX_DATA_REN(CHNL_TX_DATA_REN) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/channel_64.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: channel_64.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Represents a RIFFA channel. Contains a RX port and a // TX port. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module channel_64 #( parameter C_DATA_WIDTH = 9'd64, parameter C_MAX_READ_REQ = 2, // Max read: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B // Local parameters parameter C_RX_FIFO_DEPTH = 1024, parameter C_TX_FIFO_DEPTH = 512, parameter C_SG_FIFO_DEPTH = 1024, parameter C_DATA_WORD_WIDTH = clog2((C_DATA_WIDTH/32)+1) ) ( input CLK, input RST, input [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // Maximum read payload: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B input [2:0] CONFIG_MAX_PAYLOAD_SIZE, // Maximum write payload: 000=128B, 001=256B, 010=512B, 011=1024B input [31:0] PIO_DATA, // Single word programmed I/O data input [C_DATA_WIDTH-1:0] ENG_DATA, // Main incoming data output SG_RX_BUF_RECVD, // Scatter gather RX buffer completely read (ready for next if applicable) input SG_RX_BUF_LEN_VALID, // Scatter gather RX buffer length valid input SG_RX_BUF_ADDR_HI_VALID, // Scatter gather RX buffer high address valid input SG_RX_BUF_ADDR_LO_VALID, // Scatter gather RX buffer low address valid output SG_TX_BUF_RECVD, // Scatter gather TX buffer completely read (ready for next if applicable) input SG_TX_BUF_LEN_VALID, // Scatter gather TX buffer length valid input SG_TX_BUF_ADDR_HI_VALID, // Scatter gather TX buffer high address valid input SG_TX_BUF_ADDR_LO_VALID, // Scatter gather TX buffer low address valid input TXN_RX_LEN_VALID, // Read transaction length valid input TXN_RX_OFF_LAST_VALID, // Read transaction offset/last valid output [31:0] TXN_RX_DONE_LEN, // Read transaction actual transfer length output TXN_RX_DONE, // Read transaction done input TXN_RX_DONE_ACK, // Read transaction actual transfer length read output TXN_TX, // Write transaction notification input TXN_TX_ACK, // Write transaction acknowledged output [31:0] TXN_TX_LEN, // Write transaction length output [31:0] TXN_TX_OFF_LAST, // Write transaction offset/last output [31:0] TXN_TX_DONE_LEN, // Write transaction actual transfer length output TXN_TX_DONE, // Write transaction done input TXN_TX_DONE_ACK, // Write transaction actual transfer length read output RX_REQ, // Read request input RX_REQ_ACK, // Read request accepted output [1:0] RX_REQ_TAG, // Read request data tag output [63:0] RX_REQ_ADDR, // Read request address output [9:0] RX_REQ_LEN, // Read request length output TX_REQ, // Outgoing write request input TX_REQ_ACK, // Outgoing write request acknowledged output [63:0] TX_ADDR, // Outgoing write high address output [9:0] TX_LEN, // Outgoing write length (in 32 bit words) output [C_DATA_WIDTH-1:0] TX_DATA, // Outgoing write data input TX_DATA_REN, // Outgoing write data read enable input TX_SENT, // Outgoing write complete input [C_DATA_WORD_WIDTH-1:0] MAIN_DATA_EN, // Main incoming data enable input MAIN_DONE, // Main incoming data complete input MAIN_ERR, // Main incoming data completed with error input [C_DATA_WORD_WIDTH-1:0] SG_RX_DATA_EN, // Scatter gather for RX incoming data enable input SG_RX_DONE, // Scatter gather for RX incoming data complete input SG_RX_ERR, // Scatter gather for RX incoming data completed with error input [C_DATA_WORD_WIDTH-1:0] SG_TX_DATA_EN, // Scatter gather for TX incoming data enable input SG_TX_DONE, // Scatter gather for TX incoming data complete input SG_TX_ERR, // Scatter gather for TX incoming data completed with error input CHNL_RX_CLK, // Channel read clock output CHNL_RX, // Channel read receive signal input CHNL_RX_ACK, // Channle read received signal output CHNL_RX_LAST, // Channel last read output [31:0] CHNL_RX_LEN, // Channel read length output [30:0] CHNL_RX_OFF, // Channel read offset output [C_DATA_WIDTH-1:0] CHNL_RX_DATA, // Channel read data output CHNL_RX_DATA_VALID, // Channel read data valid input CHNL_RX_DATA_REN, // Channel read data has been recieved input CHNL_TX_CLK, // Channel write clock input CHNL_TX, // Channel write receive signal output CHNL_TX_ACK, // Channel write acknowledgement signal input CHNL_TX_LAST, // Channel last write input [31:0] CHNL_TX_LEN, // Channel write length (in 32 bit words) input [30:0] CHNL_TX_OFF, // Channel write offset input [C_DATA_WIDTH-1:0] CHNL_TX_DATA, // Channel write data input CHNL_TX_DATA_VALID, // Channel write data valid output CHNL_TX_DATA_REN // Channel write data has been recieved ); `include "common_functions.v" wire [C_DATA_WIDTH-1:0] wTxSgData; wire wTxSgDataEmpty; wire wTxSgDataRen; wire wTxSgDataErr; wire wTxSgDataRst; // Receiving port (data to the channel) rx_port_64 #( .C_DATA_WIDTH(C_DATA_WIDTH), .C_MAIN_FIFO_DEPTH(C_RX_FIFO_DEPTH), .C_SG_FIFO_DEPTH(C_SG_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ) ) rxPort ( .RST(RST), .CLK(CLK), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE), .SG_RX_BUF_RECVD(SG_RX_BUF_RECVD), .SG_RX_BUF_DATA(PIO_DATA), .SG_RX_BUF_LEN_VALID(SG_RX_BUF_LEN_VALID), .SG_RX_BUF_ADDR_HI_VALID(SG_RX_BUF_ADDR_HI_VALID), .SG_RX_BUF_ADDR_LO_VALID(SG_RX_BUF_ADDR_LO_VALID), .SG_TX_BUF_RECVD(SG_TX_BUF_RECVD), .SG_TX_BUF_DATA(PIO_DATA), .SG_TX_BUF_LEN_VALID(SG_TX_BUF_LEN_VALID), .SG_TX_BUF_ADDR_HI_VALID(SG_TX_BUF_ADDR_HI_VALID), .SG_TX_BUF_ADDR_LO_VALID(SG_TX_BUF_ADDR_LO_VALID), .SG_DATA(wTxSgData), .SG_DATA_EMPTY(wTxSgDataEmpty), .SG_DATA_REN(wTxSgDataRen), .SG_RST(wTxSgDataRst), .SG_ERR(wTxSgDataErr), .TXN_DATA(PIO_DATA), .TXN_LEN_VALID(TXN_RX_LEN_VALID), .TXN_OFF_LAST_VALID(TXN_RX_OFF_LAST_VALID), .TXN_DONE_LEN(TXN_RX_DONE_LEN), .TXN_DONE(TXN_RX_DONE), .TXN_DONE_ACK(TXN_RX_DONE_ACK), .RX_REQ(RX_REQ), .RX_REQ_ACK(RX_REQ_ACK), .RX_REQ_TAG(RX_REQ_TAG), .RX_REQ_ADDR(RX_REQ_ADDR), .RX_REQ_LEN(RX_REQ_LEN), .MAIN_DATA(ENG_DATA), .MAIN_DATA_EN(MAIN_DATA_EN), .MAIN_DONE(MAIN_DONE), .MAIN_ERR(MAIN_ERR), .SG_RX_DATA(ENG_DATA), .SG_RX_DATA_EN(SG_RX_DATA_EN), .SG_RX_DONE(SG_RX_DONE), .SG_RX_ERR(SG_RX_ERR), .SG_TX_DATA(ENG_DATA), .SG_TX_DATA_EN(SG_TX_DATA_EN), .SG_TX_DONE(SG_TX_DONE), .SG_TX_ERR(SG_TX_ERR), .CHNL_CLK(CHNL_RX_CLK), .CHNL_RX(CHNL_RX), .CHNL_RX_ACK(CHNL_RX_ACK), .CHNL_RX_LAST(CHNL_RX_LAST), .CHNL_RX_LEN(CHNL_RX_LEN), .CHNL_RX_OFF(CHNL_RX_OFF), .CHNL_RX_DATA(CHNL_RX_DATA), .CHNL_RX_DATA_VALID(CHNL_RX_DATA_VALID), .CHNL_RX_DATA_REN(CHNL_RX_DATA_REN) ); // Sending port (data from the channel) tx_port_64 #( .C_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_TX_FIFO_DEPTH) ) txPort ( .CLK(CLK), .RST(RST), .CONFIG_MAX_PAYLOAD_SIZE(CONFIG_MAX_PAYLOAD_SIZE), .TXN(TXN_TX), .TXN_ACK(TXN_TX_ACK), .TXN_LEN(TXN_TX_LEN), .TXN_OFF_LAST(TXN_TX_OFF_LAST), .TXN_DONE_LEN(TXN_TX_DONE_LEN), .TXN_DONE(TXN_TX_DONE), .TXN_DONE_ACK(TXN_TX_DONE_ACK), .SG_DATA(wTxSgData), .SG_DATA_EMPTY(wTxSgDataEmpty), .SG_DATA_REN(wTxSgDataRen), .SG_RST(wTxSgDataRst), .SG_ERR(wTxSgDataErr), .TX_REQ(TX_REQ), .TX_REQ_ACK(TX_REQ_ACK), .TX_ADDR(TX_ADDR), .TX_LEN(TX_LEN), .TX_DATA(TX_DATA), .TX_DATA_REN(TX_DATA_REN), .TX_SENT(TX_SENT), .CHNL_CLK(CHNL_TX_CLK), .CHNL_TX(CHNL_TX), .CHNL_TX_ACK(CHNL_TX_ACK), .CHNL_TX_LAST(CHNL_TX_LAST), .CHNL_TX_LEN(CHNL_TX_LEN), .CHNL_TX_OFF(CHNL_TX_OFF), .CHNL_TX_DATA(CHNL_TX_DATA), .CHNL_TX_DATA_VALID(CHNL_TX_DATA_VALID), .CHNL_TX_DATA_REN(CHNL_TX_DATA_REN) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/chnl_tester.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: chnl_tester.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Sample RIFFA channel user module. Designed to exercise // the RIFFA TX and RX interfaces. Receives data on the // RX interface and saves the last value received. Sends // the same amount of data back on the TX interface. The // returned data starts with the last value received, // resets and increments to end with a value equal to the // number of (4 byte) words sent back on the TX interface. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module chnl_tester #( parameter C_PCI_DATA_WIDTH = 9'd32 ) ( input CLK, input RST, output CHNL_RX_CLK, input CHNL_RX, output CHNL_RX_ACK, input CHNL_RX_LAST, input [31:0] CHNL_RX_LEN, input [30:0] CHNL_RX_OFF, input [C_PCI_DATA_WIDTH-1:0] CHNL_RX_DATA, input CHNL_RX_DATA_VALID, output CHNL_RX_DATA_REN, output CHNL_TX_CLK, output CHNL_TX, input CHNL_TX_ACK, output CHNL_TX_LAST, output [31:0] CHNL_TX_LEN, output [30:0] CHNL_TX_OFF, output [C_PCI_DATA_WIDTH-1:0] CHNL_TX_DATA, output CHNL_TX_DATA_VALID, input CHNL_TX_DATA_REN ); reg [C_PCI_DATA_WIDTH-1:0] rData={C_PCI_DATA_WIDTH{1'b0}}; reg [31:0] rLen=0; reg [31:0] rCount=0; reg [1:0] rState=0; assign CHNL_RX_CLK = CLK; assign CHNL_RX_ACK = (rState == 2'd1); assign CHNL_RX_DATA_REN = (rState == 2'd1); assign CHNL_TX_CLK = CLK; assign CHNL_TX = (rState == 2'd3); assign CHNL_TX_LAST = 1'd1; assign CHNL_TX_LEN = rLen; // in words assign CHNL_TX_OFF = 0; assign CHNL_TX_DATA = rData; assign CHNL_TX_DATA_VALID = (rState == 2'd3); always @(posedge CLK or posedge RST) begin if (RST) begin rLen <= #1 0; rCount <= #1 0; rState <= #1 0; rData <= #1 0; end else begin case (rState) 2'd0: begin // Wait for start of RX, save length if (CHNL_RX) begin rLen <= #1 CHNL_RX_LEN; rCount <= #1 0; rState <= #1 2'd1; end end 2'd1: begin // Wait for last data in RX, save value if (CHNL_RX_DATA_VALID) begin rData <= #1 CHNL_RX_DATA; rCount <= #1 rCount + (C_PCI_DATA_WIDTH/32); end if (rCount >= rLen) rState <= #1 2'd2; end 2'd2: begin // Prepare for TX rCount <= #1 (C_PCI_DATA_WIDTH/32); rState <= #1 2'd3; end 2'd3: begin // Start TX with save length and data value if (CHNL_TX_DATA_REN & CHNL_TX_DATA_VALID) begin rData <= #1 {rCount + 4, rCount + 3, rCount + 2, rCount + 1}; rCount <= #1 rCount + (C_PCI_DATA_WIDTH/32); if (rCount >= rLen) rState <= #1 2'd0; end end endcase end end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/common_functions.v ================================================ //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: common_functions.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Commonly used functions in the design. Mostly used in // parameter values. Many of these functions are supported // in System Verilog, but Xilinx tools do not fully // support System Verilog. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- // clog2 -- calculate the ceiling log2 value. function integer clog2; input [31:0] v; reg [31:0] value; begin value = v; if (value == 1) begin clog2 = 0; end else begin value = value-1; for (clog2=0; value>0; clog2=clog2+1) value = value>>1; end end endfunction // clog2s -- calculate the ceiling log2 value, min return is 1 (safe). function integer clog2s; input [31:0] v; reg [31:0] value; begin value = v; if (value == 1) begin clog2s = 1; end else begin value = value-1; for (clog2s=0; value>0; clog2s=clog2s+1) value = value>>1; end end endfunction ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/cross_domain_signal.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: cross_domain_signal.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Send a signal from clock domain A into clock domain B // and get the signal back into clock domain A. Domain A can know roughly when // the signal is received domain B. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module cross_domain_signal ( input CLK_A, // Clock for domain A input CLK_A_SEND, // Signal from domain A to domain B output CLK_A_RECV, // Signal from domain B received in domain A input CLK_B, // Clock for domain B output CLK_B_RECV, // Signal from domain A received in domain B input CLK_B_SEND // Signal from domain B to domain A ); // Sync level signals across domains. syncff sigAtoB (.CLK(CLK_B), .IN_ASYNC(CLK_A_SEND), .OUT_SYNC(CLK_B_RECV)); syncff sigBtoA (.CLK(CLK_A), .IN_ASYNC(CLK_B_SEND), .OUT_SYNC(CLK_A_RECV)); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/demux_1_to_n.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: demux_1_to_n.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Statically sized 1 to n demultiplexer. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module demux_1_to_n #( parameter C_FACTOR = 12, parameter C_WIDTH = 1, // Local parameters parameter C_SEL_WIDTH = clog2s(C_FACTOR) ) ( input [C_WIDTH-1:0] IN, // Inputs output [(C_FACTOR*C_WIDTH)-1:0] OUT, // Outputs input [C_SEL_WIDTH-1:0] SEL // Selector ); `include "common_functions.v" //assign OUT = (IN<<(C_WIDTH*SEL)); genvar i; generate for(i = 0; i < C_FACTOR; i = i + 1) begin: assignments assign OUT[(i*C_WIDTH) +:C_WIDTH] = (SEL == i ? IN : {C_WIDTH{1'b0}}); end endgenerate endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/ff.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: ff.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: A D/Q flip flop. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module ff( CLK, D, Q ); input CLK; input D; output Q; reg Q; always @ (posedge CLK) begin Q <= #1 D; end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/fifo_packer_128.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: fifo_packer_128.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Packs 32, 64, or 96 bit received data into a 128 bit wide // FIFO. Assumes the FIFO always has room to accommodate the data. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: //----------------------------------------------------------------------------- module fifo_packer_128 ( input CLK, input RST, input [127:0] DATA_IN, // Incoming data input [2:0] DATA_IN_EN, // Incoming data enable input DATA_IN_DONE, // Incoming data packet end input DATA_IN_ERR, // Incoming data error input DATA_IN_FLUSH, // End of incoming data output [127:0] PACKED_DATA, // Outgoing data output PACKED_WEN, // Outgoing data write enable output PACKED_DATA_DONE, // End of outgoing data packet output PACKED_DATA_ERR, // Error in outgoing data output PACKED_DATA_FLUSHED // End of outgoing data ); reg [2:0] rPackedCount=0, _rPackedCount=0; reg rPackedDone=0, _rPackedDone=0; reg rPackedErr=0, _rPackedErr=0; reg rPackedFlush=0, _rPackedFlush=0; reg rPackedFlushed=0, _rPackedFlushed=0; reg [223:0] rPackedData=224'd0, _rPackedData=224'd0; reg [127:0] rDataIn=128'd0, _rDataIn=128'd0; reg [2:0] rDataInEn=0, _rDataInEn=0; reg [127:0] rDataMasked=128'd0, _rDataMasked=128'd0; reg [2:0] rDataMaskedEn=0, _rDataMaskedEn=0; assign PACKED_DATA = rPackedData[127:0]; assign PACKED_WEN = rPackedCount[2]; assign PACKED_DATA_DONE = rPackedDone; assign PACKED_DATA_ERR = rPackedErr; assign PACKED_DATA_FLUSHED = rPackedFlushed; // Buffers input data until 4 words are available, then writes 4 words out. wire [127:0] wMask = {128{1'b1}}<<(32*rDataInEn); wire [127:0] wDataMasked = ~wMask & rDataIn; always @ (posedge CLK) begin rPackedCount <= #1 (RST ? 3'd0 : _rPackedCount); rPackedDone <= #1 (RST ? 1'd0 : _rPackedDone); rPackedErr <= #1 (RST ? 1'd0 : _rPackedErr); rPackedFlush <= #1 (RST ? 1'd0 : _rPackedFlush); rPackedFlushed <= #1 (RST ? 1'd0 : _rPackedFlushed); rPackedData <= #1 (RST ? 224'd0 : _rPackedData); rDataIn <= #1 _rDataIn; rDataInEn <= #1 (RST ? 3'd0 : _rDataInEn); rDataMasked <= #1 _rDataMasked; rDataMaskedEn <= #1 (RST ? 3'd0 : _rDataMaskedEn); end always @ (*) begin // Buffer and mask the input data. _rDataIn = DATA_IN; _rDataInEn = DATA_IN_EN; _rDataMasked = wDataMasked; _rDataMaskedEn = rDataInEn; // Count what's in our buffer. When we reach 4 words, 4 words will be written // out. If flush is requested, write out whatever remains. if (rPackedFlush && (rPackedCount[1] | rPackedCount[0])) _rPackedCount = 4; else _rPackedCount = rPackedCount + rDataMaskedEn - {rPackedCount[2], 2'd0}; // Shift data into and out of our buffer as we receive and write out data. if (rDataMaskedEn != 3'd0) _rPackedData = ((rPackedData>>(32*{rPackedCount[2], 2'd0})) | (rDataMasked<<(32*rPackedCount[1:0]))); else _rPackedData = (rPackedData>>(32*{rPackedCount[2], 2'd0})); // Track done/error/flush signals. _rPackedDone = DATA_IN_DONE; _rPackedErr = DATA_IN_ERR; _rPackedFlush = DATA_IN_FLUSH; _rPackedFlushed = rPackedFlush; end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/fifo_packer_32.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: fifo_packer_32.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Packs 32 bit received data into a 32 bit wide FIFO. // Assumes the FIFO always has room to accommodate the data. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: //----------------------------------------------------------------------------- module fifo_packer_32 ( input CLK, input RST, input [31:0] DATA_IN, // Incoming data input DATA_IN_EN, // Incoming data enable input DATA_IN_DONE, // Incoming data packet end input DATA_IN_ERR, // Incoming data error input DATA_IN_FLUSH, // End of incoming data output [31:0] PACKED_DATA, // Outgoing data output PACKED_WEN, // Outgoing data write enable output PACKED_DATA_DONE, // End of outgoing data packet output PACKED_DATA_ERR, // Error in outgoing data output PACKED_DATA_FLUSHED // End of outgoing data ); reg rPackedDone=0, _rPackedDone=0; reg rPackedErr=0, _rPackedErr=0; reg rPackedFlush=0, _rPackedFlush=0; reg rPackedFlushed=0, _rPackedFlushed=0; reg [31:0] rDataIn=64'd0, _rDataIn=64'd0; reg rDataInEn=0, _rDataInEn=0; assign PACKED_DATA = rDataIn; assign PACKED_WEN = rDataInEn; assign PACKED_DATA_DONE = rPackedDone; assign PACKED_DATA_ERR = rPackedErr; assign PACKED_DATA_FLUSHED = rPackedFlushed; // Buffers input data to ease timing. always @ (posedge CLK) begin rPackedDone <= #1 (RST ? 1'd0 : _rPackedDone); rPackedErr <= #1 (RST ? 1'd0 : _rPackedErr); rPackedFlush <= #1 (RST ? 1'd0 : _rPackedFlush); rPackedFlushed <= #1 (RST ? 1'd0 : _rPackedFlushed); rDataIn <= #1 _rDataIn; rDataInEn <= #1 (RST ? 1'd0 : _rDataInEn); end always @ (*) begin // Buffer and mask the input data. _rDataIn = DATA_IN; _rDataInEn = DATA_IN_EN; // Track done/error/flush signals. _rPackedDone = DATA_IN_DONE; _rPackedErr = DATA_IN_ERR; _rPackedFlush = DATA_IN_FLUSH; _rPackedFlushed = rPackedFlush; end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/fifo_packer_64.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: fifo_packer_64.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Packs 32 or 64 bit received data into a 64 bit wide FIFO. // Assumes the FIFO always has room to accommodate the data. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: //----------------------------------------------------------------------------- module fifo_packer_64 ( input CLK, input RST, input [63:0] DATA_IN, // Incoming data input [1:0] DATA_IN_EN, // Incoming data enable input DATA_IN_DONE, // Incoming data packet end input DATA_IN_ERR, // Incoming data error input DATA_IN_FLUSH, // End of incoming data output [63:0] PACKED_DATA, // Outgoing data output PACKED_WEN, // Outgoing data write enable output PACKED_DATA_DONE, // End of outgoing data packet output PACKED_DATA_ERR, // Error in outgoing data output PACKED_DATA_FLUSHED // End of outgoing data ); reg [1:0] rPackedCount=0, _rPackedCount=0; reg rPackedDone=0, _rPackedDone=0; reg rPackedErr=0, _rPackedErr=0; reg rPackedFlush=0, _rPackedFlush=0; reg rPackedFlushed=0, _rPackedFlushed=0; reg [95:0] rPackedData=96'd0, _rPackedData=96'd0; reg [63:0] rDataIn=64'd0, _rDataIn=64'd0; reg [1:0] rDataInEn=0, _rDataInEn=0; reg [63:0] rDataMasked=64'd0, _rDataMasked=64'd0; reg [1:0] rDataMaskedEn=0, _rDataMaskedEn=0; assign PACKED_DATA = rPackedData[63:0]; assign PACKED_WEN = rPackedCount[1]; assign PACKED_DATA_DONE = rPackedDone; assign PACKED_DATA_ERR = rPackedErr; assign PACKED_DATA_FLUSHED = rPackedFlushed; // Buffers input data until 2 words are available, then writes 2 words out. wire [63:0] wMask = {64{1'b1}}<<(32*rDataInEn); wire [63:0] wDataMasked = ~wMask & rDataIn; always @ (posedge CLK) begin rPackedCount <= #1 (RST ? 2'd0 : _rPackedCount); rPackedDone <= #1 (RST ? 1'd0 : _rPackedDone); rPackedErr <= #1 (RST ? 1'd0 : _rPackedErr); rPackedFlush <= #1 (RST ? 1'd0 : _rPackedFlush); rPackedFlushed <= #1 (RST ? 1'd0 : _rPackedFlushed); rPackedData <= #1 (RST ? 96'd0 : _rPackedData); rDataIn <= #1 _rDataIn; rDataInEn <= #1 (RST ? 2'd0 : _rDataInEn); rDataMasked <= #1 _rDataMasked; rDataMaskedEn <= #1 (RST ? 2'd0 : _rDataMaskedEn); end always @ (*) begin // Buffer and mask the input data. _rDataIn = DATA_IN; _rDataInEn = DATA_IN_EN; _rDataMasked = wDataMasked; _rDataMaskedEn = rDataInEn; // Count what's in our buffer. When we reach 2 words, 2 words will be written // out. If flush is requested, write out whatever remains. if (rPackedFlush && rPackedCount[0]) _rPackedCount = 2; else _rPackedCount = rPackedCount + rDataMaskedEn - {rPackedCount[1], 1'd0}; // Shift data into and out of our buffer as we receive and write out data. if (rDataMaskedEn != 2'd0) _rPackedData = ((rPackedData>>(32*{rPackedCount[1], 1'd0})) | (rDataMasked<<(32*rPackedCount[0]))); else _rPackedData = (rPackedData>>(32*{rPackedCount[1], 1'd0})); // Track done/error/flush signals. _rPackedDone = DATA_IN_DONE; _rPackedErr = DATA_IN_ERR; _rPackedFlush = DATA_IN_FLUSH; _rPackedFlushed = rPackedFlush; end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/gtx_drp_chanalign_fix_3752_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : gtx_drp_chanalign_fix_3752_v6.v // Version : 2.4 //-- //-- Description: Virtex6 Workaround for deadlock due lane-lane skew Bug //-- //-- //-- //-------------------------------------------------------------------------------- `timescale 1ns / 1ps module GTX_DRP_CHANALIGN_FIX_3752_V6 #( parameter TCQ = 1, parameter C_SIMULATION = 0 // Set to 1 for simulation ) ( output reg dwe, output reg [15:0] din, //THIS IS THE INPUT TO THE DRP output reg den, output reg [7:0] daddr, output reg [3:0] drpstate, input write_ts1, input write_fts, input [15:0] dout, //THIS IS THE OUTPUT OF THE DRP input drdy, input Reset_n, input drp_clk ); reg [7:0] next_daddr; reg [3:0] next_drpstate; reg write_ts1_gated; reg write_fts_gated; localparam DRP_IDLE_FTS = 1; localparam DRP_IDLE_TS1 = 2; localparam DRP_RESET = 3; localparam DRP_WRITE_FTS = 6; localparam DRP_WRITE_DONE_FTS = 7; localparam DRP_WRITE_TS1 = 8; localparam DRP_WRITE_DONE_TS1 = 9; localparam DRP_COM = 10'b0110111100; localparam DRP_FTS = 10'b0100111100; localparam DRP_TS1 = 10'b0001001010; always @(posedge drp_clk) begin if ( ~Reset_n ) begin daddr <= #(TCQ) 8'h8; drpstate <= #(TCQ) DRP_RESET; write_ts1_gated <= #(TCQ) 0; write_fts_gated <= #(TCQ) 0; end else begin daddr <= #(TCQ) next_daddr; drpstate <= #(TCQ) next_drpstate; write_ts1_gated <= #(TCQ) write_ts1; write_fts_gated <= #(TCQ) write_fts; end end always @(*) begin // DEFAULT CONDITIONS next_drpstate=drpstate; next_daddr=daddr; den=0; din=0; dwe=0; case(drpstate) // RESET CONDITION, WE NEED TO READ THE TOP 6 BITS OF THE DRP REGISTER WHEN WE GET THE WRITE FTS TRIGGER DRP_RESET : begin next_drpstate= DRP_WRITE_TS1; next_daddr=8'h8; end // WRITE FTS SEQUENCE DRP_WRITE_FTS : begin den=1; dwe=1; case (daddr) 8'h8 : din = 16'hFD3C; 8'h9 : din = 16'hC53C; 8'hA : din = 16'hFDBC; 8'hB : din = 16'h853C; endcase next_drpstate=DRP_WRITE_DONE_FTS; end // WAIT FOR FTS SEQUENCE WRITE TO FINISH, ONCE WE FINISH ALL WRITES GO TO FTS IDLE DRP_WRITE_DONE_FTS : begin if(drdy) begin if(daddr==8'hB) begin next_drpstate=DRP_IDLE_FTS; next_daddr=8'h8; end else begin next_drpstate=DRP_WRITE_FTS; next_daddr=daddr+1'b1; end end end // FTS IDLE: WAIT HERE UNTIL WE NEED TO WRITE TS1 DRP_IDLE_FTS : begin if(write_ts1_gated) begin next_drpstate=DRP_WRITE_TS1; next_daddr=8'h8; end end // WRITE TS1 SEQUENCE DRP_WRITE_TS1 : begin den=1; dwe=1; case (daddr) 8'h8 : din = 16'hFC4A; 8'h9 : din = 16'hDC4A; 8'hA : din = 16'hC04A; 8'hB : din = 16'h85BC; endcase next_drpstate=DRP_WRITE_DONE_TS1; end // WAIT FOR TS1 SEQUENCE WRITE TO FINISH, ONCE WE FINISH ALL WRITES GO TO TS1 IDLE DRP_WRITE_DONE_TS1 : begin if(drdy) begin if(daddr==8'hB) begin next_drpstate=DRP_IDLE_TS1; next_daddr=8'h8; end else begin next_drpstate=DRP_WRITE_TS1; next_daddr=daddr+1'b1; end end end // TS1 IDLE: WAIT HERE UNTIL WE NEED TO WRITE FTS DRP_IDLE_TS1 : begin if(write_fts_gated) begin next_drpstate=DRP_WRITE_FTS; next_daddr=8'h8; end end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/gtx_rx_valid_filter_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : gtx_rx_valid_filter_v6.v // Version : 2.4 `timescale 1ns / 1ns module GTX_RX_VALID_FILTER_V6 #( parameter CLK_COR_MIN_LAT = 28, parameter TCQ = 1 ) ( output [1:0] USER_RXCHARISK, output [15:0] USER_RXDATA, output USER_RXVALID, output USER_RXELECIDLE, output [ 2:0] USER_RX_STATUS, output USER_RX_PHY_STATUS, input [1:0] GT_RXCHARISK, input [15:0] GT_RXDATA, input GT_RXVALID, input GT_RXELECIDLE, input [ 2:0] GT_RX_STATUS, input GT_RX_PHY_STATUS, input PLM_IN_L0, input PLM_IN_RS, input USER_CLK, input RESET ); localparam EIOS_DET_IDL = 5'b00001; localparam EIOS_DET_NO_STR0 = 5'b00010; localparam EIOS_DET_STR0 = 5'b00100; localparam EIOS_DET_STR1 = 5'b01000; localparam EIOS_DET_DONE = 5'b10000; localparam EIOS_COM = 8'hBC; localparam EIOS_IDL = 8'h7C; localparam FTSOS_COM = 8'hBC; localparam FTSOS_FTS = 8'h3C; reg [4:0] reg_state_eios_det; wire [4:0] state_eios_det; reg reg_eios_detected; wire eios_detected; reg reg_symbol_after_eios; wire symbol_after_eios; localparam USER_RXVLD_IDL = 4'b0001; localparam USER_RXVLD_EI = 4'b0010; localparam USER_RXVLD_EI_DB0 = 4'b0100; localparam USER_RXVLD_EI_DB1 = 4'b1000; reg [3:0] reg_state_rxvld_ei; wire [3:0] state_rxvld_ei; reg [4:0] reg_rxvld_count; wire [4:0] rxvld_count; reg [3:0] reg_rxvld_fallback; wire [3:0] rxvld_fallback; reg [1:0] gt_rxcharisk_q; reg [15:0] gt_rxdata_q; reg gt_rxvalid_q; reg gt_rxelecidle_q; reg gt_rxelecidle_qq; reg [ 2:0] gt_rx_status_q; reg gt_rx_phy_status_q; reg gt_rx_is_skp0_q; reg gt_rx_is_skp1_q; // EIOS detector always @(posedge USER_CLK) begin if (RESET) begin reg_eios_detected <= #TCQ 1'b0; reg_state_eios_det <= #TCQ EIOS_DET_IDL; reg_symbol_after_eios <= #TCQ 1'b0; gt_rxcharisk_q <= #TCQ 2'b00; gt_rxdata_q <= #TCQ 16'h0; gt_rxvalid_q <= #TCQ 1'b0; gt_rxelecidle_q <= #TCQ 1'b0; gt_rxelecidle_qq <= #TCQ 1'b0; gt_rx_status_q <= #TCQ 3'b000; gt_rx_phy_status_q <= #TCQ 1'b0; gt_rx_is_skp0_q <= #TCQ 1'b0; gt_rx_is_skp1_q <= #TCQ 1'b0; end else begin reg_eios_detected <= #TCQ 1'b0; reg_symbol_after_eios <= #TCQ 1'b0; gt_rxcharisk_q <= #TCQ GT_RXCHARISK; gt_rxdata_q <= #TCQ GT_RXDATA; gt_rxvalid_q <= #TCQ GT_RXVALID; gt_rxelecidle_q <= #TCQ GT_RXELECIDLE; gt_rxelecidle_qq <= #TCQ gt_rxelecidle_q; gt_rx_status_q <= #TCQ GT_RX_STATUS; gt_rx_phy_status_q <= #TCQ GT_RX_PHY_STATUS; if (GT_RXCHARISK[0] && GT_RXDATA[7:0] == FTSOS_FTS) gt_rx_is_skp0_q <= #TCQ 1'b1; else gt_rx_is_skp0_q <= #TCQ 1'b0; if (GT_RXCHARISK[1] && GT_RXDATA[15:8] == FTSOS_FTS) gt_rx_is_skp1_q <= #TCQ 1'b1; else gt_rx_is_skp1_q <= #TCQ 1'b0; case ( state_eios_det ) EIOS_DET_IDL : begin if ((gt_rxcharisk_q[0]) && (gt_rxdata_q[7:0] == EIOS_COM) && (gt_rxcharisk_q[1]) && (gt_rxdata_q[15:8] == EIOS_IDL)) begin reg_state_eios_det <= #TCQ EIOS_DET_NO_STR0; reg_eios_detected <= #TCQ 1'b1; end else if ((gt_rxcharisk_q[1]) && (gt_rxdata_q[15:8] == EIOS_COM)) reg_state_eios_det <= #TCQ EIOS_DET_STR0; else reg_state_eios_det <= #TCQ EIOS_DET_IDL; end EIOS_DET_NO_STR0 : begin if ((gt_rxcharisk_q[0] && (gt_rxdata_q[7:0] == EIOS_IDL)) && (gt_rxcharisk_q[1] && (gt_rxdata_q[15:8] == EIOS_IDL))) reg_state_eios_det <= #TCQ EIOS_DET_DONE; else reg_state_eios_det <= #TCQ EIOS_DET_IDL; end EIOS_DET_STR0 : begin if ((gt_rxcharisk_q[0] && (gt_rxdata_q[7:0] == EIOS_IDL)) && (gt_rxcharisk_q[1] && (gt_rxdata_q[15:8] == EIOS_IDL))) begin reg_state_eios_det <= #TCQ EIOS_DET_STR1; reg_eios_detected <= #TCQ 1'b1; reg_symbol_after_eios <= #TCQ 1'b1; end else reg_state_eios_det <= #TCQ EIOS_DET_IDL; end EIOS_DET_STR1 : begin if ((gt_rxcharisk_q[0]) && (gt_rxdata_q[7:0] == EIOS_IDL)) reg_state_eios_det <= #TCQ EIOS_DET_DONE; else reg_state_eios_det <= #TCQ EIOS_DET_IDL; end EIOS_DET_DONE : begin reg_state_eios_det <= #TCQ EIOS_DET_IDL; end endcase end end assign state_eios_det = reg_state_eios_det; assign eios_detected = reg_eios_detected; assign symbol_after_eios = reg_symbol_after_eios; // user_rxvalid generation always @(posedge USER_CLK) begin if (RESET) begin reg_state_rxvld_ei <= #TCQ USER_RXVLD_IDL; end else begin case ( state_rxvld_ei ) USER_RXVLD_IDL : begin if (eios_detected) reg_state_rxvld_ei <= #TCQ USER_RXVLD_EI; else reg_state_rxvld_ei <= #TCQ USER_RXVLD_IDL; end USER_RXVLD_EI : begin if (!gt_rxvalid_q) reg_state_rxvld_ei <= #TCQ USER_RXVLD_EI_DB0; else if (rxvld_fallback == 4'b1111) reg_state_rxvld_ei <= #TCQ USER_RXVLD_IDL; else reg_state_rxvld_ei <= #TCQ USER_RXVLD_EI; end USER_RXVLD_EI_DB0 : begin if (gt_rxvalid_q) reg_state_rxvld_ei <= #TCQ USER_RXVLD_EI_DB1; else if (!PLM_IN_L0) reg_state_rxvld_ei <= #TCQ USER_RXVLD_IDL; else reg_state_rxvld_ei <= #TCQ USER_RXVLD_EI_DB0; end USER_RXVLD_EI_DB1 : begin if (rxvld_count > CLK_COR_MIN_LAT) reg_state_rxvld_ei <= #TCQ USER_RXVLD_IDL; else reg_state_rxvld_ei <= #TCQ USER_RXVLD_EI_DB1; end endcase end end assign state_rxvld_ei = reg_state_rxvld_ei; // RxValid counter always @(posedge USER_CLK) begin if (RESET) begin reg_rxvld_count <= #TCQ 5'b00000; end else begin if ((gt_rxvalid_q) && (state_rxvld_ei == USER_RXVLD_EI_DB1)) reg_rxvld_count <= #TCQ reg_rxvld_count + 1'b1; else reg_rxvld_count <= #TCQ 5'b00000; end end assign rxvld_count = reg_rxvld_count; // RxValid fallback always @(posedge USER_CLK) begin if (RESET) begin reg_rxvld_fallback <= #TCQ 4'b0000; end else begin if (state_rxvld_ei == USER_RXVLD_EI) reg_rxvld_fallback <= #TCQ reg_rxvld_fallback + 1'b1; else reg_rxvld_fallback <= #TCQ 4'b0000; end end assign rxvld_fallback = reg_rxvld_fallback; // Delay pipe_rx_elec_idle SRL16E #(.INIT(0)) rx_elec_idle_delay (.Q(USER_RXELECIDLE), .D(gt_rxelecidle_q), .CLK(USER_CLK), .CE(1'b1), .A3(1'b1),.A2(1'b1),.A1(1'b1),.A0(1'b1)); reg awake_in_progress_q = 1'b0; reg awake_see_com_q = 1'b0; reg [3:0] awake_com_count_q = 4'b0000; wire awake_see_com_0 = gt_rxvalid_q & (gt_rxcharisk_q[0] && (gt_rxdata_q[7:0] == EIOS_COM)); wire awake_see_com_1 = gt_rxvalid_q & (gt_rxcharisk_q[1] && (gt_rxdata_q[15:8] == EIOS_COM)); wire awake_see_com = (awake_see_com_0 || awake_see_com_1) && ~awake_see_com_q; // Count 8 COMs, (not back-to-back), when waking up from electrical idle // but not for L0s (which is L0). wire awake_done = awake_in_progress_q && (awake_com_count_q[3:0] >= 4'hb); wire awake_start = (~gt_rxelecidle_q && gt_rxelecidle_qq) || PLM_IN_RS; wire awake_in_progress = awake_start || (~awake_done && awake_in_progress_q); wire [3:0] awake_com_count_inced = awake_com_count_q[3:0] + 4'b0001; wire [3:0] awake_com_count = (~awake_in_progress_q) ? 4'b0000 : (awake_start) ? 4'b0000 : (awake_see_com_q) ? awake_com_count_inced[3:0] : awake_com_count_q[3:0]; wire rst_l = ~RESET; always @(posedge USER_CLK) begin awake_see_com_q <= #TCQ (rst_l) ? awake_see_com : 1'b0; awake_in_progress_q <= #TCQ (rst_l) ? awake_in_progress : 1'b0; awake_com_count_q[3:0] <= #TCQ (rst_l) ? awake_com_count[3:0] : 4'h0; end assign USER_RXVALID = ((state_rxvld_ei == USER_RXVLD_IDL) && ~awake_in_progress_q) ? gt_rxvalid_q : 1'b0; assign USER_RXCHARISK[0] = USER_RXVALID ? gt_rxcharisk_q[0] : 1'b0; assign USER_RXCHARISK[1] = (USER_RXVALID && !symbol_after_eios) ? gt_rxcharisk_q[1] : 1'b0; assign USER_RXDATA[7:0] = (gt_rx_is_skp0_q) ? FTSOS_COM : gt_rxdata_q[7:0]; assign USER_RXDATA[15:8] = (gt_rx_is_skp1_q) ? FTSOS_COM : gt_rxdata_q[15:8]; assign USER_RX_STATUS = (state_rxvld_ei == USER_RXVLD_IDL) ? gt_rx_status_q : 3'b000; assign USER_RX_PHY_STATUS = gt_rx_phy_status_q; endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/gtx_tx_sync_rate_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : gtx_tx_sync_rate_v6.v // Version : 2.4 // Module TX_SYNC `timescale 1ns / 1ps module GTX_TX_SYNC_RATE_V6 #( parameter TCQ = 1, parameter C_SIMULATION = 0 // Set to 1 for simulation ) ( output reg ENPMAPHASEALIGN = 1'b0, output reg PMASETPHASE = 1'b0, output reg SYNC_DONE = 1'b0, output reg OUT_DIV_RESET = 1'b0, output reg PCS_RESET = 1'b0, output reg USER_PHYSTATUS = 1'b0, output reg TXALIGNDISABLE = 1'b0, output reg DELAYALIGNRESET = 1'b0, input USER_CLK, input RESET, input RATE, input RATEDONE, input GT_PHYSTATUS, input RESETDONE ); reg ENPMAPHASEALIGN_c; reg PMASETPHASE_c; reg SYNC_DONE_c; reg OUT_DIV_RESET_c; reg PCS_RESET_c; reg USER_PHYSTATUS_c; reg DELAYALIGNRESET_c; reg TXALIGNDISABLE_c; reg [7:0] waitcounter2; reg [7:0] nextwaitcounter2; reg [7:0] waitcounter; reg [7:0] nextwaitcounter; reg [24:0] state; reg [24:0] nextstate; reg ratedone_r, ratedone_r2; wire ratedone_pulse_i; reg gt_phystatus_q; localparam IDLE = 25'b0000000000000000000000001; localparam PHASEALIGN = 25'b0000000000000000000000010; localparam RATECHANGE_DIVRESET = 25'b0000000000000000000000100; localparam RATECHANGE_DIVRESET_POST = 25'b0000000000000000000001000; localparam RATECHANGE_ENPMADISABLE = 25'b0000000000000000000010000; localparam RATECHANGE_ENPMADISABLE_POST = 25'b0000000000000000000100000; localparam RATECHANGE_PMARESET = 25'b0000000000000000001000000; localparam RATECHANGE_IDLE = 25'b0000000000000000010000000; localparam RATECHANGE_PCSRESET = 25'b0000000000000000100000000; localparam RATECHANGE_PCSRESET_POST = 25'b0000000000000001000000000; localparam RATECHANGE_ASSERTPHY = 25'b0000000000000010000000000; localparam RESET_STATE = 25'b0000000000000100000000000; localparam WAIT_PHYSTATUS = 25'b0000000000010000000000000; localparam RATECHANGE_PMARESET_POST = 25'b0000000000100000000000000; localparam RATECHANGE_DISABLEPHASE = 25'b0000000001000000000000000; localparam DELAYALIGNRST = 25'b0000000010000000000000000; localparam SETENPMAPHASEALIGN = 25'b0000000100000000000000000; localparam TXALIGNDISABLEDEASSERT = 25'b0000001000000000000000000; localparam RATECHANGE_TXDLYALIGNDISABLE = 25'b0000010000000000000000000; localparam GTXTEST_PULSE_1 = 25'b0000100000000000000000000; localparam RATECHANGE_DISABLE_TXALIGNDISABLE = 25'b0001000000000000000000000; localparam BEFORE_GTXTEST_PULSE1_1024CLKS = 25'b0010000000000000000000000; localparam BETWEEN_GTXTEST_PULSES = 25'b0100000000000000000000000; localparam GTXTEST_PULSE_2 = 25'b1000000000000000000000000; localparam SYNC_IDX = C_SIMULATION ? 0 : 2; localparam PMARESET_IDX = C_SIMULATION ? 0: 7; always @(posedge USER_CLK) begin if(RESET) begin state <= #(TCQ) RESET_STATE; waitcounter2 <= #(TCQ) 8'b0; waitcounter <= #(TCQ) 8'b0; USER_PHYSTATUS <= #(TCQ) GT_PHYSTATUS; SYNC_DONE <= #(TCQ) 1'b0; ENPMAPHASEALIGN <= #(TCQ) 1'b1; PMASETPHASE <= #(TCQ) 1'b0; OUT_DIV_RESET <= #(TCQ) 1'b0; PCS_RESET <= #(TCQ) 1'b0; DELAYALIGNRESET <= #(TCQ) 1'b0; TXALIGNDISABLE <= #(TCQ) 1'b1; end else begin state <= #(TCQ) nextstate; waitcounter2 <= #(TCQ) nextwaitcounter2; waitcounter <= #(TCQ) nextwaitcounter; USER_PHYSTATUS <= #(TCQ) USER_PHYSTATUS_c; SYNC_DONE <= #(TCQ) SYNC_DONE_c; ENPMAPHASEALIGN <= #(TCQ) ENPMAPHASEALIGN_c; PMASETPHASE <= #(TCQ) PMASETPHASE_c; OUT_DIV_RESET <= #(TCQ) OUT_DIV_RESET_c; PCS_RESET <= #(TCQ) PCS_RESET_c; DELAYALIGNRESET <= #(TCQ) DELAYALIGNRESET_c; TXALIGNDISABLE <= #(TCQ) TXALIGNDISABLE_c; end end always @(*) begin // DEFAULT CONDITIONS DELAYALIGNRESET_c=0; SYNC_DONE_c=0; ENPMAPHASEALIGN_c=1; PMASETPHASE_c=0; OUT_DIV_RESET_c=0; PCS_RESET_c=0; TXALIGNDISABLE_c=0; nextstate=state; USER_PHYSTATUS_c=GT_PHYSTATUS; nextwaitcounter=waitcounter+1'b1; nextwaitcounter2= (waitcounter ==8'hff)? waitcounter2 + 1'b1 : waitcounter2 ; case(state) // START IN RESET RESET_STATE : begin TXALIGNDISABLE_c=1; ENPMAPHASEALIGN_c=0; nextstate=BEFORE_GTXTEST_PULSE1_1024CLKS; nextwaitcounter=0; nextwaitcounter2=0; end // Have to hold for 1024 clocks before asserting GTXTEST[1] BEFORE_GTXTEST_PULSE1_1024CLKS : begin OUT_DIV_RESET_c=0; TXALIGNDISABLE_c=1; ENPMAPHASEALIGN_c=0; if(waitcounter2[1]) begin nextstate=GTXTEST_PULSE_1; nextwaitcounter=0; nextwaitcounter2=0; end end // Assert GTXTEST[1] for 256 clocks. Figure 3-9 UG366 GTXTEST_PULSE_1: begin OUT_DIV_RESET_c=1; TXALIGNDISABLE_c=1; ENPMAPHASEALIGN_c=0; if(waitcounter[7]) begin nextstate=BETWEEN_GTXTEST_PULSES; nextwaitcounter=0; nextwaitcounter2=0; end end // De-assert GTXTEST[1] for 256 clocks. Figure 3-9 UG366 BETWEEN_GTXTEST_PULSES: begin OUT_DIV_RESET_c=0; TXALIGNDISABLE_c=1; ENPMAPHASEALIGN_c=0; if(waitcounter[7]) begin nextstate=GTXTEST_PULSE_2; nextwaitcounter=0; nextwaitcounter2=0; end end // Assert GTXTEST[1] for 256 clocks a second time. Figure 3-9 UG366 GTXTEST_PULSE_2: begin OUT_DIV_RESET_c=1; TXALIGNDISABLE_c=1; ENPMAPHASEALIGN_c=0; if(waitcounter[7]) begin nextstate=DELAYALIGNRST; nextwaitcounter=0; nextwaitcounter2=0; end end // ASSERT TXDLYALIGNRESET FOR 16 CLOCK CYCLES DELAYALIGNRST : begin DELAYALIGNRESET_c=1; ENPMAPHASEALIGN_c=0; TXALIGNDISABLE_c=1; if(waitcounter[4]) begin nextstate=SETENPMAPHASEALIGN; nextwaitcounter=0; nextwaitcounter2=0; end end // ASSERT ENPMAPHASEALIGN FOR 32 CLOCK CYCLES SETENPMAPHASEALIGN : begin TXALIGNDISABLE_c=1; if(waitcounter[5]) begin nextstate=PHASEALIGN; nextwaitcounter=0; nextwaitcounter2=0; end end // ASSERT PMASETPHASE OUT OF RESET for 32K CYCLES PHASEALIGN : begin PMASETPHASE_c=1; TXALIGNDISABLE_c=1; if(waitcounter2[PMARESET_IDX]) begin nextstate=TXALIGNDISABLEDEASSERT; nextwaitcounter=0; nextwaitcounter2=0; end end // KEEP TXALIGNDISABLE ASSERTED for 64 CYCLES TXALIGNDISABLEDEASSERT : begin TXALIGNDISABLE_c=1; if(waitcounter[6]) begin nextwaitcounter=0; nextstate=IDLE; nextwaitcounter2=0; end end // NOW IN IDLE, ASSERT SYNC DONE, WAIT FOR RATECHANGE IDLE : begin SYNC_DONE_c=1; if(ratedone_pulse_i) begin USER_PHYSTATUS_c=0; nextstate=WAIT_PHYSTATUS; nextwaitcounter=0; nextwaitcounter2=0; end end // WAIT FOR PHYSTATUS WAIT_PHYSTATUS : begin USER_PHYSTATUS_c=0; if(gt_phystatus_q) begin nextstate=RATECHANGE_IDLE; nextwaitcounter=0; nextwaitcounter2=0; end end // WAIT 64 CYCLES BEFORE WE START THE RATE CHANGE RATECHANGE_IDLE : begin USER_PHYSTATUS_c=0; if(waitcounter[6]) begin nextstate=RATECHANGE_TXDLYALIGNDISABLE; nextwaitcounter=0; nextwaitcounter2=0; end end // ASSERT TXALIGNDISABLE FOR 32 CYCLES RATECHANGE_TXDLYALIGNDISABLE : begin USER_PHYSTATUS_c=0; TXALIGNDISABLE_c=1; if(waitcounter[5]) begin nextstate=RATECHANGE_DIVRESET; nextwaitcounter=0; nextwaitcounter2=0; end end // ASSERT DIV RESET FOR 16 CLOCK CYCLES RATECHANGE_DIVRESET : begin OUT_DIV_RESET_c=1; USER_PHYSTATUS_c=0; TXALIGNDISABLE_c=1; if(waitcounter[4]) begin nextstate=RATECHANGE_DIVRESET_POST; nextwaitcounter=0; nextwaitcounter2=0; end end // WAIT FOR 32 CLOCK CYCLES BEFORE NEXT STEP RATECHANGE_DIVRESET_POST : begin USER_PHYSTATUS_c=0; TXALIGNDISABLE_c=1; if(waitcounter[5]) begin nextstate=RATECHANGE_PMARESET; nextwaitcounter=0; nextwaitcounter2=0; end end // ASSERT PMA RESET FOR 32K CYCLES RATECHANGE_PMARESET : begin PMASETPHASE_c=1; USER_PHYSTATUS_c=0; TXALIGNDISABLE_c=1; if(waitcounter2[PMARESET_IDX]) begin nextstate=RATECHANGE_PMARESET_POST; nextwaitcounter=0; nextwaitcounter2=0; end end // WAIT FOR 32 CYCLES BEFORE DISABLING TXALIGNDISABLE RATECHANGE_PMARESET_POST : begin USER_PHYSTATUS_c=0; TXALIGNDISABLE_c=1; if(waitcounter[5]) begin nextstate=RATECHANGE_DISABLE_TXALIGNDISABLE; nextwaitcounter=0; nextwaitcounter2=0; end end // DISABLE TXALIGNDISABLE FOR 32 CYCLES RATECHANGE_DISABLE_TXALIGNDISABLE : begin USER_PHYSTATUS_c=0; if(waitcounter[5]) begin nextstate=RATECHANGE_PCSRESET; nextwaitcounter=0; nextwaitcounter2=0; end end // NOW ASSERT PCS RESET FOR 32 CYCLES RATECHANGE_PCSRESET : begin PCS_RESET_c=1; USER_PHYSTATUS_c=0; if(waitcounter[5]) begin nextstate=RATECHANGE_PCSRESET_POST; nextwaitcounter=0; nextwaitcounter2=0; end end // WAIT FOR RESETDONE BEFORE ASSERTING PHY_STATUS_OUT RATECHANGE_PCSRESET_POST : begin USER_PHYSTATUS_c=0; if(RESETDONE) begin nextstate=RATECHANGE_ASSERTPHY; end end // ASSERT PHYSTATUSOUT MEANING RATECHANGE IS DONE AND GO BACK TO IDLE RATECHANGE_ASSERTPHY : begin USER_PHYSTATUS_c=1; nextstate=IDLE; end endcase end // Generate Ratechange Pulse always @(posedge USER_CLK) begin if (RESET) begin ratedone_r <= #(TCQ) 1'b0; ratedone_r2 <= #(TCQ) 1'b0; gt_phystatus_q <= #(TCQ) 1'b0; end else begin ratedone_r <= #(TCQ) RATE; ratedone_r2 <= #(TCQ) ratedone_r; gt_phystatus_q <= #(TCQ) GT_PHYSTATUS; end end assign ratedone_pulse_i = (ratedone_r != ratedone_r2); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/gtx_wrapper_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : gtx_wrapper_v6.v // Version : 2.4 //-- Description: GTX module for Virtex6 PCIe Block //-- //-- //-- //-------------------------------------------------------------------------------- `timescale 1ns/1ns module gtx_wrapper_v6 ( // TX TX, TX_, TxData, TxDataK, TxElecIdle, TxCompliance, // RX RX, RX_, RxData, RxDataK, RxPolarity, RxValid, RxElecIdle, RxStatus, // other GTRefClkout, plm_in_l0, plm_in_rl, plm_in_dt, plm_in_rs, RxPLLLkDet, TxDetectRx, PhyStatus, TXPdownAsynch, PowerDown, Rate, Reset_n, GTReset_n, PCLK, REFCLK, TxDeemph, TxMargin, TxSwing, ChanIsAligned, local_pcs_reset, RxResetDone, SyncDone, DRPCLK, TxOutClk ); parameter NO_OF_LANES = 1; parameter REF_CLK_FREQ = 0; parameter PL_FAST_TRAIN = "FALSE"; localparam GTX_PLL_DIVSEL_FB = (REF_CLK_FREQ == 0) ? 5 : (REF_CLK_FREQ == 1) ? 4 : (REF_CLK_FREQ == 2) ? 2 : 0; localparam SIMULATION = (PL_FAST_TRAIN == "TRUE") ? 1 : 0; localparam RXPLL_CP_CFG = (REF_CLK_FREQ == 0) ? 8'h05 : (REF_CLK_FREQ == 1) ? 8'h05 : (REF_CLK_FREQ == 2) ? 8'h05 : 8'h05; localparam TXPLL_CP_CFG = (REF_CLK_FREQ == 0) ? 8'h05 : (REF_CLK_FREQ == 1) ? 8'h05 : (REF_CLK_FREQ == 2) ? 8'h05 : 8'h05; localparam RX_CLK25_DIVIDER = (REF_CLK_FREQ == 0) ? 4 : (REF_CLK_FREQ == 1) ? 5 : (REF_CLK_FREQ == 2) ? 10 : 10 ; localparam TX_CLK25_DIVIDER = (REF_CLK_FREQ == 0) ? 4 : (REF_CLK_FREQ == 1) ? 5 : (REF_CLK_FREQ == 2) ? 10 : 10 ; // TX output [NO_OF_LANES-1:0] TX; output [NO_OF_LANES-1:0] TX_; input [(NO_OF_LANES*16)-1:0] TxData; input [(NO_OF_LANES*2)-1:0] TxDataK; input [NO_OF_LANES-1:0] TxElecIdle; input [NO_OF_LANES-1:0] TxCompliance; // RX input [NO_OF_LANES-1:0] RX; input [NO_OF_LANES-1:0] RX_; output [(NO_OF_LANES*16)-1:0] RxData; output [(NO_OF_LANES*2)-1:0] RxDataK; input [NO_OF_LANES-1:0] RxPolarity; output [NO_OF_LANES-1:0] RxValid; output [NO_OF_LANES-1:0] RxElecIdle; output [(NO_OF_LANES*3)-1:0] RxStatus; // other output [NO_OF_LANES-1:0] GTRefClkout; input plm_in_l0; input plm_in_rl; input plm_in_dt; input plm_in_rs; output [NO_OF_LANES-1:0] RxPLLLkDet; input TxDetectRx; output [NO_OF_LANES-1:0] PhyStatus; input PCLK; output [NO_OF_LANES-1:0] ChanIsAligned; input TXPdownAsynch; input [(NO_OF_LANES*2)-1:0] PowerDown; input Rate; input Reset_n; input GTReset_n; input REFCLK; input TxDeemph; input TxMargin; input TxSwing; input local_pcs_reset; output RxResetDone; output SyncDone; input DRPCLK; output TxOutClk; genvar i; // dummy signals to avoid port mismatch with DUAL_GTX wire [15:0] RxData_dummy; wire [1:0] RxDataK_dummy; wire [15:0] TxData_dummy; wire [1:0] TxDataK_dummy; // inputs wire [(NO_OF_LANES*16)-1:0] GTX_TxData = TxData; wire [(NO_OF_LANES*2)-1:0] GTX_TxDataK = TxDataK; wire [(NO_OF_LANES)-1:0] GTX_TxElecIdle = TxElecIdle; wire [(NO_OF_LANES-1):0] GTX_TxCompliance = TxCompliance; wire [(NO_OF_LANES)-1:0] GTX_RXP = RX[(NO_OF_LANES)-1:0]; wire [(NO_OF_LANES)-1:0] GTX_RXN = RX_[(NO_OF_LANES)-1:0]; // outputs wire [(NO_OF_LANES)-1:0] GTX_TXP; wire [(NO_OF_LANES)-1:0] GTX_TXN; wire [(NO_OF_LANES*16)-1:0] GTX_RxData; wire [(NO_OF_LANES*2)-1:0] GTX_RxDataK; wire [(NO_OF_LANES)-1:0] GTX_RxPolarity = RxPolarity ; wire [(NO_OF_LANES)-1:0] GTX_RxValid; wire [(NO_OF_LANES)-1:0] GTX_RxElecIdle; wire [(NO_OF_LANES-1):0] GTX_RxResetDone; wire [(NO_OF_LANES*3)-1:0] GTX_RxChbondLevel; wire [(NO_OF_LANES*3)-1:0] GTX_RxStatus; wire [3:0] RXCHBOND [NO_OF_LANES+1:0]; wire [3:0] TXBYPASS8B10B = 4'b0000; wire RXDEC8B10BUSE = 1'b1; wire [NO_OF_LANES-1:0] GTX_PhyStatus; wire RESETDONE [NO_OF_LANES-1:0]; wire REFCLK; wire GTXRESET = 1'b0; wire [NO_OF_LANES-1:0] SYNC_DONE; wire [NO_OF_LANES-1:0] OUT_DIV_RESET; wire [NO_OF_LANES-1:0] PCS_RESET; wire [NO_OF_LANES-1:0] TXENPMAPHASEALIGN; wire [NO_OF_LANES-1:0] TXPMASETPHASE; wire [NO_OF_LANES-1:0] TXRESETDONE; wire [NO_OF_LANES-1:0] TXRATEDONE; wire [NO_OF_LANES-1:0] PHYSTATUS; wire [NO_OF_LANES-1:0] RXVALID; wire [NO_OF_LANES-1:0] RATE_CLK_SEL; wire [NO_OF_LANES-1:0] TXOCLK; wire [NO_OF_LANES-1:0] TXDLYALIGNDISABLE; wire [NO_OF_LANES-1:0] TXDLYALIGNRESET; reg [(NO_OF_LANES-1):0] GTX_RxResetDone_q; reg [(NO_OF_LANES-1):0] TXRESETDONE_q; wire [NO_OF_LANES-1:0] RxValid; wire [(NO_OF_LANES*8-1):0] daddr; wire [NO_OF_LANES-1:0] den; wire [(NO_OF_LANES*16-1):0] din; wire [NO_OF_LANES-1:0] dwe; wire [(NO_OF_LANES*4-1):0] drpstate; wire [NO_OF_LANES-1:0] drdy; wire [(NO_OF_LANES*16-1):0] dout; wire write_drp_cb_fts; wire write_drp_cb_ts1; assign RxResetDone = &(GTX_RxResetDone_q[(NO_OF_LANES)-1:0]); assign TX[(NO_OF_LANES)-1:0] = GTX_TXP[(NO_OF_LANES)-1:0]; assign TX_[(NO_OF_LANES)-1:0] = GTX_TXN[(NO_OF_LANES)-1:0]; assign RXCHBOND[0] = 4'b0000; assign TxData_dummy = 16'b0; assign TxDataK_dummy = 2'b0; assign SyncDone = &(SYNC_DONE[(NO_OF_LANES)-1:0]); assign TxOutClk = TXOCLK[0]; assign write_drp_cb_fts = plm_in_l0; assign write_drp_cb_ts1 = plm_in_rl | plm_in_dt; // pipeline to improve timing always @ (posedge PCLK) begin GTX_RxResetDone_q[(NO_OF_LANES)-1:0] <= GTX_RxResetDone[(NO_OF_LANES)-1:0]; TXRESETDONE_q[(NO_OF_LANES)-1:0] <= TXRESETDONE[(NO_OF_LANES)-1:0]; end generate begin: no_of_lanes for (i=0; i < NO_OF_LANES; i=i+1) begin: GTXD assign GTX_RxChbondLevel[(3*i)+2:(3*i)] = (NO_OF_LANES-(i+1)); GTX_DRP_CHANALIGN_FIX_3752_V6 # ( .C_SIMULATION(SIMULATION) ) GTX_DRP_CHANALIGN_FIX_3752 ( .dwe(dwe[i]), .din(din[(16*i)+15:(16*i)]), .den(den[i]), .daddr(daddr[(8*i)+7:(8*i)]), .drpstate(drpstate[(4*i)+3:(4*i)]), .write_ts1(write_drp_cb_ts1), .write_fts(write_drp_cb_fts), .dout(dout[(16*i)+15:(16*i)]), .drdy(drdy[i]), .Reset_n(Reset_n), .drp_clk(DRPCLK) ); GTX_RX_VALID_FILTER_V6 # ( .CLK_COR_MIN_LAT(28) ) GTX_RX_VALID_FILTER ( .USER_RXCHARISK ( RxDataK[(2*i)+1:2*i] ), //O .USER_RXDATA ( RxData[(16*i)+15:(16*i)+0] ), //O .USER_RXVALID ( RxValid[i] ), //O .USER_RXELECIDLE ( RxElecIdle[i] ), //O .USER_RX_STATUS ( RxStatus[(3*i)+2:(3*i)] ), //O .USER_RX_PHY_STATUS ( PhyStatus[i] ), //O .GT_RXCHARISK ( GTX_RxDataK[(2*i)+1:2*i] ), //I .GT_RXDATA ( GTX_RxData[(16*i)+15:(16*i)+0] ), //I .GT_RXVALID ( GTX_RxValid[i] ), //I .GT_RXELECIDLE ( GTX_RxElecIdle[i] ), //I .GT_RX_STATUS ( GTX_RxStatus[(3*i)+2:(3*i)] ), //I .GT_RX_PHY_STATUS ( PHYSTATUS[i] ), .PLM_IN_L0 ( plm_in_l0 ), //I .PLM_IN_RS ( plm_in_rs ), //I .USER_CLK ( PCLK ), //I .RESET ( !Reset_n ) //I ); GTX_TX_SYNC_RATE_V6 # ( .C_SIMULATION(SIMULATION) ) GTX_TX_SYNC ( .ENPMAPHASEALIGN ( TXENPMAPHASEALIGN[i] ), //O .PMASETPHASE ( TXPMASETPHASE[i] ), //O .SYNC_DONE ( SYNC_DONE[i] ), //O .OUT_DIV_RESET ( OUT_DIV_RESET[i] ), //O .PCS_RESET ( PCS_RESET[i] ), //O .USER_PHYSTATUS ( PHYSTATUS[i] ), //O .TXALIGNDISABLE ( TXDLYALIGNDISABLE[i] ), //O .DELAYALIGNRESET ( TXDLYALIGNRESET[i] ), //O .USER_CLK ( PCLK), //I .RESET ( !Reset_n ), //I .RATE ( Rate ), //I .RATEDONE ( TXRATEDONE[i] ), //I .GT_PHYSTATUS ( GTX_PhyStatus[i] ), //I .RESETDONE ( TXRESETDONE_q[i] & GTX_RxResetDone_q[i] ) //I ); GTXE1 # ( .TX_DRIVE_MODE("PIPE"), .TX_DEEMPH_1(5'b10010), .TX_MARGIN_FULL_0(7'b100_1101), .TX_CLK_SOURCE("RXPLL"), .POWER_SAVE(10'b0000110100), .CM_TRIM ( 2'b01 ), .PMA_CDR_SCAN ( 27'h640404C ), .PMA_CFG( 76'h0040000040000000003 ), .RCV_TERM_GND ("TRUE"), .RCV_TERM_VTTRX ("FALSE"), .RX_DLYALIGN_EDGESET(5'b00010), .RX_DLYALIGN_LPFINC(4'b0110), .RX_DLYALIGN_OVRDSETTING(8'b10000000), .TERMINATION_CTRL(5'b00000), .TERMINATION_OVRD("FALSE"), .TX_DLYALIGN_LPFINC(4'b0110), .TX_DLYALIGN_OVRDSETTING(8'b10000000), .TXPLL_CP_CFG( TXPLL_CP_CFG ), .OOBDETECT_THRESHOLD( 3'b011 ), .RXPLL_CP_CFG ( RXPLL_CP_CFG ), //.TX_DETECT_RX_CFG( 14'h1832 ), .TX_TDCC_CFG ( 2'b11 ), .BIAS_CFG ( 17'h00000 ), .AC_CAP_DIS ( "FALSE" ), .DFE_CFG ( 8'b00011011 ), .SIM_TX_ELEC_IDLE_LEVEL("1"), .SIM_RECEIVER_DETECT_PASS("TRUE"), .RX_EN_REALIGN_RESET_BUF("FALSE"), .TX_IDLE_ASSERT_DELAY(3'b100), // TX-idle-set-to-idle (13 UI) .TX_IDLE_DEASSERT_DELAY(3'b010), // TX-idle-to-diff (7 UI) .CHAN_BOND_SEQ_2_CFG(5'b11111), // 5'b11111 for PCIE mode, 5'b00000 for other modes .CHAN_BOND_KEEP_ALIGN("TRUE"), .RX_IDLE_HI_CNT(4'b1000), .RX_IDLE_LO_CNT(4'b0000), .RX_EN_IDLE_RESET_BUF("TRUE"), .TX_DATA_WIDTH(20), .RX_DATA_WIDTH(20), .ALIGN_COMMA_WORD(1), .CHAN_BOND_1_MAX_SKEW(7), .CHAN_BOND_2_MAX_SKEW(1), .CHAN_BOND_SEQ_1_1(10'b0001000101), // D5.2 (end TS2) .CHAN_BOND_SEQ_1_2(10'b0001000101), // D5.2 (end TS2) .CHAN_BOND_SEQ_1_3(10'b0001000101), // D5.2 (end TS2) .CHAN_BOND_SEQ_1_4(10'b0110111100), // K28.5 (COM) .CHAN_BOND_SEQ_1_ENABLE(4'b1111), // order is 4321 .CHAN_BOND_SEQ_2_1(10'b0100111100), // K28.1 (FTS) .CHAN_BOND_SEQ_2_2(10'b0100111100), // K28.1 (FTS) .CHAN_BOND_SEQ_2_3(10'b0110111100), // K28.5 (COM) .CHAN_BOND_SEQ_2_4(10'b0100111100), // K28.1 (FTS) .CHAN_BOND_SEQ_2_ENABLE(4'b1111), // order is 4321 .CHAN_BOND_SEQ_2_USE("TRUE"), .CHAN_BOND_SEQ_LEN(4), // 1..4 .RX_CLK25_DIVIDER(RX_CLK25_DIVIDER), .TX_CLK25_DIVIDER(TX_CLK25_DIVIDER), .CLK_COR_ADJ_LEN(1), // 1..4 .CLK_COR_DET_LEN(1), // 1..4 .CLK_COR_INSERT_IDLE_FLAG("FALSE"), .CLK_COR_KEEP_IDLE("FALSE"), .CLK_COR_MAX_LAT(30), .CLK_COR_MIN_LAT(28), .CLK_COR_PRECEDENCE("TRUE"), .CLK_CORRECT_USE("TRUE"), .CLK_COR_REPEAT_WAIT(0), .CLK_COR_SEQ_1_1(10'b0100011100), // K28.0 (SKP) .CLK_COR_SEQ_1_2(10'b0000000000), .CLK_COR_SEQ_1_3(10'b0000000000), .CLK_COR_SEQ_1_4(10'b0000000000), .CLK_COR_SEQ_1_ENABLE(4'b1111), .CLK_COR_SEQ_2_1(10'b0000000000), .CLK_COR_SEQ_2_2(10'b0000000000), .CLK_COR_SEQ_2_3(10'b0000000000), .CLK_COR_SEQ_2_4(10'b0000000000), .CLK_COR_SEQ_2_ENABLE(4'b1111), .CLK_COR_SEQ_2_USE("FALSE"), .COMMA_10B_ENABLE(10'b1111111111), .COMMA_DOUBLE("FALSE"), .DEC_MCOMMA_DETECT("TRUE"), .DEC_PCOMMA_DETECT("TRUE"), .DEC_VALID_COMMA_ONLY("TRUE"), .MCOMMA_10B_VALUE(10'b1010000011), .MCOMMA_DETECT("TRUE"), .PCI_EXPRESS_MODE("TRUE"), .PCOMMA_10B_VALUE(10'b0101111100), .PCOMMA_DETECT("TRUE"), .RXPLL_DIVSEL_FB(GTX_PLL_DIVSEL_FB), // 1..5, 8, 10 .TXPLL_DIVSEL_FB(GTX_PLL_DIVSEL_FB), // 1..5, 8, 10 .RXPLL_DIVSEL_REF(1), // 1..6, 8, 10, 12, 16, 20 .TXPLL_DIVSEL_REF(1), // 1..6, 8, 10, 12, 16, 20 .RXPLL_DIVSEL_OUT(2), // 1, 2, 4 .TXPLL_DIVSEL_OUT(2), // 1, 2, 4 .RXPLL_DIVSEL45_FB(5), .TXPLL_DIVSEL45_FB(5), .RX_BUFFER_USE("TRUE"), .RX_DECODE_SEQ_MATCH("TRUE"), .RX_LOS_INVALID_INCR(8), // power of 2: 1..128 .RX_LOSS_OF_SYNC_FSM("FALSE"), .RX_LOS_THRESHOLD(128), // power of 2: 4..512 .RX_SLIDE_MODE("OFF"), // 00=OFF 01=AUTO 10=PCS 11=PMA .RX_XCLK_SEL ("RXREC"), .TX_BUFFER_USE("FALSE"), // Must be set to FALSE for use by PCIE .TX_XCLK_SEL ("TXUSR"), // Must be set to TXUSR for use by PCIE .TXPLL_LKDET_CFG (3'b101), .RX_EYE_SCANMODE (2'b00), .RX_EYE_OFFSET (8'h4C), .PMA_RX_CFG ( 25'h05ce049 ), .TRANS_TIME_NON_P2(8'h2), // Reduced simulation time .TRANS_TIME_FROM_P2(12'h03c), // Reduced simulation time .TRANS_TIME_TO_P2(10'h064), // Reduced simulation time .TRANS_TIME_RATE(8'hD7), // Reduced simulation time .SHOW_REALIGN_COMMA("FALSE"), .TX_PMADATA_OPT(1'b1), // Lockup latch between PCS and PMA .PMA_TX_CFG( 20'h80082 ), // Aligns posedge of USRCLK .TXOUTCLK_CTRL("TXPLLREFCLK_DIV1") ) GTX ( .COMFINISH (), .COMINITDET (), .COMSASDET (), .COMWAKEDET (), .DADDR (daddr[(8*i)+7:(8*i)]), .DCLK (DRPCLK), .DEN (den[i]), .DFECLKDLYADJ ( 6'h0 ), .DFECLKDLYADJMON (), .DFEDLYOVRD ( 1'b0 ), .DFEEYEDACMON (), .DFESENSCAL (), .DFETAP1 (0), .DFETAP1MONITOR (), .DFETAP2 (5'h0), .DFETAP2MONITOR (), .DFETAP3 (4'h0), .DFETAP3MONITOR (), .DFETAP4 (4'h0), .DFETAP4MONITOR (), .DFETAPOVRD ( 1'b1 ), .DI (din[(16*i)+15:(16*i)]), .DRDY (drdy[i]), .DRPDO (dout[(16*i)+15:(16*i)]), .DWE (dwe[i]), .GATERXELECIDLE ( 1'b0 ), .GREFCLKRX (0), .GREFCLKTX (0), .GTXRXRESET ( ~GTReset_n ), .GTXTEST ( {11'b10000000000,OUT_DIV_RESET[i],1'b0} ), .GTXTXRESET ( ~GTReset_n ), .LOOPBACK ( 3'b000 ), .MGTREFCLKFAB (), .MGTREFCLKRX ( {1'b0,REFCLK} ), .MGTREFCLKTX ( {1'b0,REFCLK} ), .NORTHREFCLKRX (0), .NORTHREFCLKTX (0), .PHYSTATUS ( GTX_PhyStatus[i] ), .PLLRXRESET ( 1'b0 ), .PLLTXRESET ( 1'b0 ), .PRBSCNTRESET ( 1'b0 ), .RXBUFRESET ( 1'b0 ), .RXBUFSTATUS (), .RXBYTEISALIGNED (), .RXBYTEREALIGN (), .RXCDRRESET ( 1'b0 ), .RXCHANBONDSEQ (), .RXCHANISALIGNED ( ChanIsAligned[i] ), .RXCHANREALIGN (), .RXCHARISCOMMA (), .RXCHARISK ( {RxDataK_dummy[1:0], GTX_RxDataK[(2*i)+1:2*i]} ), .RXCHBONDI ( RXCHBOND[i] ), .RXCHBONDLEVEL ( GTX_RxChbondLevel[(3*i)+2:(3*i)] ), .RXCHBONDMASTER ( (i == 0) ), .RXCHBONDO ( RXCHBOND[i+1] ), .RXCHBONDSLAVE ( (i > 0) ), .RXCLKCORCNT (), .RXCOMMADET (), .RXCOMMADETUSE ( 1'b1 ), .RXDATA ( {RxData_dummy[15:0],GTX_RxData[(16*i)+15:(16*i)+0]} ), .RXDATAVALID (), .RXDEC8B10BUSE ( RXDEC8B10BUSE ), .RXDISPERR (), .RXDLYALIGNDISABLE ( 1'b1), .RXELECIDLE ( GTX_RxElecIdle[i] ), .RXENCHANSYNC ( 1'b1 ), .RXENMCOMMAALIGN ( 1'b1 ), .RXENPCOMMAALIGN ( 1'b1 ), .RXENPMAPHASEALIGN ( 1'b0 ), .RXENPRBSTST ( 3'b0 ), .RXENSAMPLEALIGN ( 1'b0 ), .RXDLYALIGNMONENB ( 1'b1 ), .RXEQMIX ( 10'b0110000011 ), .RXGEARBOXSLIP ( 1'b0 ), .RXHEADER (), .RXHEADERVALID (), .RXLOSSOFSYNC (), .RXN ( GTX_RXN[i] ), .RXNOTINTABLE (), .RXOVERSAMPLEERR (), .RXP ( GTX_RXP[i] ), .RXPLLLKDET ( RxPLLLkDet[i] ), .RXPLLLKDETEN ( 1'b1 ), .RXPLLPOWERDOWN ( 1'b0 ), .RXPLLREFSELDY ( 3'b000 ), .RXPMASETPHASE ( 1'b0 ), .RXPOLARITY ( GTX_RxPolarity[i] ), .RXPOWERDOWN ( PowerDown[(2*i)+1:(2*i)] ), .RXPRBSERR (), .RXRATE ( {1'b1, Rate} ), .RXRATEDONE ( ), .RXRECCLK ( RXRECCLK ), .RXRECCLKPCS ( ), .RXRESET ( ~GTReset_n | local_pcs_reset | PCS_RESET[i] ), .RXRESETDONE ( GTX_RxResetDone[i] ), .RXRUNDISP (), .RXSLIDE ( 1'b0 ), .RXSTARTOFSEQ (), .RXSTATUS ( GTX_RxStatus[(3*i)+2:(3*i)] ), .RXUSRCLK ( PCLK ), .RXUSRCLK2 ( PCLK ), .RXVALID (GTX_RxValid[i]), .SOUTHREFCLKRX (0), .SOUTHREFCLKTX (0), .TSTCLK0 ( 1'b0 ), .TSTCLK1 ( 1'b0 ), .TSTIN ( {20{1'b1}} ), .TSTOUT (), .TXBUFDIFFCTRL ( 3'b111 ), .TXBUFSTATUS (), .TXBYPASS8B10B ( TXBYPASS8B10B[3:0] ), .TXCHARDISPMODE ( {3'b000, GTX_TxCompliance[i]} ), .TXCHARDISPVAL ( 4'b0000 ), .TXCHARISK ( {TxDataK_dummy[1:0], GTX_TxDataK[(2*i)+1:2*i]} ), .TXCOMINIT ( 1'b0 ), .TXCOMSAS ( 1'b0 ), .TXCOMWAKE ( 1'b0 ), .TXDATA ( {TxData_dummy[15:0], GTX_TxData[(16*i)+15:(16*i)+0]} ), .TXDEEMPH ( TxDeemph ), .TXDETECTRX ( TxDetectRx ), .TXDIFFCTRL ( 4'b1111 ), .TXDLYALIGNDISABLE ( TXDLYALIGNDISABLE[i] ), .TXDLYALIGNRESET ( TXDLYALIGNRESET[i] ), .TXELECIDLE ( GTX_TxElecIdle[i] ), .TXENC8B10BUSE ( 1'b1 ), .TXENPMAPHASEALIGN ( TXENPMAPHASEALIGN[i] ), .TXENPRBSTST (), .TXGEARBOXREADY (), .TXHEADER (0), .TXINHIBIT ( 1'b0 ), .TXKERR (), .TXMARGIN ( {TxMargin, 2'b00} ), .TXN ( GTX_TXN[i] ), .TXOUTCLK ( TXOCLK[i] ), .TXOUTCLKPCS (), .TXP ( GTX_TXP[i] ), .TXPDOWNASYNCH ( TXPdownAsynch ), .TXPLLLKDET ( ), .TXPLLLKDETEN ( 1'b0 ), .TXPLLPOWERDOWN ( 1'b0 ), .TXPLLREFSELDY ( 3'b000 ), .TXPMASETPHASE ( TXPMASETPHASE[i] ), .TXPOLARITY ( 1'b0 ), .TXPOSTEMPHASIS (0), .TXPOWERDOWN ( PowerDown[(2*i)+1:(2*i)] ), .TXPRBSFORCEERR (0), .TXPREEMPHASIS (0), .TXRATE ( {1'b1, Rate} ), .TXRESET ( ~GTReset_n | local_pcs_reset | PCS_RESET[i] ), .TXRESETDONE ( TXRESETDONE[i] ), .TXRUNDISP (), .TXSEQUENCE (0), .TXSTARTSEQ (0), .TXSWING ( TxSwing ), .TXUSRCLK ( PCLK ), .TXUSRCLK2 ( PCLK ), .USRCODEERR (0), .IGNORESIGDET (0), .PERFCLKRX (0), .PERFCLKTX (0), .RXDLYALIGNMONITOR (), .RXDLYALIGNOVERRIDE ( 1'b0 ), .RXDLYALIGNRESET (0), .RXDLYALIGNSWPPRECURB ( 1'b1 ), .RXDLYALIGNUPDSW ( 1'b0 ), .TXDLYALIGNMONITOR (), .TXDLYALIGNOVERRIDE ( 1'b0 ), .TXDLYALIGNUPDSW ( 1'b0 ), .TXDLYALIGNMONENB ( 1'b1 ), .TXRATEDONE ( TXRATEDONE[i] ) ); end end endgenerate endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/interrupt.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: interrupt.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Manages the interrupt vector and sends interrupts. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_INTR_IDLE 2'd0 `define S_INTR_INTR 2'd1 `define S_INTR_CLR_0 2'd2 `define S_INTR_CLR_1 2'd3 module interrupt #( parameter C_NUM_CHNL = 4'd12 ) ( input CLK, input RST, input [C_NUM_CHNL-1:0] RX_SG_BUF_RECVD, // The scatter gather data for a rx_port transaction has been read input [C_NUM_CHNL-1:0] RX_TXN_DONE, // The rx_port transaction is done input [C_NUM_CHNL-1:0] TX_TXN, // New tx_port transaction input [C_NUM_CHNL-1:0] TX_SG_BUF_RECVD, // The scatter gather data for a tx_port transaction has been read input [C_NUM_CHNL-1:0] TX_TXN_DONE, // The tx_port transaction is done input VECT_0_RST, // Interrupt vector 0 reset input VECT_1_RST, // Interrupt vector 1 reset input [31:0] VECT_RST, // Interrupt vector reset value output [31:0] VECT_0, // Interrupt vector 0 output [31:0] VECT_1, // Interrupt vector 1 input INTR_LEGACY_CLR, // Pulsed high to ack the legacy interrupt and clear it input CONFIG_INTERRUPT_MSIENABLE, // 1 if MSI interrupts are enable, 0 if only legacy are supported input INTR_MSI_RDY, // High when interrupt is able to be sent output INTR_MSI_REQUEST // High to request interrupt, when both INTR_MSI_RDY and INTR_MSI_REQUEST are high, interrupt is sent ); reg [1:0] rState=0; reg [31:0] rVect0=0; reg [31:0] rVect1=0; wire [31:0] wVect0; wire [31:0] wVect1; wire wIntr = (rState == `S_INTR_INTR); wire wIntrDone; assign VECT_0 = rVect0; assign VECT_1 = rVect1; // Align the input signals to the interrupt vector. // VECT_0/VECT_1 are organized from right to left (LSB to MSB) as: // [ 0] TX_TXN for channel 0 in VECT_0, channel 6 in VECT_1 // [ 1] TX_SG_BUF_RECVD for channel 0 in VECT_0, channel 6 in VECT_1 // [ 2] TX_TXN_DONE for channel 0 in VECT_0, channel 6 in VECT_1 // [ 3] RX_SG_BUF_RECVD for channel 0 in VECT_0, channel 6 in VECT_1 // [ 4] RX_TXN_DONE for channel 0 in VECT_0, channel 6 in VECT_1 // ... // [25] TX_TXN for channel 5 in VECT_0, channel 11 in VECT_1 // [26] TX_SG_BUF_RECVD for channel 5 in VECT_0, channel 11 in VECT_1 // [27] TX_TXN_DONE for channel 5 in VECT_0, channel 11 in VECT_1 // [28] RX_SG_BUF_RECVD for channel 5 in VECT_0, channel 11 in VECT_1 // [29] RX_TXN_DONE for channel 5 in VECT_0, channel 11 in VECT_1 // Positions 30 - 31 in both VECT_0 and VECT_1 are zero. genvar i; generate for (i = 0; i < C_NUM_CHNL; i = i + 1) begin: vectMap if (i < 6) begin : vectMap0 assign wVect0[(5*i)+0] = TX_TXN[i]; assign wVect0[(5*i)+1] = TX_SG_BUF_RECVD[i]; assign wVect0[(5*i)+2] = TX_TXN_DONE[i]; assign wVect0[(5*i)+3] = RX_SG_BUF_RECVD[i]; assign wVect0[(5*i)+4] = RX_TXN_DONE[i]; end else begin : vectMap1 assign wVect1[(5*(i-6))+0] = TX_TXN[i]; assign wVect1[(5*(i-6))+1] = TX_SG_BUF_RECVD[i]; assign wVect1[(5*(i-6))+2] = TX_TXN_DONE[i]; assign wVect1[(5*(i-6))+3] = RX_SG_BUF_RECVD[i]; assign wVect1[(5*(i-6))+4] = RX_TXN_DONE[i]; end end for (i = C_NUM_CHNL; i < 12; i = i + 1) begin: vectZero if (i < 6) begin : vectZero0 assign wVect0[(5*i)+0] = 1'b0; assign wVect0[(5*i)+1] = 1'b0; assign wVect0[(5*i)+2] = 1'b0; assign wVect0[(5*i)+3] = 1'b0; assign wVect0[(5*i)+4] = 1'b0; end else begin : vectZero1 assign wVect1[(5*(i-6))+0] = 1'b0; assign wVect1[(5*(i-6))+1] = 1'b0; assign wVect1[(5*(i-6))+2] = 1'b0; assign wVect1[(5*(i-6))+3] = 1'b0; assign wVect1[(5*(i-6))+4] = 1'b0; end end assign wVect0[30] = 1'b0; assign wVect0[31] = 1'b0; assign wVect1[30] = 1'b0; assign wVect1[31] = 1'b0; endgenerate // Interrupt controller interrupt_controller intrCtlr ( .CLK(CLK), .RST(RST), .INTR(wIntr), .INTR_LEGACY_CLR(INTR_LEGACY_CLR), .INTR_DONE(wIntrDone), .CFG_INTERRUPT_ASSERT(), .CONFIG_INTERRUPT_MSIENABLE(CONFIG_INTERRUPT_MSIENABLE), .INTR_MSI_RDY(INTR_MSI_RDY), .INTR_MSI_REQUEST(INTR_MSI_REQUEST) ); // Update the interrupt vector when new signals come in (pulse in) and on reset. always @(posedge CLK) begin if (RST) begin rVect0 <= #1 0; rVect1 <= #1 0; end else begin if (VECT_0_RST) begin rVect0 <= #1 (wVect0 | (rVect0 & ~VECT_RST)); rVect1 <= #1 (wVect1 | rVect1); end else if (VECT_1_RST) begin rVect0 <= #1 (wVect0 | rVect0); rVect1 <= #1 (wVect1 | (rVect1 & ~VECT_RST)); end else begin rVect0 <= #1 (wVect0 | rVect0); rVect1 <= #1 (wVect1 | rVect1); end end end // Fire the interrupt when we have a non-zero vector. always @(posedge CLK) begin if (RST) begin rState <= #1 `S_INTR_IDLE; end else begin case (rState) `S_INTR_IDLE : rState <= #1 ((rVect0 | rVect1) == 0 ? `S_INTR_IDLE : `S_INTR_INTR); `S_INTR_INTR : rState <= #1 (wIntrDone ? `S_INTR_CLR_0 : `S_INTR_INTR); `S_INTR_CLR_0 : rState <= #1 (VECT_0_RST ? (C_NUM_CHNL > 6 ? `S_INTR_CLR_1 : `S_INTR_IDLE) : `S_INTR_CLR_0); `S_INTR_CLR_1 : rState <= #1 (VECT_1_RST ? `S_INTR_IDLE : `S_INTR_CLR_1); endcase end end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/interrupt_controller.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: interrupt_controller.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Signals an interrupt on the Xilnx PCIe Endpoint // interface. Supports single vector MSI or legacy based // interrupts. // When INTR is pulsed high, the interrupt will be issued // as soon as possible. If using legacy interrupts, the // initial interrupt must be cleared by another request // (typically a PIO read or write request to the // endpoint at some predetermined BAR address). Receipt of // the "clear" acknowledgment should cause INTR_LEGACY_CLR // input to pulse high. Thus completing the legacy // interrupt cycle. If using MSI interrupts, no such // acknowldegment is necessary. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_INTRCTLR_IDLE 3'd0 `define S_INTRCLTR_WORKING 3'd1 `define S_INTRCLTR_COMPLETE 3'd2 `define S_INTRCLTR_CLEAR_LEGACY 3'd3 `define S_INTRCLTR_CLEARING_LEGACY 3'd4 `define S_INTRCLTR_DONE 3'd5 module interrupt_controller ( input CLK, // System clock input RST, // Async reset input INTR, // Pulsed high to request an interrupt input INTR_LEGACY_CLR, // Pulsed high to ack the legacy interrupt and clear it output INTR_DONE, // Pulsed high to signal interrupt sent input CONFIG_INTERRUPT_MSIENABLE, // 1 if MSI interrupts are enable, 0 if only legacy are supported output CFG_INTERRUPT_ASSERT, // Legacy interrupt message type input INTR_MSI_RDY, // High when interrupt is able to be sent output INTR_MSI_REQUEST // High to request interrupt, when both INTR_MSI_RDY and INTR_MSI_REQUEST are high, interrupt is sent ); reg [2:0] rState=`S_INTRCTLR_IDLE; reg [2:0] rStateNext=`S_INTRCTLR_IDLE; reg rIntr=0; reg rIntrAssert=0; assign INTR_DONE = (rState == `S_INTRCLTR_DONE); assign INTR_MSI_REQUEST = rIntr; assign CFG_INTERRUPT_ASSERT = rIntrAssert; // Control sending interrupts. always @(*) begin case (rState) `S_INTRCTLR_IDLE : begin if (INTR) begin rIntr = 1; rIntrAssert = !CONFIG_INTERRUPT_MSIENABLE; rStateNext = (INTR_MSI_RDY ? `S_INTRCLTR_COMPLETE : `S_INTRCLTR_WORKING); end else begin rIntr = 0; rIntrAssert = 0; rStateNext = `S_INTRCTLR_IDLE; end end `S_INTRCLTR_WORKING : begin rIntr = 1; rIntrAssert = !CONFIG_INTERRUPT_MSIENABLE; rStateNext = (INTR_MSI_RDY ? `S_INTRCLTR_COMPLETE : `S_INTRCLTR_WORKING); end `S_INTRCLTR_COMPLETE : begin rIntr = 0; rIntrAssert = !CONFIG_INTERRUPT_MSIENABLE; rStateNext = (CONFIG_INTERRUPT_MSIENABLE ? `S_INTRCLTR_DONE : `S_INTRCLTR_CLEAR_LEGACY); end `S_INTRCLTR_CLEAR_LEGACY : begin if (INTR_LEGACY_CLR) begin rIntr = 1; rIntrAssert = 0; rStateNext = (INTR_MSI_RDY ? `S_INTRCLTR_DONE : `S_INTRCLTR_CLEARING_LEGACY); end else begin rIntr = 0; rIntrAssert = 1; rStateNext = `S_INTRCLTR_CLEAR_LEGACY; end end `S_INTRCLTR_CLEARING_LEGACY : begin rIntr = 1; rIntrAssert = 0; rStateNext = (INTR_MSI_RDY ? `S_INTRCLTR_DONE : `S_INTRCLTR_CLEARING_LEGACY); end `S_INTRCLTR_DONE : begin rIntr = 0; rIntrAssert = 0; rStateNext = `S_INTRCTLR_IDLE; end default: begin rIntr = 0; rIntrAssert = 0; rStateNext = `S_INTRCTLR_IDLE; end endcase end // Update the state. always @(posedge CLK) begin if (RST) rState <= #1 `S_INTRCTLR_IDLE; else rState <= #1 rStateNext; end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/pcie_2_0_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : pcie_2_0_v6.v // Version : 2.4 //-- Description: Solution wrapper for Virtex6 Hard Block for PCI Express //-- //-- //-- //-------------------------------------------------------------------------------- `timescale 1ps/1ps module pcie_2_0_v6 #( parameter TCQ = 1, parameter REF_CLK_FREQ = 0, // 0 - 100 MHz, 1 - 125 MHz, 2 - 250 MHz parameter PIPE_PIPELINE_STAGES = 0, // 0 - 0 stages, 1 - 1 stage, 2 - 2 stages parameter AER_BASE_PTR = 12'h128, parameter AER_CAP_ECRC_CHECK_CAPABLE = "FALSE", parameter AER_CAP_ECRC_GEN_CAPABLE = "FALSE", parameter AER_CAP_ID = 16'h0001, parameter AER_CAP_INT_MSG_NUM_MSI = 5'h0a, parameter AER_CAP_INT_MSG_NUM_MSIX = 5'h15, parameter AER_CAP_NEXTPTR = 12'h160, parameter AER_CAP_ON = "FALSE", parameter AER_CAP_PERMIT_ROOTERR_UPDATE = "TRUE", parameter AER_CAP_VERSION = 4'h1, parameter ALLOW_X8_GEN2 = "TRUE", parameter BAR0 = 32'hffffff00, parameter BAR1 = 32'hffff0000, parameter BAR2 = 32'hffff000c, parameter BAR3 = 32'hffffffff, parameter BAR4 = 32'h00000000, parameter BAR5 = 32'h00000000, parameter CAPABILITIES_PTR = 8'h40, parameter CARDBUS_CIS_POINTER = 32'h00000000, parameter CLASS_CODE = 24'h000000, parameter CMD_INTX_IMPLEMENTED = "TRUE", parameter CPL_TIMEOUT_DISABLE_SUPPORTED = "FALSE", parameter CPL_TIMEOUT_RANGES_SUPPORTED = 4'h0, parameter CRM_MODULE_RSTS = 7'h00, parameter DEV_CAP_ENABLE_SLOT_PWR_LIMIT_SCALE = "TRUE", parameter DEV_CAP_ENABLE_SLOT_PWR_LIMIT_VALUE = "TRUE", parameter DEV_CAP_ENDPOINT_L0S_LATENCY = 0, parameter DEV_CAP_ENDPOINT_L1_LATENCY = 0, parameter DEV_CAP_EXT_TAG_SUPPORTED = "TRUE", parameter DEV_CAP_FUNCTION_LEVEL_RESET_CAPABLE = "FALSE", parameter DEV_CAP_MAX_PAYLOAD_SUPPORTED = 2, parameter DEV_CAP_PHANTOM_FUNCTIONS_SUPPORT = 0, parameter DEV_CAP_ROLE_BASED_ERROR = "TRUE", parameter DEV_CAP_RSVD_14_12 = 0, parameter DEV_CAP_RSVD_17_16 = 0, parameter DEV_CAP_RSVD_31_29 = 0, parameter DEV_CONTROL_AUX_POWER_SUPPORTED = "FALSE", parameter DEVICE_ID = 16'h0007, parameter DISABLE_ASPM_L1_TIMER = "FALSE", parameter DISABLE_BAR_FILTERING = "FALSE", parameter DISABLE_ID_CHECK = "FALSE", parameter DISABLE_LANE_REVERSAL = "FALSE", parameter DISABLE_RX_TC_FILTER = "FALSE", parameter DISABLE_SCRAMBLING = "FALSE", parameter DNSTREAM_LINK_NUM = 8'h00, parameter DSN_BASE_PTR = 12'h100, parameter DSN_CAP_ID = 16'h0003, parameter DSN_CAP_NEXTPTR = 12'h000, parameter DSN_CAP_ON = "TRUE", parameter DSN_CAP_VERSION = 4'h1, parameter ENABLE_MSG_ROUTE = 11'h000, parameter ENABLE_RX_TD_ECRC_TRIM = "FALSE", parameter ENTER_RVRY_EI_L0 = "TRUE", parameter EXPANSION_ROM = 32'hfffff001, parameter EXT_CFG_CAP_PTR = 6'h3f, parameter EXT_CFG_XP_CAP_PTR = 10'h3ff, parameter HEADER_TYPE = 8'h00, parameter INFER_EI = 5'h00, parameter INTERRUPT_PIN = 8'h01, parameter IS_SWITCH = "FALSE", parameter LAST_CONFIG_DWORD = 10'h042, parameter LINK_CAP_ASPM_SUPPORT = 1, parameter LINK_CAP_CLOCK_POWER_MANAGEMENT = "FALSE", parameter LINK_CAP_DLL_LINK_ACTIVE_REPORTING_CAP = "FALSE", parameter LINK_CAP_LINK_BANDWIDTH_NOTIFICATION_CAP = "FALSE", parameter LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN1 = 7, parameter LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN2 = 7, parameter LINK_CAP_L0S_EXIT_LATENCY_GEN1 = 7, parameter LINK_CAP_L0S_EXIT_LATENCY_GEN2 = 7, parameter LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN1 = 7, parameter LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN2 = 7, parameter LINK_CAP_L1_EXIT_LATENCY_GEN1 = 7, parameter LINK_CAP_L1_EXIT_LATENCY_GEN2 = 7, parameter LINK_CAP_MAX_LINK_SPEED = 4'h1, parameter LINK_CAP_MAX_LINK_WIDTH = 6'h08, parameter LINK_CAP_RSVD_23_22 = 0, parameter LINK_CAP_SURPRISE_DOWN_ERROR_CAPABLE = "FALSE", parameter LINK_CONTROL_RCB = 0, parameter LINK_CTRL2_DEEMPHASIS = "FALSE", parameter LINK_CTRL2_HW_AUTONOMOUS_SPEED_DISABLE = "FALSE", parameter LINK_CTRL2_TARGET_LINK_SPEED = 4'h0, parameter LINK_STATUS_SLOT_CLOCK_CONFIG = "TRUE", parameter LL_ACK_TIMEOUT = 15'h0204, parameter LL_ACK_TIMEOUT_EN = "FALSE", parameter LL_ACK_TIMEOUT_FUNC = 0, parameter LL_REPLAY_TIMEOUT = 15'h060d, parameter LL_REPLAY_TIMEOUT_EN = "FALSE", parameter LL_REPLAY_TIMEOUT_FUNC = 0, parameter LTSSM_MAX_LINK_WIDTH = LINK_CAP_MAX_LINK_WIDTH, parameter MSI_BASE_PTR = 8'h48, parameter MSI_CAP_ID = 8'h05, parameter MSI_CAP_MULTIMSGCAP = 0, parameter MSI_CAP_MULTIMSG_EXTENSION = 0, parameter MSI_CAP_NEXTPTR = 8'h60, parameter MSI_CAP_ON = "FALSE", parameter MSI_CAP_PER_VECTOR_MASKING_CAPABLE = "TRUE", parameter MSI_CAP_64_BIT_ADDR_CAPABLE = "TRUE", parameter MSIX_BASE_PTR = 8'h9c, parameter MSIX_CAP_ID = 8'h11, parameter MSIX_CAP_NEXTPTR = 8'h00, parameter MSIX_CAP_ON = "FALSE", parameter MSIX_CAP_PBA_BIR = 0, parameter MSIX_CAP_PBA_OFFSET = 29'h00000050, parameter MSIX_CAP_TABLE_BIR = 0, parameter MSIX_CAP_TABLE_OFFSET = 29'h00000040, parameter MSIX_CAP_TABLE_SIZE = 11'h000, parameter N_FTS_COMCLK_GEN1 = 255, parameter N_FTS_COMCLK_GEN2 = 255, parameter N_FTS_GEN1 = 255, parameter N_FTS_GEN2 = 255, parameter PCIE_BASE_PTR = 8'h60, parameter PCIE_CAP_CAPABILITY_ID = 8'h10, parameter PCIE_CAP_CAPABILITY_VERSION = 4'h2, parameter PCIE_CAP_DEVICE_PORT_TYPE = 4'h0, parameter PCIE_CAP_INT_MSG_NUM = 5'h00, parameter PCIE_CAP_NEXTPTR = 8'h00, parameter PCIE_CAP_ON = "TRUE", parameter PCIE_CAP_RSVD_15_14 = 0, parameter PCIE_CAP_SLOT_IMPLEMENTED = "FALSE", parameter PCIE_REVISION = 2, parameter PGL0_LANE = 0, parameter PGL1_LANE = 1, parameter PGL2_LANE = 2, parameter PGL3_LANE = 3, parameter PGL4_LANE = 4, parameter PGL5_LANE = 5, parameter PGL6_LANE = 6, parameter PGL7_LANE = 7, parameter PL_AUTO_CONFIG = 0, parameter PL_FAST_TRAIN = "FALSE", parameter PM_BASE_PTR = 8'h40, parameter PM_CAP_AUXCURRENT = 0, parameter PM_CAP_DSI = "FALSE", parameter PM_CAP_D1SUPPORT = "TRUE", parameter PM_CAP_D2SUPPORT = "TRUE", parameter PM_CAP_ID = 8'h01, parameter PM_CAP_NEXTPTR = 8'h48, parameter PM_CAP_ON = "TRUE", parameter PM_CAP_PME_CLOCK = "FALSE", parameter PM_CAP_PMESUPPORT = 5'h0f, parameter PM_CAP_RSVD_04 = 0, parameter PM_CAP_VERSION = 3, parameter PM_CSR_BPCCEN = "FALSE", parameter PM_CSR_B2B3 = "FALSE", parameter PM_CSR_NOSOFTRST = "TRUE", parameter PM_DATA_SCALE0 = 2'h1, parameter PM_DATA_SCALE1 = 2'h1, parameter PM_DATA_SCALE2 = 2'h1, parameter PM_DATA_SCALE3 = 2'h1, parameter PM_DATA_SCALE4 = 2'h1, parameter PM_DATA_SCALE5 = 2'h1, parameter PM_DATA_SCALE6 = 2'h1, parameter PM_DATA_SCALE7 = 2'h1, parameter PM_DATA0 = 8'h01, parameter PM_DATA1 = 8'h01, parameter PM_DATA2 = 8'h01, parameter PM_DATA3 = 8'h01, parameter PM_DATA4 = 8'h01, parameter PM_DATA5 = 8'h01, parameter PM_DATA6 = 8'h01, parameter PM_DATA7 = 8'h01, parameter RECRC_CHK = 0, parameter RECRC_CHK_TRIM = "FALSE", parameter REVISION_ID = 8'h00, parameter ROOT_CAP_CRS_SW_VISIBILITY = "FALSE", parameter SELECT_DLL_IF = "FALSE", parameter SLOT_CAP_ATT_BUTTON_PRESENT = "FALSE", parameter SLOT_CAP_ATT_INDICATOR_PRESENT = "FALSE", parameter SLOT_CAP_ELEC_INTERLOCK_PRESENT = "FALSE", parameter SLOT_CAP_HOTPLUG_CAPABLE = "FALSE", parameter SLOT_CAP_HOTPLUG_SURPRISE = "FALSE", parameter SLOT_CAP_MRL_SENSOR_PRESENT = "FALSE", parameter SLOT_CAP_NO_CMD_COMPLETED_SUPPORT = "FALSE", parameter SLOT_CAP_PHYSICAL_SLOT_NUM = 13'h0000, parameter SLOT_CAP_POWER_CONTROLLER_PRESENT = "FALSE", parameter SLOT_CAP_POWER_INDICATOR_PRESENT = "FALSE", parameter SLOT_CAP_SLOT_POWER_LIMIT_SCALE = 0, parameter SLOT_CAP_SLOT_POWER_LIMIT_VALUE = 8'h00, parameter SPARE_BIT0 = 0, parameter SPARE_BIT1 = 0, parameter SPARE_BIT2 = 0, parameter SPARE_BIT3 = 0, parameter SPARE_BIT4 = 0, parameter SPARE_BIT5 = 0, parameter SPARE_BIT6 = 0, parameter SPARE_BIT7 = 0, parameter SPARE_BIT8 = 0, parameter SPARE_BYTE0 = 8'h00, parameter SPARE_BYTE1 = 8'h00, parameter SPARE_BYTE2 = 8'h00, parameter SPARE_BYTE3 = 8'h00, parameter SPARE_WORD0 = 32'h00000000, parameter SPARE_WORD1 = 32'h00000000, parameter SPARE_WORD2 = 32'h00000000, parameter SPARE_WORD3 = 32'h00000000, parameter SUBSYSTEM_ID = 16'h0007, parameter SUBSYSTEM_VENDOR_ID = 16'h10ee, parameter TL_RBYPASS = "FALSE", parameter TL_RX_RAM_RADDR_LATENCY = 0, parameter TL_RX_RAM_RDATA_LATENCY = 2, parameter TL_RX_RAM_WRITE_LATENCY = 0, parameter TL_TFC_DISABLE = "FALSE", parameter TL_TX_CHECKS_DISABLE = "FALSE", parameter TL_TX_RAM_RADDR_LATENCY = 0, parameter TL_TX_RAM_RDATA_LATENCY = 2, parameter TL_TX_RAM_WRITE_LATENCY = 0, parameter UPCONFIG_CAPABLE = "TRUE", parameter UPSTREAM_FACING = "TRUE", parameter EXIT_LOOPBACK_ON_EI = "TRUE", parameter UR_INV_REQ = "TRUE", parameter USER_CLK_FREQ = 3, parameter VC_BASE_PTR = 12'h10c, parameter VC_CAP_ID = 16'h0002, parameter VC_CAP_NEXTPTR = 12'h000, parameter VC_CAP_ON = "FALSE", parameter VC_CAP_REJECT_SNOOP_TRANSACTIONS = "FALSE", parameter VC_CAP_VERSION = 4'h1, parameter VC0_CPL_INFINITE = "TRUE", parameter VC0_RX_RAM_LIMIT = 13'h03ff, parameter VC0_TOTAL_CREDITS_CD = 127, parameter VC0_TOTAL_CREDITS_CH = 31, parameter VC0_TOTAL_CREDITS_NPH = 12, parameter VC0_TOTAL_CREDITS_PD = 288, parameter VC0_TOTAL_CREDITS_PH = 32, parameter VC0_TX_LASTPACKET = 31, parameter VENDOR_ID = 16'h10ee, parameter VSEC_BASE_PTR = 12'h160, parameter VSEC_CAP_HDR_ID = 16'h1234, parameter VSEC_CAP_HDR_LENGTH = 12'h018, parameter VSEC_CAP_HDR_REVISION = 4'h1, parameter VSEC_CAP_ID = 16'h000b, parameter VSEC_CAP_IS_LINK_VISIBLE = "TRUE", parameter VSEC_CAP_NEXTPTR = 12'h000, parameter VSEC_CAP_ON = "FALSE", parameter VSEC_CAP_VERSION = 4'h1 ) ( input [(LINK_CAP_MAX_LINK_WIDTH - 1) : 0] PCIEXPRXN, input [(LINK_CAP_MAX_LINK_WIDTH - 1) : 0] PCIEXPRXP, output [(LINK_CAP_MAX_LINK_WIDTH - 1) : 0] PCIEXPTXN, output [(LINK_CAP_MAX_LINK_WIDTH - 1) : 0] PCIEXPTXP, input SYSCLK, input FUNDRSTN, output TRNLNKUPN, output PHYRDYN, output USERRSTN, output RECEIVEDFUNCLVLRSTN, output LNKCLKEN, input SYSRSTN, input PLRSTN, input DLRSTN, input TLRSTN, input FUNCLVLRSTN, input CMRSTN, input CMSTICKYRSTN, output [6:0] TRNRBARHITN, output [63:0] TRNRD, output TRNRECRCERRN, output TRNREOFN, output TRNRERRFWDN, output TRNRREMN, output TRNRSOFN, output TRNRSRCDSCN, output TRNRSRCRDYN, input TRNRDSTRDYN, input TRNRNPOKN, output [5:0] TRNTBUFAV, output TRNTCFGREQN, output TRNTDLLPDSTRDYN, output TRNTDSTRDYN, output TRNTERRDROPN, input TRNTCFGGNTN, input [63:0] TRNTD, input [31:0] TRNTDLLPDATA, input TRNTDLLPSRCRDYN, input TRNTECRCGENN, input TRNTEOFN, input TRNTERRFWDN, input TRNTREMN, input TRNTSOFN, input TRNTSRCDSCN, input TRNTSRCRDYN, input TRNTSTRN, output [11:0] TRNFCCPLD, output [7:0] TRNFCCPLH, output [11:0] TRNFCNPD, output [7:0] TRNFCNPH, output [11:0] TRNFCPD, output [7:0] TRNFCPH, input [2:0] TRNFCSEL, output CFGAERECRCCHECKEN, output CFGAERECRCGENEN, output CFGCOMMANDBUSMASTERENABLE, output CFGCOMMANDINTERRUPTDISABLE, output CFGCOMMANDIOENABLE, output CFGCOMMANDMEMENABLE, output CFGCOMMANDSERREN, output CFGDEVCONTROLAUXPOWEREN, output CFGDEVCONTROLCORRERRREPORTINGEN, output CFGDEVCONTROLENABLERO, output CFGDEVCONTROLEXTTAGEN, output CFGDEVCONTROLFATALERRREPORTINGEN, output [2:0] CFGDEVCONTROLMAXPAYLOAD, output [2:0] CFGDEVCONTROLMAXREADREQ, output CFGDEVCONTROLNONFATALREPORTINGEN, output CFGDEVCONTROLNOSNOOPEN, output CFGDEVCONTROLPHANTOMEN, output CFGDEVCONTROLURERRREPORTINGEN, output CFGDEVCONTROL2CPLTIMEOUTDIS, output [3:0] CFGDEVCONTROL2CPLTIMEOUTVAL, output CFGDEVSTATUSCORRERRDETECTED, output CFGDEVSTATUSFATALERRDETECTED, output CFGDEVSTATUSNONFATALERRDETECTED, output CFGDEVSTATUSURDETECTED, output [31:0] CFGDO, output CFGERRAERHEADERLOGSETN, output CFGERRCPLRDYN, output [7:0] CFGINTERRUPTDO, output [2:0] CFGINTERRUPTMMENABLE, output CFGINTERRUPTMSIENABLE, output CFGINTERRUPTMSIXENABLE, output CFGINTERRUPTMSIXFM, output CFGINTERRUPTRDYN, output CFGLINKCONTROLRCB, output [1:0] CFGLINKCONTROLASPMCONTROL, output CFGLINKCONTROLAUTOBANDWIDTHINTEN, output CFGLINKCONTROLBANDWIDTHINTEN, output CFGLINKCONTROLCLOCKPMEN, output CFGLINKCONTROLCOMMONCLOCK, output CFGLINKCONTROLEXTENDEDSYNC, output CFGLINKCONTROLHWAUTOWIDTHDIS, output CFGLINKCONTROLLINKDISABLE, output CFGLINKCONTROLRETRAINLINK, output CFGLINKSTATUSAUTOBANDWIDTHSTATUS, output CFGLINKSTATUSBANDWITHSTATUS, output [1:0] CFGLINKSTATUSCURRENTSPEED, output CFGLINKSTATUSDLLACTIVE, output CFGLINKSTATUSLINKTRAINING, output [3:0] CFGLINKSTATUSNEGOTIATEDWIDTH, output [15:0] CFGMSGDATA, output CFGMSGRECEIVED, output CFGMSGRECEIVEDASSERTINTA, output CFGMSGRECEIVEDASSERTINTB, output CFGMSGRECEIVEDASSERTINTC, output CFGMSGRECEIVEDASSERTINTD, output CFGMSGRECEIVEDDEASSERTINTA, output CFGMSGRECEIVEDDEASSERTINTB, output CFGMSGRECEIVEDDEASSERTINTC, output CFGMSGRECEIVEDDEASSERTINTD, output CFGMSGRECEIVEDERRCOR, output CFGMSGRECEIVEDERRFATAL, output CFGMSGRECEIVEDERRNONFATAL, output CFGMSGRECEIVEDPMASNAK, output CFGMSGRECEIVEDPMETO, output CFGMSGRECEIVEDPMETOACK, output CFGMSGRECEIVEDPMPME, output CFGMSGRECEIVEDSETSLOTPOWERLIMIT, output CFGMSGRECEIVEDUNLOCK, output [2:0] CFGPCIELINKSTATE, output CFGPMCSRPMEEN, output CFGPMCSRPMESTATUS, output [1:0] CFGPMCSRPOWERSTATE, output CFGPMRCVASREQL1N, output CFGPMRCVENTERL1N, output CFGPMRCVENTERL23N, output CFGPMRCVREQACKN, output CFGRDWRDONEN, output CFGSLOTCONTROLELECTROMECHILCTLPULSE, output CFGTRANSACTION, output [6:0] CFGTRANSACTIONADDR, output CFGTRANSACTIONTYPE, output [6:0] CFGVCTCVCMAP, input [3:0] CFGBYTEENN, input [31:0] CFGDI, input [7:0] CFGDSBUSNUMBER, input [4:0] CFGDSDEVICENUMBER, input [2:0] CFGDSFUNCTIONNUMBER, input [63:0] CFGDSN, input [9:0] CFGDWADDR, input CFGERRACSN, input [127:0] CFGERRAERHEADERLOG, input CFGERRCORN, input CFGERRCPLABORTN, input CFGERRCPLTIMEOUTN, input CFGERRCPLUNEXPECTN, input CFGERRECRCN, input CFGERRLOCKEDN, input CFGERRPOSTEDN, input [47:0] CFGERRTLPCPLHEADER, input CFGERRURN, input CFGINTERRUPTASSERTN, input [7:0] CFGINTERRUPTDI, input CFGINTERRUPTN, input CFGPMDIRECTASPML1N, input CFGPMSENDPMACKN, input CFGPMSENDPMETON, input CFGPMSENDPMNAKN, input CFGPMTURNOFFOKN, input CFGPMWAKEN, input [7:0] CFGPORTNUMBER, input CFGRDENN, input CFGTRNPENDINGN, input CFGWRENN, input CFGWRREADONLYN, input CFGWRRW1CASRWN, output [2:0] PLINITIALLINKWIDTH, output [1:0] PLLANEREVERSALMODE, output PLLINKGEN2CAP, output PLLINKPARTNERGEN2SUPPORTED, output PLLINKUPCFGCAP, output [5:0] PLLTSSMSTATE, output PLPHYLNKUPN, output PLRECEIVEDHOTRST, output [1:0] PLRXPMSTATE, output PLSELLNKRATE, output [1:0] PLSELLNKWIDTH, output [2:0] PLTXPMSTATE, input PLDIRECTEDLINKAUTON, input [1:0] PLDIRECTEDLINKCHANGE, input PLDIRECTEDLINKSPEED, input [1:0] PLDIRECTEDLINKWIDTH, input PLDOWNSTREAMDEEMPHSOURCE, input PLUPSTREAMPREFERDEEMPH, input PLTRANSMITHOTRST, output DBGSCLRA, output DBGSCLRB, output DBGSCLRC, output DBGSCLRD, output DBGSCLRE, output DBGSCLRF, output DBGSCLRG, output DBGSCLRH, output DBGSCLRI, output DBGSCLRJ, output DBGSCLRK, output [63:0] DBGVECA, output [63:0] DBGVECB, output [11:0] DBGVECC, output [11:0] PLDBGVEC, input [1:0] DBGMODE, input DBGSUBMODE, input [2:0] PLDBGMODE, output [15:0] PCIEDRPDO, output PCIEDRPDRDY, input PCIEDRPCLK, input [8:0] PCIEDRPDADDR, input PCIEDRPDEN, input [15:0] PCIEDRPDI, input PCIEDRPDWE, output GTPLLLOCK, input PIPECLK, input USERCLK, input DRPCLK, input CLOCKLOCKED, output TxOutClk, output [31:0] TRNRDLLPDATA, output TRNRDLLPSRCRDYN ); // wire declarations wire LL2BADDLLPERRN; wire LL2BADTLPERRN; wire LL2PROTOCOLERRN; wire LL2REPLAYROERRN; wire LL2REPLAYTOERRN; wire LL2SUSPENDOKN; wire LL2TFCINIT1SEQN; wire LL2TFCINIT2SEQN; wire [12:0] MIMRXRADDR; wire MIMRXRCE; wire MIMRXREN; wire [12:0] MIMRXWADDR; wire [67:0] MIMRXWDATA; wire MIMRXWEN; wire [12:0] MIMTXRADDR; wire MIMTXRCE; wire MIMTXREN; wire [12:0] MIMTXWADDR; wire [68:0] MIMTXWDATA; wire MIMTXWEN; wire PIPERX0POLARITY; wire PIPERX1POLARITY; wire PIPERX2POLARITY; wire PIPERX3POLARITY; wire PIPERX4POLARITY; wire PIPERX5POLARITY; wire PIPERX6POLARITY; wire PIPERX7POLARITY; wire PIPETXDEEMPH; wire [2:0] PIPETXMARGIN; wire PIPETXRATE; wire PIPETXRCVRDET; wire PIPETXRESET; wire [1:0] PIPETX0CHARISK; wire PIPETX0COMPLIANCE; wire [15:0] PIPETX0DATA; wire PIPETX0ELECIDLE; wire [1:0] PIPETX0POWERDOWN; wire [1:0] PIPETX1CHARISK; wire PIPETX1COMPLIANCE; wire [15:0] PIPETX1DATA; wire PIPETX1ELECIDLE; wire [1:0] PIPETX1POWERDOWN; wire [1:0] PIPETX2CHARISK; wire PIPETX2COMPLIANCE; wire [15:0] PIPETX2DATA; wire PIPETX2ELECIDLE; wire [1:0] PIPETX2POWERDOWN; wire [1:0] PIPETX3CHARISK; wire PIPETX3COMPLIANCE; wire [15:0] PIPETX3DATA; wire PIPETX3ELECIDLE; wire [1:0] PIPETX3POWERDOWN; wire [1:0] PIPETX4CHARISK; wire PIPETX4COMPLIANCE; wire [15:0] PIPETX4DATA; wire PIPETX4ELECIDLE; wire [1:0] PIPETX4POWERDOWN; wire [1:0] PIPETX5CHARISK; wire PIPETX5COMPLIANCE; wire [15:0] PIPETX5DATA; wire PIPETX5ELECIDLE; wire [1:0] PIPETX5POWERDOWN; wire [1:0] PIPETX6CHARISK; wire PIPETX6COMPLIANCE; wire [15:0] PIPETX6DATA; wire PIPETX6ELECIDLE; wire [1:0] PIPETX6POWERDOWN; wire [1:0] PIPETX7CHARISK; wire PIPETX7COMPLIANCE; wire [15:0] PIPETX7DATA; wire PIPETX7ELECIDLE; wire [1:0] PIPETX7POWERDOWN; wire PL2LINKUPN; wire PL2RECEIVERERRN; wire PL2RECOVERYN; wire PL2RXELECIDLE; wire PL2SUSPENDOK; wire TL2ASPMSUSPENDCREDITCHECKOKN; wire TL2ASPMSUSPENDREQN; wire TL2PPMSUSPENDOKN; wire LL2SENDASREQL1N = 1'b1; wire LL2SENDENTERL1N = 1'b1; wire LL2SENDENTERL23N = 1'b1; wire LL2SUSPENDNOWN = 1'b1; wire LL2TLPRCVN = 1'b1; wire [71:0] MIMRXRDATA; wire [71:0] MIMTXRDATA; wire [4:0] PL2DIRECTEDLSTATE = 5'b0; wire TL2ASPMSUSPENDCREDITCHECKN; wire TL2PPMSUSPENDREQN; wire PIPERX0CHANISALIGNED; wire [1:0] PIPERX0CHARISK; wire [15:0] PIPERX0DATA; wire PIPERX0ELECIDLE; wire PIPERX0PHYSTATUS; wire [2:0] PIPERX0STATUS; wire PIPERX0VALID; wire PIPERX1CHANISALIGNED; wire [1:0] PIPERX1CHARISK; wire [15:0] PIPERX1DATA; wire PIPERX1ELECIDLE; wire PIPERX1PHYSTATUS; wire [2:0] PIPERX1STATUS; wire PIPERX1VALID; wire PIPERX2CHANISALIGNED; wire [1:0] PIPERX2CHARISK; wire [15:0] PIPERX2DATA; wire PIPERX2ELECIDLE; wire PIPERX2PHYSTATUS; wire [2:0] PIPERX2STATUS; wire PIPERX2VALID; wire PIPERX3CHANISALIGNED; wire [1:0] PIPERX3CHARISK; wire [15:0] PIPERX3DATA; wire PIPERX3ELECIDLE; wire PIPERX3PHYSTATUS; wire [2:0] PIPERX3STATUS; wire PIPERX3VALID; wire PIPERX4CHANISALIGNED; wire [1:0] PIPERX4CHARISK; wire [15:0] PIPERX4DATA; wire PIPERX4ELECIDLE; wire PIPERX4PHYSTATUS; wire [2:0] PIPERX4STATUS; wire PIPERX4VALID; wire PIPERX5CHANISALIGNED; wire [1:0] PIPERX5CHARISK; wire [15:0] PIPERX5DATA; wire PIPERX5ELECIDLE; wire PIPERX5PHYSTATUS; wire [2:0] PIPERX5STATUS; wire PIPERX5VALID; wire PIPERX6CHANISALIGNED; wire [1:0] PIPERX6CHARISK; wire [15:0] PIPERX6DATA; wire PIPERX6ELECIDLE; wire PIPERX6PHYSTATUS; wire [2:0] PIPERX6STATUS; wire PIPERX6VALID; wire PIPERX7CHANISALIGNED; wire [1:0] PIPERX7CHARISK; wire [15:0] PIPERX7DATA; wire PIPERX7ELECIDLE; wire PIPERX7PHYSTATUS; wire [2:0] PIPERX7STATUS; wire PIPERX7VALID; wire PIPERX0POLARITYGT; wire PIPERX1POLARITYGT; wire PIPERX2POLARITYGT; wire PIPERX3POLARITYGT; wire PIPERX4POLARITYGT; wire PIPERX5POLARITYGT; wire PIPERX6POLARITYGT; wire PIPERX7POLARITYGT; wire PIPETXDEEMPHGT; wire [2:0] PIPETXMARGINGT; wire PIPETXRATEGT; wire PIPETXRCVRDETGT; wire [1:0] PIPETX0CHARISKGT; wire PIPETX0COMPLIANCEGT; wire [15:0] PIPETX0DATAGT; wire PIPETX0ELECIDLEGT; wire [1:0] PIPETX0POWERDOWNGT; wire [1:0] PIPETX1CHARISKGT; wire PIPETX1COMPLIANCEGT; wire [15:0] PIPETX1DATAGT; wire PIPETX1ELECIDLEGT; wire [1:0] PIPETX1POWERDOWNGT; wire [1:0] PIPETX2CHARISKGT; wire PIPETX2COMPLIANCEGT; wire [15:0] PIPETX2DATAGT; wire PIPETX2ELECIDLEGT; wire [1:0] PIPETX2POWERDOWNGT; wire [1:0] PIPETX3CHARISKGT; wire PIPETX3COMPLIANCEGT; wire [15:0] PIPETX3DATAGT; wire PIPETX3ELECIDLEGT; wire [1:0] PIPETX3POWERDOWNGT; wire [1:0] PIPETX4CHARISKGT; wire PIPETX4COMPLIANCEGT; wire [15:0] PIPETX4DATAGT; wire PIPETX4ELECIDLEGT; wire [1:0] PIPETX4POWERDOWNGT; wire [1:0] PIPETX5CHARISKGT; wire PIPETX5COMPLIANCEGT; wire [15:0] PIPETX5DATAGT; wire PIPETX5ELECIDLEGT; wire [1:0] PIPETX5POWERDOWNGT; wire [1:0] PIPETX6CHARISKGT; wire PIPETX6COMPLIANCEGT; wire [15:0] PIPETX6DATAGT; wire PIPETX6ELECIDLEGT; wire [1:0] PIPETX6POWERDOWNGT; wire [1:0] PIPETX7CHARISKGT; wire PIPETX7COMPLIANCEGT; wire [15:0] PIPETX7DATAGT; wire PIPETX7ELECIDLEGT; wire [1:0] PIPETX7POWERDOWNGT; wire PIPERX0CHANISALIGNEDGT; wire [1:0] PIPERX0CHARISKGT; wire [15:0] PIPERX0DATAGT; wire PIPERX0ELECIDLEGT; wire PIPERX0PHYSTATUSGT; wire [2:0] PIPERX0STATUSGT; wire PIPERX0VALIDGT; wire PIPERX1CHANISALIGNEDGT; wire [1:0] PIPERX1CHARISKGT; wire [15:0] PIPERX1DATAGT; wire PIPERX1ELECIDLEGT; wire PIPERX1PHYSTATUSGT; wire [2:0] PIPERX1STATUSGT; wire PIPERX1VALIDGT; wire PIPERX2CHANISALIGNEDGT; wire [1:0] PIPERX2CHARISKGT; wire [15:0] PIPERX2DATAGT; wire PIPERX2ELECIDLEGT; wire PIPERX2PHYSTATUSGT; wire [2:0] PIPERX2STATUSGT; wire PIPERX2VALIDGT; wire PIPERX3CHANISALIGNEDGT; wire [1:0] PIPERX3CHARISKGT; wire [15:0] PIPERX3DATAGT; wire PIPERX3ELECIDLEGT; wire PIPERX3PHYSTATUSGT; wire [2:0] PIPERX3STATUSGT; wire PIPERX3VALIDGT; wire PIPERX4CHANISALIGNEDGT; wire [1:0] PIPERX4CHARISKGT; wire [15:0] PIPERX4DATAGT; wire PIPERX4ELECIDLEGT; wire PIPERX4PHYSTATUSGT; wire [2:0] PIPERX4STATUSGT; wire PIPERX4VALIDGT; wire PIPERX5CHANISALIGNEDGT; wire [1:0] PIPERX5CHARISKGT; wire [15:0] PIPERX5DATAGT; wire PIPERX5ELECIDLEGT; wire PIPERX5PHYSTATUSGT; wire [2:0] PIPERX5STATUSGT; wire PIPERX5VALIDGT; wire PIPERX6CHANISALIGNEDGT; wire [1:0] PIPERX6CHARISKGT; wire [15:0] PIPERX6DATAGT; wire PIPERX6ELECIDLEGT; wire PIPERX6PHYSTATUSGT; wire [2:0] PIPERX6STATUSGT; wire PIPERX6VALIDGT; wire PIPERX7CHANISALIGNEDGT; wire [1:0] PIPERX7CHARISKGT; wire [15:0] PIPERX7DATAGT; wire PIPERX7ELECIDLEGT; wire PIPERX7PHYSTATUSGT; wire [2:0] PIPERX7STATUSGT; wire PIPERX7VALIDGT; wire filter_pipe_upconfig_fix_3451; //------------------------------------------------------- // Virtex6 PCI Express Block Module //------------------------------------------------------- PCIE_2_0 #( .AER_BASE_PTR ( AER_BASE_PTR ), .AER_CAP_ECRC_CHECK_CAPABLE ( AER_CAP_ECRC_CHECK_CAPABLE ), .AER_CAP_ECRC_GEN_CAPABLE ( AER_CAP_ECRC_GEN_CAPABLE ), .AER_CAP_ID ( AER_CAP_ID ), .AER_CAP_INT_MSG_NUM_MSI ( AER_CAP_INT_MSG_NUM_MSI ), .AER_CAP_INT_MSG_NUM_MSIX ( AER_CAP_INT_MSG_NUM_MSIX ), .AER_CAP_NEXTPTR ( AER_CAP_NEXTPTR ), .AER_CAP_ON ( AER_CAP_ON ), .AER_CAP_PERMIT_ROOTERR_UPDATE ( AER_CAP_PERMIT_ROOTERR_UPDATE ), .AER_CAP_VERSION ( AER_CAP_VERSION ), .ALLOW_X8_GEN2 ( ALLOW_X8_GEN2 ), .BAR0 ( BAR0 ), .BAR1 ( BAR1 ), .BAR2 ( BAR2 ), .BAR3 ( BAR3 ), .BAR4 ( BAR4 ), .BAR5 ( BAR5 ), .CAPABILITIES_PTR ( CAPABILITIES_PTR ), .CARDBUS_CIS_POINTER ( CARDBUS_CIS_POINTER ), .CLASS_CODE ( CLASS_CODE ), .CMD_INTX_IMPLEMENTED ( CMD_INTX_IMPLEMENTED ), .CPL_TIMEOUT_DISABLE_SUPPORTED ( CPL_TIMEOUT_DISABLE_SUPPORTED ), .CPL_TIMEOUT_RANGES_SUPPORTED ( CPL_TIMEOUT_RANGES_SUPPORTED ), .CRM_MODULE_RSTS ( CRM_MODULE_RSTS ), .DEV_CAP_ENABLE_SLOT_PWR_LIMIT_SCALE ( DEV_CAP_ENABLE_SLOT_PWR_LIMIT_SCALE ), .DEV_CAP_ENABLE_SLOT_PWR_LIMIT_VALUE ( DEV_CAP_ENABLE_SLOT_PWR_LIMIT_VALUE ), .DEV_CAP_ENDPOINT_L0S_LATENCY ( DEV_CAP_ENDPOINT_L0S_LATENCY ), .DEV_CAP_ENDPOINT_L1_LATENCY ( DEV_CAP_ENDPOINT_L1_LATENCY ), .DEV_CAP_EXT_TAG_SUPPORTED ( DEV_CAP_EXT_TAG_SUPPORTED ), .DEV_CAP_FUNCTION_LEVEL_RESET_CAPABLE ( DEV_CAP_FUNCTION_LEVEL_RESET_CAPABLE ), .DEV_CAP_MAX_PAYLOAD_SUPPORTED ( DEV_CAP_MAX_PAYLOAD_SUPPORTED ), .DEV_CAP_PHANTOM_FUNCTIONS_SUPPORT ( DEV_CAP_PHANTOM_FUNCTIONS_SUPPORT ), .DEV_CAP_ROLE_BASED_ERROR ( DEV_CAP_ROLE_BASED_ERROR ), .DEV_CAP_RSVD_14_12 ( DEV_CAP_RSVD_14_12 ), .DEV_CAP_RSVD_17_16 ( DEV_CAP_RSVD_17_16 ), .DEV_CAP_RSVD_31_29 ( DEV_CAP_RSVD_31_29 ), .DEV_CONTROL_AUX_POWER_SUPPORTED ( DEV_CONTROL_AUX_POWER_SUPPORTED ), .DEVICE_ID ( DEVICE_ID ), .DISABLE_ASPM_L1_TIMER ( DISABLE_ASPM_L1_TIMER ), .DISABLE_BAR_FILTERING ( DISABLE_BAR_FILTERING ), .DISABLE_ID_CHECK ( DISABLE_ID_CHECK ), .DISABLE_LANE_REVERSAL ( DISABLE_LANE_REVERSAL ), .DISABLE_RX_TC_FILTER ( DISABLE_RX_TC_FILTER ), .DISABLE_SCRAMBLING ( DISABLE_SCRAMBLING ), .DNSTREAM_LINK_NUM ( DNSTREAM_LINK_NUM ), .DSN_BASE_PTR ( DSN_BASE_PTR ), .DSN_CAP_ID ( DSN_CAP_ID ), .DSN_CAP_NEXTPTR ( DSN_CAP_NEXTPTR ), .DSN_CAP_ON ( DSN_CAP_ON ), .DSN_CAP_VERSION ( DSN_CAP_VERSION ), .ENABLE_MSG_ROUTE ( ENABLE_MSG_ROUTE ), .ENABLE_RX_TD_ECRC_TRIM ( ENABLE_RX_TD_ECRC_TRIM ), .ENTER_RVRY_EI_L0 ( ENTER_RVRY_EI_L0 ), .EXPANSION_ROM ( EXPANSION_ROM ), .EXT_CFG_CAP_PTR ( EXT_CFG_CAP_PTR ), .EXT_CFG_XP_CAP_PTR ( EXT_CFG_XP_CAP_PTR ), .HEADER_TYPE ( HEADER_TYPE ), .INFER_EI ( INFER_EI ), .INTERRUPT_PIN ( INTERRUPT_PIN ), .IS_SWITCH ( IS_SWITCH ), .LAST_CONFIG_DWORD ( LAST_CONFIG_DWORD ), .LINK_CAP_ASPM_SUPPORT ( LINK_CAP_ASPM_SUPPORT ), .LINK_CAP_CLOCK_POWER_MANAGEMENT ( LINK_CAP_CLOCK_POWER_MANAGEMENT ), .LINK_CAP_DLL_LINK_ACTIVE_REPORTING_CAP ( LINK_CAP_DLL_LINK_ACTIVE_REPORTING_CAP ), .LINK_CAP_LINK_BANDWIDTH_NOTIFICATION_CAP ( LINK_CAP_LINK_BANDWIDTH_NOTIFICATION_CAP ), .LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN1 ( LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN1 ), .LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN2 ( LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN2 ), .LINK_CAP_L0S_EXIT_LATENCY_GEN1 ( LINK_CAP_L0S_EXIT_LATENCY_GEN1 ), .LINK_CAP_L0S_EXIT_LATENCY_GEN2 ( LINK_CAP_L0S_EXIT_LATENCY_GEN2 ), .LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN1 ( LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN1 ), .LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN2 ( LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN2 ), .LINK_CAP_L1_EXIT_LATENCY_GEN1 ( LINK_CAP_L1_EXIT_LATENCY_GEN1 ), .LINK_CAP_L1_EXIT_LATENCY_GEN2 ( LINK_CAP_L1_EXIT_LATENCY_GEN2 ), .LINK_CAP_MAX_LINK_SPEED ( LINK_CAP_MAX_LINK_SPEED ), .LINK_CAP_MAX_LINK_WIDTH ( LINK_CAP_MAX_LINK_WIDTH ), .LINK_CAP_RSVD_23_22 ( LINK_CAP_RSVD_23_22 ), .LINK_CAP_SURPRISE_DOWN_ERROR_CAPABLE ( LINK_CAP_SURPRISE_DOWN_ERROR_CAPABLE ), .LINK_CONTROL_RCB ( LINK_CONTROL_RCB ), .LINK_CTRL2_DEEMPHASIS ( LINK_CTRL2_DEEMPHASIS ), .LINK_CTRL2_HW_AUTONOMOUS_SPEED_DISABLE ( LINK_CTRL2_HW_AUTONOMOUS_SPEED_DISABLE ), .LINK_CTRL2_TARGET_LINK_SPEED ( LINK_CTRL2_TARGET_LINK_SPEED ), .LINK_STATUS_SLOT_CLOCK_CONFIG ( LINK_STATUS_SLOT_CLOCK_CONFIG ), .LL_ACK_TIMEOUT ( LL_ACK_TIMEOUT ), .LL_ACK_TIMEOUT_EN ( LL_ACK_TIMEOUT_EN ), .LL_ACK_TIMEOUT_FUNC ( LL_ACK_TIMEOUT_FUNC ), .LL_REPLAY_TIMEOUT ( LL_REPLAY_TIMEOUT ), .LL_REPLAY_TIMEOUT_EN ( LL_REPLAY_TIMEOUT_EN ), .LL_REPLAY_TIMEOUT_FUNC ( LL_REPLAY_TIMEOUT_FUNC ), .LTSSM_MAX_LINK_WIDTH ( LTSSM_MAX_LINK_WIDTH ), .MSI_BASE_PTR ( MSI_BASE_PTR ), .MSI_CAP_ID ( MSI_CAP_ID ), .MSI_CAP_MULTIMSGCAP ( MSI_CAP_MULTIMSGCAP ), .MSI_CAP_MULTIMSG_EXTENSION ( MSI_CAP_MULTIMSG_EXTENSION ), .MSI_CAP_NEXTPTR ( MSI_CAP_NEXTPTR ), .MSI_CAP_ON ( MSI_CAP_ON ), .MSI_CAP_PER_VECTOR_MASKING_CAPABLE ( MSI_CAP_PER_VECTOR_MASKING_CAPABLE ), .MSI_CAP_64_BIT_ADDR_CAPABLE ( MSI_CAP_64_BIT_ADDR_CAPABLE ), .MSIX_BASE_PTR ( MSIX_BASE_PTR ), .MSIX_CAP_ID ( MSIX_CAP_ID ), .MSIX_CAP_NEXTPTR ( MSIX_CAP_NEXTPTR ), .MSIX_CAP_ON ( MSIX_CAP_ON ), .MSIX_CAP_PBA_BIR ( MSIX_CAP_PBA_BIR ), .MSIX_CAP_PBA_OFFSET ( MSIX_CAP_PBA_OFFSET ), .MSIX_CAP_TABLE_BIR ( MSIX_CAP_TABLE_BIR ), .MSIX_CAP_TABLE_OFFSET ( MSIX_CAP_TABLE_OFFSET ), .MSIX_CAP_TABLE_SIZE ( MSIX_CAP_TABLE_SIZE ), .N_FTS_COMCLK_GEN1 ( N_FTS_COMCLK_GEN1 ), .N_FTS_COMCLK_GEN2 ( N_FTS_COMCLK_GEN2 ), .N_FTS_GEN1 ( N_FTS_GEN1 ), .N_FTS_GEN2 ( N_FTS_GEN2 ), .PCIE_BASE_PTR ( PCIE_BASE_PTR ), .PCIE_CAP_CAPABILITY_ID ( PCIE_CAP_CAPABILITY_ID ), .PCIE_CAP_CAPABILITY_VERSION ( PCIE_CAP_CAPABILITY_VERSION ), .PCIE_CAP_DEVICE_PORT_TYPE ( PCIE_CAP_DEVICE_PORT_TYPE ), .PCIE_CAP_INT_MSG_NUM ( PCIE_CAP_INT_MSG_NUM ), .PCIE_CAP_NEXTPTR ( PCIE_CAP_NEXTPTR ), .PCIE_CAP_ON ( PCIE_CAP_ON ), .PCIE_CAP_RSVD_15_14 ( PCIE_CAP_RSVD_15_14 ), .PCIE_CAP_SLOT_IMPLEMENTED ( PCIE_CAP_SLOT_IMPLEMENTED ), .PCIE_REVISION ( PCIE_REVISION ), .PGL0_LANE ( PGL0_LANE ), .PGL1_LANE ( PGL1_LANE ), .PGL2_LANE ( PGL2_LANE ), .PGL3_LANE ( PGL3_LANE ), .PGL4_LANE ( PGL4_LANE ), .PGL5_LANE ( PGL5_LANE ), .PGL6_LANE ( PGL6_LANE ), .PGL7_LANE ( PGL7_LANE ), .PL_AUTO_CONFIG ( PL_AUTO_CONFIG ), .PL_FAST_TRAIN ( PL_FAST_TRAIN ), .PM_BASE_PTR ( PM_BASE_PTR ), .PM_CAP_AUXCURRENT ( PM_CAP_AUXCURRENT ), .PM_CAP_DSI ( PM_CAP_DSI ), .PM_CAP_D1SUPPORT ( PM_CAP_D1SUPPORT ), .PM_CAP_D2SUPPORT ( PM_CAP_D2SUPPORT ), .PM_CAP_ID ( PM_CAP_ID ), .PM_CAP_NEXTPTR ( PM_CAP_NEXTPTR ), .PM_CAP_ON ( PM_CAP_ON ), .PM_CAP_PME_CLOCK ( PM_CAP_PME_CLOCK ), .PM_CAP_PMESUPPORT ( PM_CAP_PMESUPPORT ), .PM_CAP_RSVD_04 ( PM_CAP_RSVD_04 ), .PM_CAP_VERSION ( PM_CAP_VERSION ), .PM_CSR_BPCCEN ( PM_CSR_BPCCEN ), .PM_CSR_B2B3 ( PM_CSR_B2B3 ), .PM_CSR_NOSOFTRST ( PM_CSR_NOSOFTRST ), .PM_DATA_SCALE0 ( PM_DATA_SCALE0 ), .PM_DATA_SCALE1 ( PM_DATA_SCALE1 ), .PM_DATA_SCALE2 ( PM_DATA_SCALE2 ), .PM_DATA_SCALE3 ( PM_DATA_SCALE3 ), .PM_DATA_SCALE4 ( PM_DATA_SCALE4 ), .PM_DATA_SCALE5 ( PM_DATA_SCALE5 ), .PM_DATA_SCALE6 ( PM_DATA_SCALE6 ), .PM_DATA_SCALE7 ( PM_DATA_SCALE7 ), .PM_DATA0 ( PM_DATA0 ), .PM_DATA1 ( PM_DATA1 ), .PM_DATA2 ( PM_DATA2 ), .PM_DATA3 ( PM_DATA3 ), .PM_DATA4 ( PM_DATA4 ), .PM_DATA5 ( PM_DATA5 ), .PM_DATA6 ( PM_DATA6 ), .PM_DATA7 ( PM_DATA7 ), .RECRC_CHK ( RECRC_CHK ), .RECRC_CHK_TRIM ( RECRC_CHK_TRIM ), .REVISION_ID ( REVISION_ID ), .ROOT_CAP_CRS_SW_VISIBILITY ( ROOT_CAP_CRS_SW_VISIBILITY ), .SELECT_DLL_IF ( SELECT_DLL_IF ), .SLOT_CAP_ATT_BUTTON_PRESENT ( SLOT_CAP_ATT_BUTTON_PRESENT ), .SLOT_CAP_ATT_INDICATOR_PRESENT ( SLOT_CAP_ATT_INDICATOR_PRESENT ), .SLOT_CAP_ELEC_INTERLOCK_PRESENT ( SLOT_CAP_ELEC_INTERLOCK_PRESENT ), .SLOT_CAP_HOTPLUG_CAPABLE ( SLOT_CAP_HOTPLUG_CAPABLE ), .SLOT_CAP_HOTPLUG_SURPRISE ( SLOT_CAP_HOTPLUG_SURPRISE ), .SLOT_CAP_MRL_SENSOR_PRESENT ( SLOT_CAP_MRL_SENSOR_PRESENT ), .SLOT_CAP_NO_CMD_COMPLETED_SUPPORT ( SLOT_CAP_NO_CMD_COMPLETED_SUPPORT ), .SLOT_CAP_PHYSICAL_SLOT_NUM ( SLOT_CAP_PHYSICAL_SLOT_NUM ), .SLOT_CAP_POWER_CONTROLLER_PRESENT ( SLOT_CAP_POWER_CONTROLLER_PRESENT ), .SLOT_CAP_POWER_INDICATOR_PRESENT ( SLOT_CAP_POWER_INDICATOR_PRESENT ), .SLOT_CAP_SLOT_POWER_LIMIT_SCALE ( SLOT_CAP_SLOT_POWER_LIMIT_SCALE ), .SLOT_CAP_SLOT_POWER_LIMIT_VALUE ( SLOT_CAP_SLOT_POWER_LIMIT_VALUE ), .SPARE_BIT0 ( SPARE_BIT0 ), .SPARE_BIT1 ( SPARE_BIT1 ), .SPARE_BIT2 ( SPARE_BIT2 ), .SPARE_BIT3 ( SPARE_BIT3 ), .SPARE_BIT4 ( SPARE_BIT4 ), .SPARE_BIT5 ( SPARE_BIT5 ), .SPARE_BIT6 ( SPARE_BIT6 ), .SPARE_BIT7 ( SPARE_BIT7 ), .SPARE_BIT8 ( SPARE_BIT8 ), .SPARE_BYTE0 ( SPARE_BYTE0 ), .SPARE_BYTE1 ( SPARE_BYTE1 ), .SPARE_BYTE2 ( SPARE_BYTE2 ), .SPARE_BYTE3 ( SPARE_BYTE3 ), .SPARE_WORD0 ( SPARE_WORD0 ), .SPARE_WORD1 ( SPARE_WORD1 ), .SPARE_WORD2 ( SPARE_WORD2 ), .SPARE_WORD3 ( SPARE_WORD3 ), .SUBSYSTEM_ID ( SUBSYSTEM_ID ), .SUBSYSTEM_VENDOR_ID ( SUBSYSTEM_VENDOR_ID ), .TL_RBYPASS ( TL_RBYPASS ), .TL_RX_RAM_RADDR_LATENCY ( TL_RX_RAM_RADDR_LATENCY ), .TL_RX_RAM_RDATA_LATENCY ( TL_RX_RAM_RDATA_LATENCY ), .TL_RX_RAM_WRITE_LATENCY ( TL_RX_RAM_WRITE_LATENCY ), .TL_TFC_DISABLE ( TL_TFC_DISABLE ), .TL_TX_CHECKS_DISABLE ( TL_TX_CHECKS_DISABLE ), .TL_TX_RAM_RADDR_LATENCY ( TL_TX_RAM_RADDR_LATENCY ), .TL_TX_RAM_RDATA_LATENCY ( TL_TX_RAM_RDATA_LATENCY ), .TL_TX_RAM_WRITE_LATENCY ( TL_TX_RAM_WRITE_LATENCY ), .UPCONFIG_CAPABLE ( UPCONFIG_CAPABLE ), .UPSTREAM_FACING ( UPSTREAM_FACING ), .EXIT_LOOPBACK_ON_EI ( EXIT_LOOPBACK_ON_EI ), .UR_INV_REQ ( UR_INV_REQ ), .USER_CLK_FREQ ( USER_CLK_FREQ ), .VC_BASE_PTR ( VC_BASE_PTR ), .VC_CAP_ID ( VC_CAP_ID ), .VC_CAP_NEXTPTR ( VC_CAP_NEXTPTR ), .VC_CAP_ON ( VC_CAP_ON ), .VC_CAP_REJECT_SNOOP_TRANSACTIONS ( VC_CAP_REJECT_SNOOP_TRANSACTIONS ), .VC_CAP_VERSION ( VC_CAP_VERSION ), .VC0_CPL_INFINITE ( VC0_CPL_INFINITE ), .VC0_RX_RAM_LIMIT ( VC0_RX_RAM_LIMIT ), .VC0_TOTAL_CREDITS_CD ( VC0_TOTAL_CREDITS_CD ), .VC0_TOTAL_CREDITS_CH ( VC0_TOTAL_CREDITS_CH ), .VC0_TOTAL_CREDITS_NPH ( VC0_TOTAL_CREDITS_NPH ), .VC0_TOTAL_CREDITS_PD ( VC0_TOTAL_CREDITS_PD ), .VC0_TOTAL_CREDITS_PH ( VC0_TOTAL_CREDITS_PH ), .VC0_TX_LASTPACKET ( VC0_TX_LASTPACKET ), .VENDOR_ID ( VENDOR_ID ), .VSEC_BASE_PTR ( VSEC_BASE_PTR ), .VSEC_CAP_HDR_ID ( VSEC_CAP_HDR_ID ), .VSEC_CAP_HDR_LENGTH ( VSEC_CAP_HDR_LENGTH ), .VSEC_CAP_HDR_REVISION ( VSEC_CAP_HDR_REVISION ), .VSEC_CAP_ID ( VSEC_CAP_ID ), .VSEC_CAP_IS_LINK_VISIBLE ( VSEC_CAP_IS_LINK_VISIBLE ), .VSEC_CAP_NEXTPTR ( VSEC_CAP_NEXTPTR ), .VSEC_CAP_ON ( VSEC_CAP_ON ), .VSEC_CAP_VERSION ( VSEC_CAP_VERSION ) ) pcie_block_i ( .CFGAERECRCCHECKEN ( CFGAERECRCCHECKEN ), .CFGAERECRCGENEN ( CFGAERECRCGENEN ), .CFGCOMMANDBUSMASTERENABLE ( CFGCOMMANDBUSMASTERENABLE ), .CFGCOMMANDINTERRUPTDISABLE ( CFGCOMMANDINTERRUPTDISABLE ), .CFGCOMMANDIOENABLE ( CFGCOMMANDIOENABLE ), .CFGCOMMANDMEMENABLE ( CFGCOMMANDMEMENABLE ), .CFGCOMMANDSERREN ( CFGCOMMANDSERREN ), .CFGDEVCONTROLAUXPOWEREN ( CFGDEVCONTROLAUXPOWEREN ), .CFGDEVCONTROLCORRERRREPORTINGEN ( CFGDEVCONTROLCORRERRREPORTINGEN ), .CFGDEVCONTROLENABLERO ( CFGDEVCONTROLENABLERO ), .CFGDEVCONTROLEXTTAGEN ( CFGDEVCONTROLEXTTAGEN ), .CFGDEVCONTROLFATALERRREPORTINGEN ( CFGDEVCONTROLFATALERRREPORTINGEN ), .CFGDEVCONTROLMAXPAYLOAD ( CFGDEVCONTROLMAXPAYLOAD ), .CFGDEVCONTROLMAXREADREQ ( CFGDEVCONTROLMAXREADREQ ), .CFGDEVCONTROLNONFATALREPORTINGEN ( CFGDEVCONTROLNONFATALREPORTINGEN ), .CFGDEVCONTROLNOSNOOPEN ( CFGDEVCONTROLNOSNOOPEN ), .CFGDEVCONTROLPHANTOMEN ( CFGDEVCONTROLPHANTOMEN ), .CFGDEVCONTROLURERRREPORTINGEN ( CFGDEVCONTROLURERRREPORTINGEN ), .CFGDEVCONTROL2CPLTIMEOUTDIS ( CFGDEVCONTROL2CPLTIMEOUTDIS ), .CFGDEVCONTROL2CPLTIMEOUTVAL ( CFGDEVCONTROL2CPLTIMEOUTVAL ), .CFGDEVSTATUSCORRERRDETECTED ( CFGDEVSTATUSCORRERRDETECTED ), .CFGDEVSTATUSFATALERRDETECTED ( CFGDEVSTATUSFATALERRDETECTED ), .CFGDEVSTATUSNONFATALERRDETECTED ( CFGDEVSTATUSNONFATALERRDETECTED ), .CFGDEVSTATUSURDETECTED ( CFGDEVSTATUSURDETECTED ), .CFGDO ( CFGDO ), .CFGERRAERHEADERLOGSETN ( CFGERRAERHEADERLOGSETN ), .CFGERRCPLRDYN ( CFGERRCPLRDYN ), .CFGINTERRUPTDO ( CFGINTERRUPTDO ), .CFGINTERRUPTMMENABLE ( CFGINTERRUPTMMENABLE ), .CFGINTERRUPTMSIENABLE ( CFGINTERRUPTMSIENABLE ), .CFGINTERRUPTMSIXENABLE ( CFGINTERRUPTMSIXENABLE ), .CFGINTERRUPTMSIXFM ( CFGINTERRUPTMSIXFM ), .CFGINTERRUPTRDYN ( CFGINTERRUPTRDYN ), .CFGLINKCONTROLRCB ( CFGLINKCONTROLRCB ), .CFGLINKCONTROLASPMCONTROL ( CFGLINKCONTROLASPMCONTROL ), .CFGLINKCONTROLAUTOBANDWIDTHINTEN ( CFGLINKCONTROLAUTOBANDWIDTHINTEN ), .CFGLINKCONTROLBANDWIDTHINTEN ( CFGLINKCONTROLBANDWIDTHINTEN ), .CFGLINKCONTROLCLOCKPMEN ( CFGLINKCONTROLCLOCKPMEN ), .CFGLINKCONTROLCOMMONCLOCK ( CFGLINKCONTROLCOMMONCLOCK ), .CFGLINKCONTROLEXTENDEDSYNC ( CFGLINKCONTROLEXTENDEDSYNC ), .CFGLINKCONTROLHWAUTOWIDTHDIS ( CFGLINKCONTROLHWAUTOWIDTHDIS ), .CFGLINKCONTROLLINKDISABLE ( CFGLINKCONTROLLINKDISABLE ), .CFGLINKCONTROLRETRAINLINK ( CFGLINKCONTROLRETRAINLINK ), .CFGLINKSTATUSAUTOBANDWIDTHSTATUS ( CFGLINKSTATUSAUTOBANDWIDTHSTATUS ), .CFGLINKSTATUSBANDWITHSTATUS ( CFGLINKSTATUSBANDWITHSTATUS ), .CFGLINKSTATUSCURRENTSPEED ( CFGLINKSTATUSCURRENTSPEED ), .CFGLINKSTATUSDLLACTIVE ( CFGLINKSTATUSDLLACTIVE ), .CFGLINKSTATUSLINKTRAINING ( CFGLINKSTATUSLINKTRAINING ), .CFGLINKSTATUSNEGOTIATEDWIDTH ( CFGLINKSTATUSNEGOTIATEDWIDTH ), .CFGMSGDATA ( CFGMSGDATA ), .CFGMSGRECEIVED ( CFGMSGRECEIVED ), .CFGMSGRECEIVEDASSERTINTA ( CFGMSGRECEIVEDASSERTINTA ), .CFGMSGRECEIVEDASSERTINTB ( CFGMSGRECEIVEDASSERTINTB ), .CFGMSGRECEIVEDASSERTINTC ( CFGMSGRECEIVEDASSERTINTC ), .CFGMSGRECEIVEDASSERTINTD ( CFGMSGRECEIVEDASSERTINTD ), .CFGMSGRECEIVEDDEASSERTINTA ( CFGMSGRECEIVEDDEASSERTINTA ), .CFGMSGRECEIVEDDEASSERTINTB ( CFGMSGRECEIVEDDEASSERTINTB ), .CFGMSGRECEIVEDDEASSERTINTC ( CFGMSGRECEIVEDDEASSERTINTC ), .CFGMSGRECEIVEDDEASSERTINTD ( CFGMSGRECEIVEDDEASSERTINTD ), .CFGMSGRECEIVEDERRCOR ( CFGMSGRECEIVEDERRCOR ), .CFGMSGRECEIVEDERRFATAL ( CFGMSGRECEIVEDERRFATAL ), .CFGMSGRECEIVEDERRNONFATAL ( CFGMSGRECEIVEDERRNONFATAL ), .CFGMSGRECEIVEDPMASNAK ( CFGMSGRECEIVEDPMASNAK ), .CFGMSGRECEIVEDPMETO ( CFGMSGRECEIVEDPMETO ), .CFGMSGRECEIVEDPMETOACK ( CFGMSGRECEIVEDPMETOACK ), .CFGMSGRECEIVEDPMPME ( CFGMSGRECEIVEDPMPME ), .CFGMSGRECEIVEDSETSLOTPOWERLIMIT ( CFGMSGRECEIVEDSETSLOTPOWERLIMIT ), .CFGMSGRECEIVEDUNLOCK ( CFGMSGRECEIVEDUNLOCK ), .CFGPCIELINKSTATE ( CFGPCIELINKSTATE ), .CFGPMRCVASREQL1N ( CFGPMRCVASREQL1N ), .CFGPMRCVENTERL1N ( CFGPMRCVENTERL1N ), .CFGPMRCVENTERL23N ( CFGPMRCVENTERL23N ), .CFGPMRCVREQACKN ( CFGPMRCVREQACKN ), .CFGPMCSRPMEEN( CFGPMCSRPMEEN ), .CFGPMCSRPMESTATUS( CFGPMCSRPMESTATUS ), .CFGPMCSRPOWERSTATE( CFGPMCSRPOWERSTATE ), .CFGRDWRDONEN ( CFGRDWRDONEN ), .CFGSLOTCONTROLELECTROMECHILCTLPULSE ( CFGSLOTCONTROLELECTROMECHILCTLPULSE ), .CFGTRANSACTION ( CFGTRANSACTION ), .CFGTRANSACTIONADDR ( CFGTRANSACTIONADDR ), .CFGTRANSACTIONTYPE ( CFGTRANSACTIONTYPE ), .CFGVCTCVCMAP ( CFGVCTCVCMAP ), .DBGSCLRA ( DBGSCLRA ), .DBGSCLRB ( DBGSCLRB ), .DBGSCLRC ( DBGSCLRC ), .DBGSCLRD ( DBGSCLRD ), .DBGSCLRE ( DBGSCLRE ), .DBGSCLRF ( DBGSCLRF ), .DBGSCLRG ( DBGSCLRG ), .DBGSCLRH ( DBGSCLRH ), .DBGSCLRI ( DBGSCLRI ), .DBGSCLRJ ( DBGSCLRJ ), .DBGSCLRK ( DBGSCLRK ), .DBGVECA ( DBGVECA ), .DBGVECB ( DBGVECB ), .DBGVECC ( DBGVECC ), .DRPDO ( PCIEDRPDO ), .DRPDRDY ( PCIEDRPDRDY ), .LL2BADDLLPERRN ( LL2BADDLLPERRN ), .LL2BADTLPERRN ( LL2BADTLPERRN ), .LL2PROTOCOLERRN ( LL2PROTOCOLERRN ), .LL2REPLAYROERRN ( LL2REPLAYROERRN ), .LL2REPLAYTOERRN ( LL2REPLAYTOERRN ), .LL2SUSPENDOKN ( LL2SUSPENDOKN ), .LL2TFCINIT1SEQN ( LL2TFCINIT1SEQN ), .LL2TFCINIT2SEQN ( LL2TFCINIT2SEQN ), .MIMRXRADDR ( MIMRXRADDR ), .MIMRXRCE ( MIMRXRCE ), .MIMRXREN ( MIMRXREN ), .MIMRXWADDR ( MIMRXWADDR ), .MIMRXWDATA ( MIMRXWDATA ), .MIMRXWEN ( MIMRXWEN ), .MIMTXRADDR ( MIMTXRADDR ), .MIMTXRCE ( MIMTXRCE ), .MIMTXREN ( MIMTXREN ), .MIMTXWADDR ( MIMTXWADDR ), .MIMTXWDATA ( MIMTXWDATA ), .MIMTXWEN ( MIMTXWEN ), .PIPERX0POLARITY ( PIPERX0POLARITY ), .PIPERX1POLARITY ( PIPERX1POLARITY ), .PIPERX2POLARITY ( PIPERX2POLARITY ), .PIPERX3POLARITY ( PIPERX3POLARITY ), .PIPERX4POLARITY ( PIPERX4POLARITY ), .PIPERX5POLARITY ( PIPERX5POLARITY ), .PIPERX6POLARITY ( PIPERX6POLARITY ), .PIPERX7POLARITY ( PIPERX7POLARITY ), .PIPETXDEEMPH ( PIPETXDEEMPH ), .PIPETXMARGIN ( PIPETXMARGIN ), .PIPETXRATE ( PIPETXRATE ), .PIPETXRCVRDET ( PIPETXRCVRDET ), .PIPETXRESET ( PIPETXRESET ), .PIPETX0CHARISK ( PIPETX0CHARISK ), .PIPETX0COMPLIANCE ( PIPETX0COMPLIANCE ), .PIPETX0DATA ( PIPETX0DATA ), .PIPETX0ELECIDLE ( PIPETX0ELECIDLE ), .PIPETX0POWERDOWN ( PIPETX0POWERDOWN ), .PIPETX1CHARISK ( PIPETX1CHARISK ), .PIPETX1COMPLIANCE ( PIPETX1COMPLIANCE ), .PIPETX1DATA ( PIPETX1DATA ), .PIPETX1ELECIDLE ( PIPETX1ELECIDLE ), .PIPETX1POWERDOWN ( PIPETX1POWERDOWN ), .PIPETX2CHARISK ( PIPETX2CHARISK ), .PIPETX2COMPLIANCE ( PIPETX2COMPLIANCE ), .PIPETX2DATA ( PIPETX2DATA ), .PIPETX2ELECIDLE ( PIPETX2ELECIDLE ), .PIPETX2POWERDOWN ( PIPETX2POWERDOWN ), .PIPETX3CHARISK ( PIPETX3CHARISK ), .PIPETX3COMPLIANCE ( PIPETX3COMPLIANCE ), .PIPETX3DATA ( PIPETX3DATA ), .PIPETX3ELECIDLE ( PIPETX3ELECIDLE ), .PIPETX3POWERDOWN ( PIPETX3POWERDOWN ), .PIPETX4CHARISK ( PIPETX4CHARISK ), .PIPETX4COMPLIANCE ( PIPETX4COMPLIANCE ), .PIPETX4DATA ( PIPETX4DATA ), .PIPETX4ELECIDLE ( PIPETX4ELECIDLE ), .PIPETX4POWERDOWN ( PIPETX4POWERDOWN ), .PIPETX5CHARISK ( PIPETX5CHARISK ), .PIPETX5COMPLIANCE ( PIPETX5COMPLIANCE ), .PIPETX5DATA ( PIPETX5DATA ), .PIPETX5ELECIDLE ( PIPETX5ELECIDLE ), .PIPETX5POWERDOWN ( PIPETX5POWERDOWN ), .PIPETX6CHARISK ( PIPETX6CHARISK ), .PIPETX6COMPLIANCE ( PIPETX6COMPLIANCE ), .PIPETX6DATA ( PIPETX6DATA ), .PIPETX6ELECIDLE ( PIPETX6ELECIDLE ), .PIPETX6POWERDOWN ( PIPETX6POWERDOWN ), .PIPETX7CHARISK ( PIPETX7CHARISK ), .PIPETX7COMPLIANCE ( PIPETX7COMPLIANCE ), .PIPETX7DATA ( PIPETX7DATA ), .PIPETX7ELECIDLE ( PIPETX7ELECIDLE ), .PIPETX7POWERDOWN ( PIPETX7POWERDOWN ), .PLDBGVEC ( PLDBGVEC ), .PLINITIALLINKWIDTH ( PLINITIALLINKWIDTH ), .PLLANEREVERSALMODE ( PLLANEREVERSALMODE ), .PLLINKGEN2CAP ( PLLINKGEN2CAP ), .PLLINKPARTNERGEN2SUPPORTED ( PLLINKPARTNERGEN2SUPPORTED ), .PLLINKUPCFGCAP ( PLLINKUPCFGCAP ), .PLLTSSMSTATE ( PLLTSSMSTATE ), .PLPHYLNKUPN ( PLPHYLNKUPN ), .PLRECEIVEDHOTRST ( PLRECEIVEDHOTRST ), .PLRXPMSTATE ( PLRXPMSTATE ), .PLSELLNKRATE ( PLSELLNKRATE ), .PLSELLNKWIDTH ( PLSELLNKWIDTH ), .PLTXPMSTATE ( PLTXPMSTATE ), .PL2LINKUPN ( PL2LINKUPN ), .PL2RECEIVERERRN ( PL2RECEIVERERRN ), .PL2RECOVERYN ( PL2RECOVERYN ), .PL2RXELECIDLE ( PL2RXELECIDLE ), .PL2SUSPENDOK ( PL2SUSPENDOK ), .RECEIVEDFUNCLVLRSTN ( RECEIVEDFUNCLVLRSTN ), .LNKCLKEN ( LNKCLKEN ), .TL2ASPMSUSPENDCREDITCHECKOKN ( TL2ASPMSUSPENDCREDITCHECKOKN ), .TL2ASPMSUSPENDREQN ( TL2ASPMSUSPENDREQN ), .TL2PPMSUSPENDOKN ( TL2PPMSUSPENDOKN ), .TRNFCCPLD ( TRNFCCPLD ), .TRNFCCPLH ( TRNFCCPLH ), .TRNFCNPD ( TRNFCNPD ), .TRNFCNPH ( TRNFCNPH ), .TRNFCPD ( TRNFCPD ), .TRNFCPH ( TRNFCPH ), .TRNLNKUPN ( TRNLNKUPN ), .TRNRBARHITN ( TRNRBARHITN ), .TRNRD ( TRNRD ), .TRNRDLLPDATA ( TRNRDLLPDATA ), .TRNRDLLPSRCRDYN ( TRNRDLLPSRCRDYN ), .TRNRECRCERRN ( TRNRECRCERRN ), .TRNREOFN ( TRNREOFN ), .TRNRERRFWDN ( TRNRERRFWDN ), .TRNRREMN ( TRNRREMN ), .TRNRSOFN ( TRNRSOFN ), .TRNRSRCDSCN ( TRNRSRCDSCN ), .TRNRSRCRDYN ( TRNRSRCRDYN ), .TRNTBUFAV ( TRNTBUFAV ), .TRNTCFGREQN ( TRNTCFGREQN ), .TRNTDLLPDSTRDYN ( TRNTDLLPDSTRDYN ), .TRNTDSTRDYN ( TRNTDSTRDYN ), .TRNTERRDROPN ( TRNTERRDROPN ), .USERRSTN ( USERRSTN ), .CFGBYTEENN ( CFGBYTEENN ), .CFGDI ( CFGDI ), .CFGDSBUSNUMBER ( CFGDSBUSNUMBER ), .CFGDSDEVICENUMBER ( CFGDSDEVICENUMBER ), .CFGDSFUNCTIONNUMBER ( CFGDSFUNCTIONNUMBER ), .CFGDSN ( CFGDSN ), .CFGDWADDR ( CFGDWADDR ), .CFGERRACSN ( CFGERRACSN ), .CFGERRAERHEADERLOG ( CFGERRAERHEADERLOG ), .CFGERRCORN ( CFGERRCORN ), .CFGERRCPLABORTN ( CFGERRCPLABORTN ), .CFGERRCPLTIMEOUTN ( CFGERRCPLTIMEOUTN ), .CFGERRCPLUNEXPECTN ( CFGERRCPLUNEXPECTN ), .CFGERRECRCN ( CFGERRECRCN ), .CFGERRLOCKEDN ( CFGERRLOCKEDN ), .CFGERRPOSTEDN ( CFGERRPOSTEDN ), .CFGERRTLPCPLHEADER ( CFGERRTLPCPLHEADER ), .CFGERRURN ( CFGERRURN ), .CFGINTERRUPTASSERTN ( CFGINTERRUPTASSERTN ), .CFGINTERRUPTDI ( CFGINTERRUPTDI ), .CFGINTERRUPTN ( CFGINTERRUPTN ), .CFGPMDIRECTASPML1N ( CFGPMDIRECTASPML1N ), .CFGPMSENDPMACKN ( CFGPMSENDPMACKN ), .CFGPMSENDPMETON ( CFGPMSENDPMETON ), .CFGPMSENDPMNAKN ( CFGPMSENDPMNAKN ), .CFGPMTURNOFFOKN ( CFGPMTURNOFFOKN ), .CFGPMWAKEN ( CFGPMWAKEN ), .CFGPORTNUMBER ( CFGPORTNUMBER ), .CFGRDENN ( CFGRDENN ), .CFGTRNPENDINGN ( CFGTRNPENDINGN ), .CFGWRENN ( CFGWRENN ), .CFGWRREADONLYN ( CFGWRREADONLYN ), .CFGWRRW1CASRWN ( CFGWRRW1CASRWN ), .CMRSTN ( CMRSTN ), .CMSTICKYRSTN ( CMSTICKYRSTN ), .DBGMODE ( DBGMODE ), .DBGSUBMODE ( DBGSUBMODE ), .DLRSTN ( DLRSTN ), .DRPCLK ( PCIEDRPCLK ), .DRPDADDR ( PCIEDRPDADDR ), .DRPDEN ( PCIEDRPDEN ), .DRPDI ( PCIEDRPDI ), .DRPDWE ( PCIEDRPDWE ), .FUNCLVLRSTN ( FUNCLVLRSTN ), .LL2SENDASREQL1N ( LL2SENDASREQL1N ), .LL2SENDENTERL1N ( LL2SENDENTERL1N ), .LL2SENDENTERL23N ( LL2SENDENTERL23N ), .LL2SUSPENDNOWN ( LL2SUSPENDNOWN ), .LL2TLPRCVN ( LL2TLPRCVN ), .MIMRXRDATA ( MIMRXRDATA[67:0] ), .MIMTXRDATA ( MIMTXRDATA[68:0] ), .PIPECLK ( PIPECLK ), .PIPERX0CHANISALIGNED ( PIPERX0CHANISALIGNED ), .PIPERX0CHARISK ( filter_pipe_upconfig_fix_3451 ? 2'b11 : PIPERX0CHARISK ), .PIPERX0DATA ( PIPERX0DATA ), .PIPERX0ELECIDLE ( PIPERX0ELECIDLE ), .PIPERX0PHYSTATUS ( PIPERX0PHYSTATUS ), .PIPERX0STATUS ( PIPERX0STATUS ), .PIPERX0VALID ( PIPERX0VALID ), .PIPERX1CHANISALIGNED ( PIPERX1CHANISALIGNED ), .PIPERX1CHARISK ( filter_pipe_upconfig_fix_3451 ? 2'b11 : PIPERX1CHARISK ), .PIPERX1DATA ( PIPERX1DATA ), .PIPERX1ELECIDLE ( PIPERX1ELECIDLE ), .PIPERX1PHYSTATUS ( PIPERX1PHYSTATUS ), .PIPERX1STATUS ( PIPERX1STATUS ), .PIPERX1VALID ( PIPERX1VALID ), .PIPERX2CHANISALIGNED ( PIPERX2CHANISALIGNED ), .PIPERX2CHARISK ( filter_pipe_upconfig_fix_3451 ? 2'b11 : PIPERX2CHARISK ), .PIPERX2DATA ( PIPERX2DATA ), .PIPERX2ELECIDLE ( PIPERX2ELECIDLE ), .PIPERX2PHYSTATUS ( PIPERX2PHYSTATUS ), .PIPERX2STATUS ( PIPERX2STATUS ), .PIPERX2VALID ( PIPERX2VALID ), .PIPERX3CHANISALIGNED ( PIPERX3CHANISALIGNED ), .PIPERX3CHARISK ( filter_pipe_upconfig_fix_3451 ? 2'b11 : PIPERX3CHARISK ), .PIPERX3DATA ( PIPERX3DATA ), .PIPERX3ELECIDLE ( PIPERX3ELECIDLE ), .PIPERX3PHYSTATUS ( PIPERX3PHYSTATUS ), .PIPERX3STATUS ( PIPERX3STATUS ), .PIPERX3VALID ( PIPERX3VALID ), .PIPERX4CHANISALIGNED ( PIPERX4CHANISALIGNED ), .PIPERX4CHARISK ( filter_pipe_upconfig_fix_3451 ? 2'b11 : PIPERX4CHARISK ), .PIPERX4DATA ( PIPERX4DATA ), .PIPERX4ELECIDLE ( PIPERX4ELECIDLE ), .PIPERX4PHYSTATUS ( PIPERX4PHYSTATUS ), .PIPERX4STATUS ( PIPERX4STATUS ), .PIPERX4VALID ( PIPERX4VALID ), .PIPERX5CHANISALIGNED ( PIPERX5CHANISALIGNED ), .PIPERX5CHARISK ( filter_pipe_upconfig_fix_3451 ? 2'b11 : PIPERX5CHARISK ), .PIPERX5DATA ( PIPERX5DATA ), .PIPERX5ELECIDLE ( PIPERX5ELECIDLE ), .PIPERX5PHYSTATUS ( PIPERX5PHYSTATUS ), .PIPERX5STATUS ( PIPERX5STATUS ), .PIPERX5VALID ( PIPERX5VALID ), .PIPERX6CHANISALIGNED ( PIPERX6CHANISALIGNED ), .PIPERX6CHARISK ( filter_pipe_upconfig_fix_3451 ? 2'b11 : PIPERX6CHARISK ), .PIPERX6DATA ( PIPERX6DATA ), .PIPERX6ELECIDLE ( PIPERX6ELECIDLE ), .PIPERX6PHYSTATUS ( PIPERX6PHYSTATUS ), .PIPERX6STATUS ( PIPERX6STATUS ), .PIPERX6VALID ( PIPERX6VALID ), .PIPERX7CHANISALIGNED ( PIPERX7CHANISALIGNED ), .PIPERX7CHARISK ( filter_pipe_upconfig_fix_3451 ? 2'b11 : PIPERX7CHARISK ), .PIPERX7DATA ( PIPERX7DATA ), .PIPERX7ELECIDLE ( PIPERX7ELECIDLE ), .PIPERX7PHYSTATUS ( PIPERX7PHYSTATUS ), .PIPERX7STATUS ( PIPERX7STATUS ), .PIPERX7VALID ( PIPERX7VALID ), .PLDBGMODE ( PLDBGMODE ), .PLDIRECTEDLINKAUTON ( PLDIRECTEDLINKAUTON ), .PLDIRECTEDLINKCHANGE ( PLDIRECTEDLINKCHANGE ), .PLDIRECTEDLINKSPEED ( PLDIRECTEDLINKSPEED ), .PLDIRECTEDLINKWIDTH ( PLDIRECTEDLINKWIDTH ), .PLDOWNSTREAMDEEMPHSOURCE ( PLDOWNSTREAMDEEMPHSOURCE ), .PLRSTN ( PLRSTN ), .PLTRANSMITHOTRST ( PLTRANSMITHOTRST ), .PLUPSTREAMPREFERDEEMPH ( PLUPSTREAMPREFERDEEMPH ), .PL2DIRECTEDLSTATE ( PL2DIRECTEDLSTATE ), .SYSRSTN ( SYSRSTN ), .TLRSTN ( TLRSTN ), .TL2ASPMSUSPENDCREDITCHECKN ( 1'b1), .TL2PPMSUSPENDREQN ( 1'b1 ), .TRNFCSEL ( TRNFCSEL ), .TRNRDSTRDYN ( TRNRDSTRDYN ), .TRNRNPOKN ( TRNRNPOKN ), .TRNTCFGGNTN ( TRNTCFGGNTN ), .TRNTD ( TRNTD ), .TRNTDLLPDATA ( TRNTDLLPDATA ), .TRNTDLLPSRCRDYN ( TRNTDLLPSRCRDYN ), .TRNTECRCGENN ( TRNTECRCGENN ), .TRNTEOFN ( TRNTEOFN ), .TRNTERRFWDN ( TRNTERRFWDN ), .TRNTREMN ( TRNTREMN ), .TRNTSOFN ( TRNTSOFN ), .TRNTSRCDSCN ( TRNTSRCDSCN ), .TRNTSRCRDYN ( TRNTSRCRDYN ), .TRNTSTRN ( TRNTSTRN ), .USERCLK ( USERCLK ) ); //------------------------------------------------------- // Virtex6 PIPE Module //------------------------------------------------------- pcie_pipe_v6 # ( .NO_OF_LANES(LINK_CAP_MAX_LINK_WIDTH), .LINK_CAP_MAX_LINK_SPEED(LINK_CAP_MAX_LINK_SPEED), .PIPE_PIPELINE_STAGES(PIPE_PIPELINE_STAGES) ) pcie_pipe_i ( // Pipe Per-Link Signals .pipe_tx_rcvr_det_i (PIPETXRCVRDET), .pipe_tx_reset_i (PIPETXRESET), .pipe_tx_rate_i (PIPETXRATE), .pipe_tx_deemph_i (PIPETXDEEMPH), .pipe_tx_margin_i (PIPETXMARGIN), .pipe_tx_swing_i (1'b0), .pipe_tx_rcvr_det_o (PIPETXRCVRDETGT), .pipe_tx_reset_o ( ), .pipe_tx_rate_o (PIPETXRATEGT), .pipe_tx_deemph_o (PIPETXDEEMPHGT), .pipe_tx_margin_o (PIPETXMARGINGT), .pipe_tx_swing_o ( ), // Pipe Per-Lane Signals - Lane 0 .pipe_rx0_char_is_k_o (PIPERX0CHARISK ), .pipe_rx0_data_o (PIPERX0DATA ), .pipe_rx0_valid_o (PIPERX0VALID ), .pipe_rx0_chanisaligned_o (PIPERX0CHANISALIGNED ), .pipe_rx0_status_o (PIPERX0STATUS ), .pipe_rx0_phy_status_o (PIPERX0PHYSTATUS ), .pipe_rx0_elec_idle_i (PIPERX0ELECIDLEGT ), .pipe_rx0_polarity_i (PIPERX0POLARITY ), .pipe_tx0_compliance_i (PIPETX0COMPLIANCE ), .pipe_tx0_char_is_k_i (PIPETX0CHARISK ), .pipe_tx0_data_i (PIPETX0DATA ), .pipe_tx0_elec_idle_i (PIPETX0ELECIDLE ), .pipe_tx0_powerdown_i (PIPETX0POWERDOWN ), .pipe_rx0_char_is_k_i (PIPERX0CHARISKGT ), .pipe_rx0_data_i (PIPERX0DATAGT ), .pipe_rx0_valid_i (PIPERX0VALIDGT ), .pipe_rx0_chanisaligned_i (PIPERX0CHANISALIGNEDGT ), .pipe_rx0_status_i (PIPERX0STATUSGT ), .pipe_rx0_phy_status_i (PIPERX0PHYSTATUSGT ), .pipe_rx0_elec_idle_o (PIPERX0ELECIDLE ), .pipe_rx0_polarity_o (PIPERX0POLARITYGT ), .pipe_tx0_compliance_o (PIPETX0COMPLIANCEGT ), .pipe_tx0_char_is_k_o (PIPETX0CHARISKGT ), .pipe_tx0_data_o (PIPETX0DATAGT ), .pipe_tx0_elec_idle_o (PIPETX0ELECIDLEGT ), .pipe_tx0_powerdown_o (PIPETX0POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 1 .pipe_rx1_char_is_k_o (PIPERX1CHARISK ), .pipe_rx1_data_o (PIPERX1DATA ), .pipe_rx1_valid_o (PIPERX1VALID ), .pipe_rx1_chanisaligned_o (PIPERX1CHANISALIGNED ), .pipe_rx1_status_o (PIPERX1STATUS ), .pipe_rx1_phy_status_o (PIPERX1PHYSTATUS ), .pipe_rx1_elec_idle_i (PIPERX1ELECIDLEGT ), .pipe_rx1_polarity_i (PIPERX1POLARITY ), .pipe_tx1_compliance_i (PIPETX1COMPLIANCE ), .pipe_tx1_char_is_k_i (PIPETX1CHARISK ), .pipe_tx1_data_i (PIPETX1DATA ), .pipe_tx1_elec_idle_i (PIPETX1ELECIDLE ), .pipe_tx1_powerdown_i (PIPETX1POWERDOWN ), .pipe_rx1_char_is_k_i (PIPERX1CHARISKGT ), .pipe_rx1_data_i (PIPERX1DATAGT ), .pipe_rx1_valid_i (PIPERX1VALIDGT ), .pipe_rx1_chanisaligned_i (PIPERX1CHANISALIGNEDGT ), .pipe_rx1_status_i (PIPERX1STATUSGT ), .pipe_rx1_phy_status_i (PIPERX1PHYSTATUSGT ), .pipe_rx1_elec_idle_o (PIPERX1ELECIDLE ), .pipe_rx1_polarity_o (PIPERX1POLARITYGT ), .pipe_tx1_compliance_o (PIPETX1COMPLIANCEGT ), .pipe_tx1_char_is_k_o (PIPETX1CHARISKGT ), .pipe_tx1_data_o (PIPETX1DATAGT ), .pipe_tx1_elec_idle_o (PIPETX1ELECIDLEGT ), .pipe_tx1_powerdown_o (PIPETX1POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 2 .pipe_rx2_char_is_k_o (PIPERX2CHARISK ), .pipe_rx2_data_o (PIPERX2DATA ), .pipe_rx2_valid_o (PIPERX2VALID ), .pipe_rx2_chanisaligned_o (PIPERX2CHANISALIGNED ), .pipe_rx2_status_o (PIPERX2STATUS ), .pipe_rx2_phy_status_o (PIPERX2PHYSTATUS ), .pipe_rx2_elec_idle_i (PIPERX2ELECIDLEGT ), .pipe_rx2_polarity_i (PIPERX2POLARITY ), .pipe_tx2_compliance_i (PIPETX2COMPLIANCE ), .pipe_tx2_char_is_k_i (PIPETX2CHARISK ), .pipe_tx2_data_i (PIPETX2DATA ), .pipe_tx2_elec_idle_i (PIPETX2ELECIDLE ), .pipe_tx2_powerdown_i (PIPETX2POWERDOWN ), .pipe_rx2_char_is_k_i (PIPERX2CHARISKGT ), .pipe_rx2_data_i (PIPERX2DATAGT ), .pipe_rx2_valid_i (PIPERX2VALIDGT ), .pipe_rx2_chanisaligned_i (PIPERX2CHANISALIGNEDGT ), .pipe_rx2_status_i (PIPERX2STATUSGT ), .pipe_rx2_phy_status_i (PIPERX2PHYSTATUSGT ), .pipe_rx2_elec_idle_o (PIPERX2ELECIDLE ), .pipe_rx2_polarity_o (PIPERX2POLARITYGT ), .pipe_tx2_compliance_o (PIPETX2COMPLIANCEGT ), .pipe_tx2_char_is_k_o (PIPETX2CHARISKGT ), .pipe_tx2_data_o (PIPETX2DATAGT ), .pipe_tx2_elec_idle_o (PIPETX2ELECIDLEGT ), .pipe_tx2_powerdown_o (PIPETX2POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 3 .pipe_rx3_char_is_k_o (PIPERX3CHARISK ), .pipe_rx3_data_o (PIPERX3DATA ), .pipe_rx3_valid_o (PIPERX3VALID ), .pipe_rx3_chanisaligned_o (PIPERX3CHANISALIGNED ), .pipe_rx3_status_o (PIPERX3STATUS ), .pipe_rx3_phy_status_o (PIPERX3PHYSTATUS ), .pipe_rx3_elec_idle_i (PIPERX3ELECIDLEGT ), .pipe_rx3_polarity_i (PIPERX3POLARITY ), .pipe_tx3_compliance_i (PIPETX3COMPLIANCE ), .pipe_tx3_char_is_k_i (PIPETX3CHARISK ), .pipe_tx3_data_i (PIPETX3DATA ), .pipe_tx3_elec_idle_i (PIPETX3ELECIDLE ), .pipe_tx3_powerdown_i (PIPETX3POWERDOWN ), .pipe_rx3_char_is_k_i (PIPERX3CHARISKGT ), .pipe_rx3_data_i (PIPERX3DATAGT ), .pipe_rx3_valid_i (PIPERX3VALIDGT ), .pipe_rx3_chanisaligned_i (PIPERX3CHANISALIGNEDGT ), .pipe_rx3_status_i (PIPERX3STATUSGT ), .pipe_rx3_phy_status_i (PIPERX3PHYSTATUSGT ), .pipe_rx3_elec_idle_o (PIPERX3ELECIDLE ), .pipe_rx3_polarity_o (PIPERX3POLARITYGT ), .pipe_tx3_compliance_o (PIPETX3COMPLIANCEGT ), .pipe_tx3_char_is_k_o (PIPETX3CHARISKGT ), .pipe_tx3_data_o (PIPETX3DATAGT ), .pipe_tx3_elec_idle_o (PIPETX3ELECIDLEGT ), .pipe_tx3_powerdown_o (PIPETX3POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 4 .pipe_rx4_char_is_k_o (PIPERX4CHARISK ), .pipe_rx4_data_o (PIPERX4DATA ), .pipe_rx4_valid_o (PIPERX4VALID ), .pipe_rx4_chanisaligned_o (PIPERX4CHANISALIGNED ), .pipe_rx4_status_o (PIPERX4STATUS ), .pipe_rx4_phy_status_o (PIPERX4PHYSTATUS ), .pipe_rx4_elec_idle_i (PIPERX4ELECIDLEGT ), .pipe_rx4_polarity_i (PIPERX4POLARITY ), .pipe_tx4_compliance_i (PIPETX4COMPLIANCE ), .pipe_tx4_char_is_k_i (PIPETX4CHARISK ), .pipe_tx4_data_i (PIPETX4DATA ), .pipe_tx4_elec_idle_i (PIPETX4ELECIDLE ), .pipe_tx4_powerdown_i (PIPETX4POWERDOWN ), .pipe_rx4_char_is_k_i (PIPERX4CHARISKGT ), .pipe_rx4_data_i (PIPERX4DATAGT ), .pipe_rx4_valid_i (PIPERX4VALIDGT ), .pipe_rx4_chanisaligned_i (PIPERX4CHANISALIGNEDGT ), .pipe_rx4_status_i (PIPERX4STATUSGT ), .pipe_rx4_phy_status_i (PIPERX4PHYSTATUSGT ), .pipe_rx4_elec_idle_o (PIPERX4ELECIDLE ), .pipe_rx4_polarity_o (PIPERX4POLARITYGT ), .pipe_tx4_compliance_o (PIPETX4COMPLIANCEGT ), .pipe_tx4_char_is_k_o (PIPETX4CHARISKGT ), .pipe_tx4_data_o (PIPETX4DATAGT ), .pipe_tx4_elec_idle_o (PIPETX4ELECIDLEGT ), .pipe_tx4_powerdown_o (PIPETX4POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 5 .pipe_rx5_char_is_k_o (PIPERX5CHARISK ), .pipe_rx5_data_o (PIPERX5DATA ), .pipe_rx5_valid_o (PIPERX5VALID ), .pipe_rx5_chanisaligned_o (PIPERX5CHANISALIGNED ), .pipe_rx5_status_o (PIPERX5STATUS ), .pipe_rx5_phy_status_o (PIPERX5PHYSTATUS ), .pipe_rx5_elec_idle_i (PIPERX5ELECIDLEGT ), .pipe_rx5_polarity_i (PIPERX5POLARITY ), .pipe_tx5_compliance_i (PIPETX5COMPLIANCE ), .pipe_tx5_char_is_k_i (PIPETX5CHARISK ), .pipe_tx5_data_i (PIPETX5DATA ), .pipe_tx5_elec_idle_i (PIPETX5ELECIDLE ), .pipe_tx5_powerdown_i (PIPETX5POWERDOWN ), .pipe_rx5_char_is_k_i (PIPERX5CHARISKGT ), .pipe_rx5_data_i (PIPERX5DATAGT ), .pipe_rx5_valid_i (PIPERX5VALIDGT ), .pipe_rx5_chanisaligned_i (PIPERX5CHANISALIGNEDGT ), .pipe_rx5_status_i (PIPERX5STATUSGT ), .pipe_rx5_phy_status_i (PIPERX5PHYSTATUSGT ), .pipe_rx5_elec_idle_o (PIPERX5ELECIDLE ), .pipe_rx5_polarity_o (PIPERX5POLARITYGT ), .pipe_tx5_compliance_o (PIPETX5COMPLIANCEGT ), .pipe_tx5_char_is_k_o (PIPETX5CHARISKGT ), .pipe_tx5_data_o (PIPETX5DATAGT ), .pipe_tx5_elec_idle_o (PIPETX5ELECIDLEGT ), .pipe_tx5_powerdown_o (PIPETX5POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 6 .pipe_rx6_char_is_k_o (PIPERX6CHARISK ), .pipe_rx6_data_o (PIPERX6DATA ), .pipe_rx6_valid_o (PIPERX6VALID ), .pipe_rx6_chanisaligned_o (PIPERX6CHANISALIGNED ), .pipe_rx6_status_o (PIPERX6STATUS ), .pipe_rx6_phy_status_o (PIPERX6PHYSTATUS ), .pipe_rx6_elec_idle_i (PIPERX6ELECIDLEGT ), .pipe_rx6_polarity_i (PIPERX6POLARITY ), .pipe_tx6_compliance_i (PIPETX6COMPLIANCE ), .pipe_tx6_char_is_k_i (PIPETX6CHARISK ), .pipe_tx6_data_i (PIPETX6DATA ), .pipe_tx6_elec_idle_i (PIPETX6ELECIDLE ), .pipe_tx6_powerdown_i (PIPETX6POWERDOWN ), .pipe_rx6_char_is_k_i (PIPERX6CHARISKGT ), .pipe_rx6_data_i (PIPERX6DATAGT ), .pipe_rx6_valid_i (PIPERX6VALIDGT ), .pipe_rx6_chanisaligned_i (PIPERX6CHANISALIGNEDGT ), .pipe_rx6_status_i (PIPERX6STATUSGT ), .pipe_rx6_phy_status_i (PIPERX6PHYSTATUSGT ), .pipe_rx6_elec_idle_o (PIPERX6ELECIDLE ), .pipe_rx6_polarity_o (PIPERX6POLARITYGT ), .pipe_tx6_compliance_o (PIPETX6COMPLIANCEGT ), .pipe_tx6_char_is_k_o (PIPETX6CHARISKGT ), .pipe_tx6_data_o (PIPETX6DATAGT ), .pipe_tx6_elec_idle_o (PIPETX6ELECIDLEGT ), .pipe_tx6_powerdown_o (PIPETX6POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 7 .pipe_rx7_char_is_k_o (PIPERX7CHARISK ), .pipe_rx7_data_o (PIPERX7DATA ), .pipe_rx7_valid_o (PIPERX7VALID ), .pipe_rx7_chanisaligned_o (PIPERX7CHANISALIGNED ), .pipe_rx7_status_o (PIPERX7STATUS ), .pipe_rx7_phy_status_o (PIPERX7PHYSTATUS ), .pipe_rx7_elec_idle_i (PIPERX7ELECIDLEGT ), .pipe_rx7_polarity_i (PIPERX7POLARITY ), .pipe_tx7_compliance_i (PIPETX7COMPLIANCE ), .pipe_tx7_char_is_k_i (PIPETX7CHARISK ), .pipe_tx7_data_i (PIPETX7DATA ), .pipe_tx7_elec_idle_i (PIPETX7ELECIDLE ), .pipe_tx7_powerdown_i (PIPETX7POWERDOWN ), .pipe_rx7_char_is_k_i (PIPERX7CHARISKGT ), .pipe_rx7_data_i (PIPERX7DATAGT ), .pipe_rx7_valid_i (PIPERX7VALIDGT ), .pipe_rx7_chanisaligned_i (PIPERX7CHANISALIGNEDGT ), .pipe_rx7_status_i (PIPERX7STATUSGT ), .pipe_rx7_phy_status_i (PIPERX7PHYSTATUSGT ), .pipe_rx7_elec_idle_o (PIPERX7ELECIDLE ), .pipe_rx7_polarity_o (PIPERX7POLARITYGT ), .pipe_tx7_compliance_o (PIPETX7COMPLIANCEGT ), .pipe_tx7_char_is_k_o (PIPETX7CHARISKGT ), .pipe_tx7_data_o (PIPETX7DATAGT ), .pipe_tx7_elec_idle_o (PIPETX7ELECIDLEGT ), .pipe_tx7_powerdown_o (PIPETX7POWERDOWNGT ), // Non PIPE signals .pl_ltssm_state (PLLTSSMSTATE ), .pipe_clk (PIPECLK ), .rst_n (PHYRDYN ) ); //------------------------------------------------------- // Virtex6 GTX Module //------------------------------------------------------- pcie_gtx_v6 #( .NO_OF_LANES(LINK_CAP_MAX_LINK_WIDTH), .LINK_CAP_MAX_LINK_SPEED(LINK_CAP_MAX_LINK_SPEED), .REF_CLK_FREQ(REF_CLK_FREQ), .PL_FAST_TRAIN(PL_FAST_TRAIN) ) pcie_gt_i ( // Pipe Common Signals .pipe_tx_rcvr_det (PIPETXRCVRDETGT ), .pipe_tx_reset (1'b0 ), .pipe_tx_rate (PIPETXRATEGT ), .pipe_tx_deemph (PIPETXDEEMPHGT ), .pipe_tx_margin (PIPETXMARGINGT ), .pipe_tx_swing (1'b0), // Pipe Per-Lane Signals - Lane 0 .pipe_rx0_char_is_k (PIPERX0CHARISKGT ), .pipe_rx0_data (PIPERX0DATAGT ), .pipe_rx0_valid (PIPERX0VALIDGT ), .pipe_rx0_chanisaligned (PIPERX0CHANISALIGNEDGT ), .pipe_rx0_status (PIPERX0STATUSGT ), .pipe_rx0_phy_status (PIPERX0PHYSTATUSGT ), .pipe_rx0_elec_idle (PIPERX0ELECIDLEGT ), .pipe_rx0_polarity (PIPERX0POLARITYGT ), .pipe_tx0_compliance (PIPETX0COMPLIANCEGT ), .pipe_tx0_char_is_k (PIPETX0CHARISKGT ), .pipe_tx0_data (PIPETX0DATAGT ), .pipe_tx0_elec_idle (PIPETX0ELECIDLEGT ), .pipe_tx0_powerdown (PIPETX0POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 1 .pipe_rx1_char_is_k (PIPERX1CHARISKGT ), .pipe_rx1_data (PIPERX1DATAGT ), .pipe_rx1_valid (PIPERX1VALIDGT ), .pipe_rx1_chanisaligned (PIPERX1CHANISALIGNEDGT ), .pipe_rx1_status (PIPERX1STATUSGT ), .pipe_rx1_phy_status (PIPERX1PHYSTATUSGT ), .pipe_rx1_elec_idle (PIPERX1ELECIDLEGT ), .pipe_rx1_polarity (PIPERX1POLARITYGT ), .pipe_tx1_compliance (PIPETX1COMPLIANCEGT ), .pipe_tx1_char_is_k (PIPETX1CHARISKGT ), .pipe_tx1_data (PIPETX1DATAGT ), .pipe_tx1_elec_idle (PIPETX1ELECIDLEGT ), .pipe_tx1_powerdown (PIPETX1POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 2 .pipe_rx2_char_is_k (PIPERX2CHARISKGT ), .pipe_rx2_data (PIPERX2DATAGT ), .pipe_rx2_valid (PIPERX2VALIDGT ), .pipe_rx2_chanisaligned (PIPERX2CHANISALIGNEDGT ), .pipe_rx2_status (PIPERX2STATUSGT ), .pipe_rx2_phy_status (PIPERX2PHYSTATUSGT ), .pipe_rx2_elec_idle (PIPERX2ELECIDLEGT ), .pipe_rx2_polarity (PIPERX2POLARITYGT ), .pipe_tx2_compliance (PIPETX2COMPLIANCEGT ), .pipe_tx2_char_is_k (PIPETX2CHARISKGT ), .pipe_tx2_data (PIPETX2DATAGT ), .pipe_tx2_elec_idle (PIPETX2ELECIDLEGT ), .pipe_tx2_powerdown (PIPETX2POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 3 .pipe_rx3_char_is_k (PIPERX3CHARISKGT ), .pipe_rx3_data (PIPERX3DATAGT ), .pipe_rx3_valid (PIPERX3VALIDGT ), .pipe_rx3_chanisaligned (PIPERX3CHANISALIGNEDGT ), .pipe_rx3_status (PIPERX3STATUSGT ), .pipe_rx3_phy_status (PIPERX3PHYSTATUSGT ), .pipe_rx3_elec_idle (PIPERX3ELECIDLEGT ), .pipe_rx3_polarity (PIPERX3POLARITYGT ), .pipe_tx3_compliance (PIPETX3COMPLIANCEGT ), .pipe_tx3_char_is_k (PIPETX3CHARISKGT ), .pipe_tx3_data (PIPETX3DATAGT ), .pipe_tx3_elec_idle (PIPETX3ELECIDLEGT ), .pipe_tx3_powerdown (PIPETX3POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 4 .pipe_rx4_char_is_k (PIPERX4CHARISKGT ), .pipe_rx4_data (PIPERX4DATAGT ), .pipe_rx4_valid (PIPERX4VALIDGT ), .pipe_rx4_chanisaligned (PIPERX4CHANISALIGNEDGT ), .pipe_rx4_status (PIPERX4STATUSGT ), .pipe_rx4_phy_status (PIPERX4PHYSTATUSGT ), .pipe_rx4_elec_idle (PIPERX4ELECIDLEGT ), .pipe_rx4_polarity (PIPERX4POLARITYGT ), .pipe_tx4_compliance (PIPETX4COMPLIANCEGT ), .pipe_tx4_char_is_k (PIPETX4CHARISKGT ), .pipe_tx4_data (PIPETX4DATAGT ), .pipe_tx4_elec_idle (PIPETX4ELECIDLEGT ), .pipe_tx4_powerdown (PIPETX4POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 5 .pipe_rx5_char_is_k (PIPERX5CHARISKGT ), .pipe_rx5_data (PIPERX5DATAGT ), .pipe_rx5_valid (PIPERX5VALIDGT ), .pipe_rx5_chanisaligned (PIPERX5CHANISALIGNEDGT ), .pipe_rx5_status (PIPERX5STATUSGT ), .pipe_rx5_phy_status (PIPERX5PHYSTATUSGT ), .pipe_rx5_elec_idle (PIPERX5ELECIDLEGT ), .pipe_rx5_polarity (PIPERX5POLARITYGT ), .pipe_tx5_compliance (PIPETX5COMPLIANCEGT ), .pipe_tx5_char_is_k (PIPETX5CHARISKGT ), .pipe_tx5_data (PIPETX5DATAGT ), .pipe_tx5_elec_idle (PIPETX5ELECIDLEGT ), .pipe_tx5_powerdown (PIPETX5POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 6 .pipe_rx6_char_is_k (PIPERX6CHARISKGT ), .pipe_rx6_data (PIPERX6DATAGT ), .pipe_rx6_valid (PIPERX6VALIDGT ), .pipe_rx6_chanisaligned (PIPERX6CHANISALIGNEDGT ), .pipe_rx6_status (PIPERX6STATUSGT ), .pipe_rx6_phy_status (PIPERX6PHYSTATUSGT ), .pipe_rx6_elec_idle (PIPERX6ELECIDLEGT ), .pipe_rx6_polarity (PIPERX6POLARITYGT ), .pipe_tx6_compliance (PIPETX6COMPLIANCEGT ), .pipe_tx6_char_is_k (PIPETX6CHARISKGT ), .pipe_tx6_data (PIPETX6DATAGT ), .pipe_tx6_elec_idle (PIPETX6ELECIDLEGT ), .pipe_tx6_powerdown (PIPETX6POWERDOWNGT ), // Pipe Per-Lane Signals - Lane 7 .pipe_rx7_char_is_k (PIPERX7CHARISKGT ), .pipe_rx7_data (PIPERX7DATAGT ), .pipe_rx7_valid (PIPERX7VALIDGT ), .pipe_rx7_chanisaligned (PIPERX7CHANISALIGNEDGT ), .pipe_rx7_status (PIPERX7STATUSGT ), .pipe_rx7_phy_status (PIPERX7PHYSTATUSGT ), .pipe_rx7_elec_idle (PIPERX7ELECIDLEGT ), .pipe_rx7_polarity (PIPERX7POLARITYGT ), .pipe_tx7_compliance (PIPETX7COMPLIANCEGT ), .pipe_tx7_char_is_k (PIPETX7CHARISKGT ), .pipe_tx7_data (PIPETX7DATAGT ), .pipe_tx7_elec_idle (PIPETX7ELECIDLEGT ), .pipe_tx7_powerdown (PIPETX7POWERDOWNGT ), // PCI Express Signals .pci_exp_txn (PCIEXPTXN ), .pci_exp_txp (PCIEXPTXP ), .pci_exp_rxn (PCIEXPRXN ), .pci_exp_rxp (PCIEXPRXP ), // Non PIPE Signals .sys_clk (SYSCLK ), .sys_rst_n (FUNDRSTN ), .pipe_clk (PIPECLK ), .drp_clk (DRPCLK ), .clock_locked (CLOCKLOCKED ), .pl_ltssm_state (PLLTSSMSTATE ), .gt_pll_lock (GTPLLLOCK ), .phy_rdy_n (PHYRDYN ), .TxOutClk (TxOutClk ) ); //------------------------------------------------------- // PCI Express BRAM Module //------------------------------------------------------- pcie_bram_top_v6 #( .DEV_CAP_MAX_PAYLOAD_SUPPORTED(DEV_CAP_MAX_PAYLOAD_SUPPORTED), .VC0_TX_LASTPACKET(VC0_TX_LASTPACKET), .TL_TX_RAM_RADDR_LATENCY(TL_TX_RAM_RADDR_LATENCY), .TL_TX_RAM_RDATA_LATENCY(TL_TX_RAM_RDATA_LATENCY), .TL_TX_RAM_WRITE_LATENCY(TL_TX_RAM_WRITE_LATENCY), .VC0_RX_LIMIT(VC0_RX_RAM_LIMIT), .TL_RX_RAM_RADDR_LATENCY(TL_RX_RAM_RADDR_LATENCY), .TL_RX_RAM_RDATA_LATENCY(TL_RX_RAM_RDATA_LATENCY), .TL_RX_RAM_WRITE_LATENCY(TL_RX_RAM_WRITE_LATENCY) ) pcie_bram_i ( .user_clk_i( USERCLK ), .reset_i( PHYRDYN ), .mim_tx_waddr( MIMTXWADDR ), .mim_tx_wen( MIMTXWEN ), .mim_tx_ren( MIMTXREN ), .mim_tx_rce( MIMTXRCE ), .mim_tx_wdata( {3'b0, MIMTXWDATA} ), .mim_tx_raddr( MIMTXRADDR ), .mim_tx_rdata( MIMTXRDATA ), .mim_rx_waddr( MIMRXWADDR ), .mim_rx_wen( MIMRXWEN ), .mim_rx_ren( MIMRXREN ), .mim_rx_rce( MIMRXRCE ), .mim_rx_wdata( {4'h0, MIMRXWDATA} ), .mim_rx_raddr( MIMRXRADDR ), .mim_rx_rdata( MIMRXRDATA ) ); //------------------------------------------------------- // PCI Express Port Workarounds //------------------------------------------------------- pcie_upconfig_fix_3451_v6 # ( .UPSTREAM_FACING ( UPSTREAM_FACING ), .PL_FAST_TRAIN ( PL_FAST_TRAIN ), .LINK_CAP_MAX_LINK_WIDTH ( LINK_CAP_MAX_LINK_WIDTH ) ) pcie_upconfig_fix_3451_v6_i ( .pipe_clk(PIPECLK), .pl_phy_lnkup_n(PLPHYLNKUPN), .pl_ltssm_state(PLLTSSMSTATE), .pl_sel_lnk_rate(PLSELLNKRATE), .pl_directed_link_change(PLDIRECTEDLINKCHANGE), .cfg_link_status_negotiated_width(CFGLINKSTATUSNEGOTIATEDWIDTH), .pipe_rx0_data(PIPERX0DATAGT[15:0]), .pipe_rx0_char_isk(PIPERX0CHARISKGT[1:0]), .filter_pipe(filter_pipe_upconfig_fix_3451) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/pcie_bram_top_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : pcie_bram_top_v6.v // Version : 2.4 //-- //-- Description: BlockRAM top level module for Virtex6 PCIe Block //-- //-- //-- //-------------------------------------------------------------------------------- `timescale 1ns/1ns module pcie_bram_top_v6 #( parameter DEV_CAP_MAX_PAYLOAD_SUPPORTED = 0, parameter VC0_TX_LASTPACKET = 31, parameter TLM_TX_OVERHEAD = 24, parameter TL_TX_RAM_RADDR_LATENCY = 1, parameter TL_TX_RAM_RDATA_LATENCY = 2, parameter TL_TX_RAM_WRITE_LATENCY = 1, parameter VC0_RX_LIMIT = 'h1FFF, parameter TL_RX_RAM_RADDR_LATENCY = 1, parameter TL_RX_RAM_RDATA_LATENCY = 2, parameter TL_RX_RAM_WRITE_LATENCY = 1 ) ( input user_clk_i, input reset_i, input mim_tx_wen, input [12:0] mim_tx_waddr, input [71:0] mim_tx_wdata, input mim_tx_ren, input mim_tx_rce, input [12:0] mim_tx_raddr, output [71:0] mim_tx_rdata, input mim_rx_wen, input [12:0] mim_rx_waddr, input [71:0] mim_rx_wdata, input mim_rx_ren, input mim_rx_rce, input [12:0] mim_rx_raddr, output [71:0] mim_rx_rdata ); // TX calculations localparam MPS_BYTES = ((DEV_CAP_MAX_PAYLOAD_SUPPORTED == 0) ? 128 : (DEV_CAP_MAX_PAYLOAD_SUPPORTED == 1) ? 256 : (DEV_CAP_MAX_PAYLOAD_SUPPORTED == 2) ? 512 : 1024 ); localparam BYTES_TX = (VC0_TX_LASTPACKET + 1) * (MPS_BYTES + TLM_TX_OVERHEAD); localparam ROWS_TX = 1; localparam COLS_TX = ((BYTES_TX <= 4096) ? 1 : (BYTES_TX <= 8192) ? 2 : (BYTES_TX <= 16384) ? 4 : (BYTES_TX <= 32768) ? 8 : 18 ); // RX calculations localparam ROWS_RX = 1; localparam COLS_RX = ((VC0_RX_LIMIT < 'h0200) ? 1 : (VC0_RX_LIMIT < 'h0400) ? 2 : (VC0_RX_LIMIT < 'h0800) ? 4 : (VC0_RX_LIMIT < 'h1000) ? 8 : 18 ); initial begin $display("[%t] %m ROWS_TX %0d COLS_TX %0d", $time, ROWS_TX, COLS_TX); $display("[%t] %m ROWS_RX %0d COLS_RX %0d", $time, ROWS_RX, COLS_RX); end pcie_brams_v6 #(.NUM_BRAMS (COLS_TX), .RAM_RADDR_LATENCY(TL_TX_RAM_RADDR_LATENCY), .RAM_RDATA_LATENCY(TL_TX_RAM_RDATA_LATENCY), .RAM_WRITE_LATENCY(TL_TX_RAM_WRITE_LATENCY)) pcie_brams_tx ( .user_clk_i(user_clk_i), .reset_i(reset_i), .waddr(mim_tx_waddr), .wen(mim_tx_wen), .ren(mim_tx_ren), .rce(mim_tx_rce), .wdata(mim_tx_wdata), .raddr(mim_tx_raddr), .rdata(mim_tx_rdata) ); pcie_brams_v6 #(.NUM_BRAMS (COLS_RX), .RAM_RADDR_LATENCY(TL_RX_RAM_RADDR_LATENCY), .RAM_RDATA_LATENCY(TL_RX_RAM_RDATA_LATENCY), .RAM_WRITE_LATENCY(TL_RX_RAM_WRITE_LATENCY)) pcie_brams_rx ( .user_clk_i(user_clk_i), .reset_i(reset_i), .waddr(mim_rx_waddr), .wen(mim_rx_wen), .ren(mim_rx_ren), .rce(mim_rx_rce), .wdata(mim_rx_wdata), .raddr(mim_rx_raddr), .rdata(mim_rx_rdata) ); endmodule // pcie_bram_top ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/pcie_bram_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : pcie_bram_v6.v // Version : 2.4 //-- //-- Description: BlockRAM module for Virtex6 PCIe Block //-- //-- //-- //-------------------------------------------------------------------------------- `timescale 1ns/1ns module pcie_bram_v6 #( parameter DOB_REG = 0,// 1 use the output register 0 don't use the output register parameter WIDTH = 0 // supported WIDTH's are: 4, 9, 18, 36 (uses RAMB36) and 72 (uses RAMB36SDP) ) ( input user_clk_i,// user clock input reset_i, // bram reset input wen_i, // write enable input [12:0] waddr_i, // write address input [WIDTH - 1:0] wdata_i, // write data input ren_i, // read enable input rce_i, // output register clock enable input [12:0] raddr_i, // read address output [WIDTH - 1:0] rdata_o // read data ); // map the address bits localparam ADDR_MSB = ((WIDTH == 4) ? 12 : (WIDTH == 9) ? 11 : (WIDTH == 18) ? 10 : (WIDTH == 36) ? 9 : 8 ); // set the width of the tied off low address bits localparam ADDR_LO_BITS = ((WIDTH == 4) ? 2 : (WIDTH == 9) ? 3 : (WIDTH == 18) ? 4 : (WIDTH == 36) ? 5 : 0 // for WIDTH 72 use RAMB36SDP ); // map the data bits localparam D_MSB = ((WIDTH == 4) ? 3 : (WIDTH == 9) ? 7 : (WIDTH == 18) ? 15 : (WIDTH == 36) ? 31 : 63 ); // map the data parity bits localparam DP_LSB = D_MSB + 1; localparam DP_MSB = ((WIDTH == 4) ? 4 : (WIDTH == 9) ? 8 : (WIDTH == 18) ? 17 : (WIDTH == 36) ? 35 : 71 ); localparam DPW = DP_MSB - DP_LSB + 1; localparam WRITE_MODE = "NO_CHANGE"; //synthesis translate_off initial begin //$display("[%t] %m DOB_REG %0d WIDTH %0d ADDR_MSB %0d ADDR_LO_BITS %0d DP_MSB %0d DP_LSB %0d D_MSB %0d", // $time, DOB_REG, WIDTH, ADDR_MSB, ADDR_LO_BITS, DP_MSB, DP_LSB, D_MSB); case (WIDTH) 4,9,18,36,72:; default: begin $display("[%t] %m Error WIDTH %0d not supported", $time, WIDTH); $finish; end endcase // case (WIDTH) end //synthesis translate_on generate if (WIDTH == 72) begin : use_ramb36sdp // use RAMB36SDP if the width is 72 RAMB36SDP #( .DO_REG (DOB_REG) ) ramb36sdp( .WRCLK (user_clk_i), .SSR (1'b0), .WRADDR (waddr_i[ADDR_MSB:0]), .DI (wdata_i[D_MSB:0]), .DIP (wdata_i[DP_MSB:DP_LSB]), .WREN (wen_i), .WE ({8{wen_i}}), .DBITERR (), .ECCPARITY (), .SBITERR (), .RDCLK (user_clk_i), .RDADDR (raddr_i[ADDR_MSB:0]), .DO (rdata_o[D_MSB:0]), .DOP (rdata_o[DP_MSB:DP_LSB]), .RDEN (ren_i), .REGCE (rce_i) ); // use RAMB36's if the width is 4, 9, 18, or 36 end else if (WIDTH == 36) begin : use_ramb36 RAMB36 #( .DOA_REG (0), .DOB_REG (DOB_REG), .READ_WIDTH_A (0), .READ_WIDTH_B (WIDTH), .WRITE_WIDTH_A (WIDTH), .WRITE_WIDTH_B (0), .WRITE_MODE_A (WRITE_MODE) ) ramb36( .CLKA (user_clk_i), .SSRA (1'b0), .REGCEA (1'b0), .CASCADEINLATA (1'b0), .CASCADEINREGA (1'b0), .CASCADEOUTLATA (), .CASCADEOUTREGA (), .DOA (), .DOPA (), .ADDRA ({1'b1, waddr_i[ADDR_MSB:0], {ADDR_LO_BITS{1'b1}}}), .DIA (wdata_i[D_MSB:0]), .DIPA (wdata_i[DP_MSB:DP_LSB]), .ENA (wen_i), .WEA ({4{wen_i}}), .CLKB (user_clk_i), .SSRB (1'b0), .WEB (4'b0), .CASCADEINLATB (1'b0), .CASCADEINREGB (1'b0), .CASCADEOUTLATB (), .CASCADEOUTREGB (), .DIB (32'b0), .DIPB ( 4'b0), .ADDRB ({1'b1, raddr_i[ADDR_MSB:0], {ADDR_LO_BITS{1'b1}}}), .DOB (rdata_o[D_MSB:0]), .DOPB (rdata_o[DP_MSB:DP_LSB]), .ENB (ren_i), .REGCEB (rce_i) ); end else if (WIDTH < 36 && WIDTH > 4) begin : use_ramb36 wire [31 - D_MSB - 1 : 0] dob_unused; wire [ 4 - DPW - 1 : 0] dopb_unused; RAMB36 #( .DOA_REG (0), .DOB_REG (DOB_REG), .READ_WIDTH_A (0), .READ_WIDTH_B (WIDTH), .WRITE_WIDTH_A (WIDTH), .WRITE_WIDTH_B (0), .WRITE_MODE_A (WRITE_MODE) ) ramb36( .CLKA (user_clk_i), .SSRA (1'b0), .REGCEA (1'b0), .CASCADEINLATA (1'b0), .CASCADEINREGA (1'b0), .CASCADEOUTLATA (), .CASCADEOUTREGA (), .DOA (), .DOPA (), .ADDRA ({1'b1, waddr_i[ADDR_MSB:0], {ADDR_LO_BITS{1'b1}}}), .DIA ({{31 - D_MSB{1'b0}},wdata_i[D_MSB:0]}), .DIPA ({{ 4 - DPW {1'b0}},wdata_i[DP_MSB:DP_LSB]}), .ENA (wen_i), .WEA ({4{wen_i}}), .CLKB (user_clk_i), .SSRB (1'b0), .WEB (4'b0), .CASCADEINLATB (1'b0), .CASCADEINREGB (1'b0), .CASCADEOUTLATB (), .CASCADEOUTREGB (), .DIB (32'b0), .DIPB ( 4'b0), .ADDRB ({1'b1, raddr_i[ADDR_MSB:0], {ADDR_LO_BITS{1'b1}}}), .DOB ({dob_unused, rdata_o[D_MSB:0]}), .DOPB ({dopb_unused, rdata_o[DP_MSB:DP_LSB]}), .ENB (ren_i), .REGCEB (rce_i) ); end else if (WIDTH == 4) begin : use_ramb36 wire [31 - D_MSB - 1 : 0] dob_unused; RAMB36 #( .DOB_REG (DOB_REG), .READ_WIDTH_A (0), .READ_WIDTH_B (WIDTH), .WRITE_WIDTH_A (WIDTH), .WRITE_WIDTH_B (0), .WRITE_MODE_A (WRITE_MODE) ) ramb36( .CLKA (user_clk_i), .SSRA (1'b0), .REGCEA (1'b0), .CASCADEINLATA (1'b0), .CASCADEINREGA (1'b0), .CASCADEOUTLATA (), .CASCADEOUTREGA (), .DOA (), .DOPA (), .ADDRA ({1'b1, waddr_i[ADDR_MSB:0], {ADDR_LO_BITS{1'b1}}}), .DIA ({{31 - D_MSB{1'b0}},wdata_i[D_MSB:0]}), //.DIPA (wdata_i[DP_MSB:DP_LSB]), .ENA (wen_i), .WEA ({4{wen_i}}), .CLKB (user_clk_i), .SSRB (1'b0), .WEB (4'b0), .CASCADEINLATB (1'b0), .CASCADEINREGB (1'b0), .CASCADEOUTLATB (), .CASCADEOUTREGB (), .ADDRB ({1'b1, raddr_i[ADDR_MSB:0], {ADDR_LO_BITS{1'b1}}}), .DOB ({dob_unused,rdata_o[D_MSB:0]}), //.DOPB (rdata_o[DP_MSB:DP_LSB]), .ENB (ren_i), .REGCEB (rce_i) ); end // block: use_ramb36 endgenerate endmodule // pcie_bram_v6 ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/pcie_brams_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : pcie_brams_v6.v // Version : 2.4 //-- //-- Description: BlockRAM module for Virtex6 PCIe Block //-- //-- //-- //-------------------------------------------------------------------------------- `timescale 1ns/1ns module pcie_brams_v6 #( // the number of BRAMs to use // supported values are: // 1,2,4,8,18 parameter NUM_BRAMS = 0, // BRAM read address latency // // value meaning // ==================================================== // 0 BRAM read address port sample // 1 BRAM read address port sample and a pipeline stage on the address port parameter RAM_RADDR_LATENCY = 1, // BRAM read data latency // // value meaning // ==================================================== // 1 no BRAM OREG // 2 use BRAM OREG // 3 use BRAM OREG and a pipeline stage on the data port parameter RAM_RDATA_LATENCY = 1, // BRAM write latency // The BRAM write port is synchronous // // value meaning // ==================================================== // 0 BRAM write port sample // 1 BRAM write port sample plus pipeline stage parameter RAM_WRITE_LATENCY = 1, parameter TCQ = 1 ) ( input user_clk_i, input reset_i, input wen, input [12:0] waddr, input [71:0] wdata, input ren, input rce, input [12:0] raddr, output [71:0] rdata ); // turn on the bram output register localparam DOB_REG = (RAM_RDATA_LATENCY > 1) ? 1 : 0; // calculate the data width of the individual brams localparam [6:0] WIDTH = ((NUM_BRAMS == 1) ? 72 : (NUM_BRAMS == 2) ? 36 : (NUM_BRAMS == 4) ? 18 : (NUM_BRAMS == 8) ? 9 : 4 ); //synthesis translate_off initial begin $display("[%t] %m NUM_BRAMS %0d DOB_REG %0d WIDTH %0d RAM_WRITE_LATENCY %0d RAM_RADDR_LATENCY %0d RAM_RDATA_LATENCY %0d", $time, NUM_BRAMS, DOB_REG, WIDTH, RAM_WRITE_LATENCY, RAM_RADDR_LATENCY, RAM_RDATA_LATENCY); case (NUM_BRAMS) 1,2,4,8,18:; default: begin $display("[%t] %m Error NUM_BRAMS %0d not supported", $time, NUM_BRAMS); $finish; end endcase // case(NUM_BRAMS) case (RAM_RADDR_LATENCY) 0,1:; default: begin $display("[%t] %m Error RAM_READ_LATENCY %0d not supported", $time, RAM_RADDR_LATENCY); $finish; end endcase // case (RAM_RADDR_LATENCY) case (RAM_RDATA_LATENCY) 1,2,3:; default: begin $display("[%t] %m Error RAM_READ_LATENCY %0d not supported", $time, RAM_RDATA_LATENCY); $finish; end endcase // case (RAM_RDATA_LATENCY) case (RAM_WRITE_LATENCY) 0,1:; default: begin $display("[%t] %m Error RAM_WRITE_LATENCY %0d not supported", $time, RAM_WRITE_LATENCY); $finish; end endcase // case(RAM_WRITE_LATENCY) end //synthesis translate_on // model the delays for ram write latency wire wen_int; wire [12:0] waddr_int; wire [71:0] wdata_int; generate if (RAM_WRITE_LATENCY == 1) begin : wr_lat_2 reg wen_dly; reg [12:0] waddr_dly; reg [71:0] wdata_dly; always @(posedge user_clk_i) begin if (reset_i) begin wen_dly <= #TCQ 1'b0; waddr_dly <= #TCQ 13'b0; wdata_dly <= #TCQ 72'b0; end else begin wen_dly <= #TCQ wen; waddr_dly <= #TCQ waddr; wdata_dly <= #TCQ wdata; end end assign wen_int = wen_dly; assign waddr_int = waddr_dly; assign wdata_int = wdata_dly; end // if (RAM_WRITE_LATENCY == 1) else if (RAM_WRITE_LATENCY == 0) begin : wr_lat_1 assign wen_int = wen; assign waddr_int = waddr; assign wdata_int = wdata; end endgenerate // model the delays for ram read latency wire ren_int; wire [12:0] raddr_int; wire [71:0] rdata_int; generate if (RAM_RADDR_LATENCY == 1) begin : raddr_lat_2 reg ren_dly; reg [12:0] raddr_dly; always @(posedge user_clk_i) begin if (reset_i) begin ren_dly <= #TCQ 1'b0; raddr_dly <= #TCQ 13'b0; end else begin ren_dly <= #TCQ ren; raddr_dly <= #TCQ raddr; end // else: !if(reset_i) end assign ren_int = ren_dly; assign raddr_int = raddr_dly; end // block: rd_lat_addr_2 else begin : raddr_lat_1 assign ren_int = ren; assign raddr_int = raddr; end endgenerate generate if (RAM_RDATA_LATENCY == 3) begin : rdata_lat_3 reg [71:0] rdata_dly; always @(posedge user_clk_i) begin if (reset_i) begin rdata_dly <= #TCQ 72'b0; end else begin rdata_dly <= #TCQ rdata_int; end // else: !if(reset_i) end assign rdata = rdata_dly; end // block: rd_lat_data_3 else begin : rdata_lat_1_2 assign #TCQ rdata = rdata_int; end endgenerate // instantiate the brams generate begin: num_brams genvar i; for (i = 0; i < NUM_BRAMS; i = i + 1) begin : brams pcie_bram_v6 #(.DOB_REG(DOB_REG), .WIDTH(WIDTH)) ram (.user_clk_i(user_clk_i), .reset_i(reset_i), .wen_i(wen_int), .waddr_i(waddr_int), .wdata_i(wdata_int[(((i + 1) * WIDTH) - 1): (i * WIDTH)]), .ren_i(ren_int), .raddr_i(raddr_int), .rdata_o(rdata_int[(((i + 1) * WIDTH) - 1): (i * WIDTH)]), .rce_i(rce)); end end endgenerate endmodule // pcie_brams_v6 ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/pcie_clocking_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : pcie_clocking_v6.v // Version : 2.4 //-- Description: Clocking module for Virtex6 PCIe Block //-- //-- //-- //-------------------------------------------------------------------------------- `timescale 1ns/1ns module pcie_clocking_v6 # ( parameter IS_ENDPOINT = "TRUE", parameter CAP_LINK_WIDTH = 8, // 1 - x1 , 2 - x2 , 4 - x4 , 8 - x8 parameter CAP_LINK_SPEED = 4'h1, // 1 - Gen1 , 2 - Gen2 parameter REF_CLK_FREQ = 0, // 0 - 100 MHz , 1 - 125 MHz , 2 - 250 MHz parameter USER_CLK_FREQ = 3 // 0 - 31.25 MHz , 1 - 62.5 MHz , 2 - 125 MHz , 3 - 250 MHz , 4 - 500Mhz ) ( input wire sys_clk, input wire gt_pll_lock, input wire sel_lnk_rate, input wire [1:0] sel_lnk_width, output wire sys_clk_bufg, output wire pipe_clk, output wire user_clk, output wire block_clk, output wire drp_clk, output wire clock_locked ); parameter TCQ = 1; wire mmcm_locked; wire mmcm_clkfbin; wire mmcm_clkfbout; wire mmcm_reset; wire clk_500; wire clk_250; wire clk_125; wire user_clk_prebuf; wire sel_lnk_rate_d; reg [1:0] reg_clock_locked = 2'b11; // MMCM Configuration localparam mmcm_clockin_period = (REF_CLK_FREQ == 0) ? 10 : (REF_CLK_FREQ == 1) ? 8 : (REF_CLK_FREQ == 2) ? 4 : 0; localparam mmcm_clockfb_mult = (REF_CLK_FREQ == 0) ? 10 : (REF_CLK_FREQ == 1) ? 8 : (REF_CLK_FREQ == 2) ? 8 : 0; localparam mmcm_divclk_divide = (REF_CLK_FREQ == 0) ? 1 : (REF_CLK_FREQ == 1) ? 1 : (REF_CLK_FREQ == 2) ? 2 : 0; localparam mmcm_clock0_div = 4; localparam mmcm_clock1_div = 8; localparam mmcm_clock2_div = ((CAP_LINK_WIDTH == 6'h01) && (CAP_LINK_SPEED == 4'h1) && (USER_CLK_FREQ == 0)) ? 32 : ((CAP_LINK_WIDTH == 6'h01) && (CAP_LINK_SPEED == 4'h1) && (USER_CLK_FREQ == 1)) ? 16 : ((CAP_LINK_WIDTH == 6'h01) && (CAP_LINK_SPEED == 4'h2) && (USER_CLK_FREQ == 1)) ? 16 : ((CAP_LINK_WIDTH == 6'h02) && (CAP_LINK_SPEED == 4'h1) && (USER_CLK_FREQ == 1)) ? 16 : 2; localparam mmcm_clock3_div = 2; // MMCM Reset assign mmcm_reset = 1'b0; generate // PIPE Clock BUFG. if (CAP_LINK_SPEED == 4'h1) begin : GEN1_LINK BUFG pipe_clk_bufg (.O(pipe_clk),.I(clk_125)); end else if (CAP_LINK_SPEED == 4'h2) begin : GEN2_LINK SRL16E #(.INIT(0)) sel_lnk_rate_delay (.Q(sel_lnk_rate_d), .D(sel_lnk_rate), .CLK(pipe_clk),.CE(clock_locked), .A3(1'b1),.A2(1'b1),.A1(1'b1),.A0(1'b1)); BUFGMUX pipe_clk_bufgmux (.O(pipe_clk), .I0(clk_125),.I1(clk_250),.S(sel_lnk_rate_d)); end else begin : ILLEGAL_LINK_SPEED //$display("Confiuration Error : CAP_LINK_SPEED = %d, must be either 1 or 2.", CAP_LINK_SPEED); //$finish; end // User Clock BUFG. if ((CAP_LINK_WIDTH == 6'h01) && (CAP_LINK_SPEED == 4'h1) && (USER_CLK_FREQ == 0)) begin : x1_GEN1_31_25 BUFG user_clk_bufg (.O(user_clk),.I(user_clk_prebuf)); end else if ((CAP_LINK_WIDTH == 6'h01) && (CAP_LINK_SPEED == 4'h1) && (USER_CLK_FREQ == 1)) begin : x1_GEN1_62_50 BUFG user_clk_bufg (.O(user_clk),.I(user_clk_prebuf)); end else if ((CAP_LINK_WIDTH == 6'h01) && (CAP_LINK_SPEED == 4'h1) && (USER_CLK_FREQ == 2)) begin : x1_GEN1_125_00 BUFG user_clk_bufg (.O(user_clk),.I(clk_125)); end else if ((CAP_LINK_WIDTH == 6'h01) && (CAP_LINK_SPEED == 4'h1) && (USER_CLK_FREQ == 3)) begin : x1_GEN1_250_00 BUFG user_clk_bufg (.O(user_clk),.I(clk_250)); end else if ((CAP_LINK_WIDTH == 6'h01) && (CAP_LINK_SPEED == 4'h2) && (USER_CLK_FREQ == 1)) begin : x1_GEN2_62_50 BUFG user_clk_bufg (.O(user_clk),.I(user_clk_prebuf)); end else if ((CAP_LINK_WIDTH == 6'h01) && (CAP_LINK_SPEED == 4'h2) && (USER_CLK_FREQ == 2)) begin : x1_GEN2_125_00 BUFG user_clk_bufg (.O(user_clk),.I(clk_125)); end else if ((CAP_LINK_WIDTH == 6'h01) && (CAP_LINK_SPEED == 4'h2) && (USER_CLK_FREQ == 3)) begin : x1_GEN2_250_00 BUFG user_clk_bufg (.O(user_clk),.I(clk_250)); end else if ((CAP_LINK_WIDTH == 6'h02) && (CAP_LINK_SPEED == 4'h1) && (USER_CLK_FREQ == 1)) begin : x2_GEN1_62_50 BUFG user_clk_bufg (.O(user_clk),.I(user_clk_prebuf)); end else if ((CAP_LINK_WIDTH == 6'h02) && (CAP_LINK_SPEED == 4'h1) && (USER_CLK_FREQ == 2)) begin : x2_GEN1_125_00 BUFG user_clk_bufg (.O(user_clk),.I(clk_125)); end else if ((CAP_LINK_WIDTH == 6'h02) && (CAP_LINK_SPEED == 4'h1) && (USER_CLK_FREQ == 3)) begin : x2_GEN1_250_00 BUFG user_clk_bufg (.O(user_clk),.I(clk_250)); end else if ((CAP_LINK_WIDTH == 6'h02) && (CAP_LINK_SPEED == 4'h2) && (USER_CLK_FREQ == 2)) begin : x2_GEN2_125_00 BUFG user_clk_bufg (.O(user_clk),.I(clk_125)); end else if ((CAP_LINK_WIDTH == 6'h02) && (CAP_LINK_SPEED == 4'h2) && (USER_CLK_FREQ == 3)) begin : x2_GEN2_250_00 BUFG user_clk_bufg (.O(user_clk),.I(clk_250)); end else if ((CAP_LINK_WIDTH == 6'h04) && (CAP_LINK_SPEED == 4'h1) && (USER_CLK_FREQ == 2)) begin : x4_GEN1_125_00 BUFG user_clk_bufg (.O(user_clk),.I(clk_125)); end else if ((CAP_LINK_WIDTH == 6'h04) && (CAP_LINK_SPEED == 4'h1) && (USER_CLK_FREQ == 3)) begin : x4_GEN1_250_00 BUFG user_clk_bufg (.O(user_clk),.I(clk_250)); end else if ((CAP_LINK_WIDTH == 6'h04) && (CAP_LINK_SPEED == 4'h2) && (USER_CLK_FREQ == 3)) begin : x4_GEN2_250_00 BUFG user_clk_bufg (.O(user_clk),.I(clk_250)); end else if ((CAP_LINK_WIDTH == 6'h08) && (CAP_LINK_SPEED == 4'h1) && (USER_CLK_FREQ == 3)) begin : x8_GEN1_250_00 BUFG user_clk_bufg (.O(user_clk),.I(clk_250)); end else if ((CAP_LINK_WIDTH == 6'h08) && (CAP_LINK_SPEED == 4'h2) && (USER_CLK_FREQ == 4)) begin : x8_GEN2_250_00 BUFG user_clk_bufg (.O(user_clk),.I(clk_250)); BUFG block_clk_bufg (.O(block_clk),.I(clk_500)); end else begin : ILLEGAL_CONFIGURATION //$display("Confiuration Error : Unsupported Link Width, Link Speed and User Clock Frequency Combination"); //$finish; end endgenerate // DRP clk BUFG drp_clk_bufg_i (.O(drp_clk), .I(clk_125)); // Feedback BUFG. Required for Temp Compensation BUFG clkfbin_bufg_i (.O(mmcm_clkfbin), .I(mmcm_clkfbout)); // sys_clk BUFG. BUFG sys_clk_bufg_i (.O(sys_clk_bufg), .I(sys_clk)); MMCM_ADV # ( // 5 for 100 MHz , 4 for 125 MHz , 2 for 250 MHz .CLKFBOUT_MULT_F (mmcm_clockfb_mult), .DIVCLK_DIVIDE (mmcm_divclk_divide), .CLKFBOUT_PHASE(0), // 10 for 100 MHz, 4 for 250 MHz .CLKIN1_PERIOD (mmcm_clockin_period), .CLKIN2_PERIOD (mmcm_clockin_period), // 500 MHz / mmcm_clockx_div .CLKOUT0_DIVIDE_F (mmcm_clock0_div), .CLKOUT0_PHASE (0), .CLKOUT1_DIVIDE (mmcm_clock1_div), .CLKOUT1_PHASE (0), .CLKOUT2_DIVIDE (mmcm_clock2_div), .CLKOUT2_PHASE (0), .CLKOUT3_DIVIDE (mmcm_clock3_div), .CLKOUT3_PHASE (0) ) mmcm_adv_i ( .CLKFBOUT (mmcm_clkfbout), .CLKOUT0 (clk_250), // 250 MHz for pipe_clk .CLKOUT1 (clk_125), // 125 MHz for pipe_clk .CLKOUT2 (user_clk_prebuf), // user clk .CLKOUT3 (clk_500), .CLKOUT4 (), .CLKOUT5 (), .CLKOUT6 (), .DO (), .DRDY (), .CLKFBOUTB (), .CLKFBSTOPPED (), .CLKINSTOPPED (), .CLKOUT0B (), .CLKOUT1B (), .CLKOUT2B (), .CLKOUT3B (), .PSDONE (), .LOCKED (mmcm_locked), .CLKFBIN (mmcm_clkfbin), .CLKIN1 (sys_clk), .CLKIN2 (1'b0), .CLKINSEL (1'b1), .DADDR (7'b0), .DCLK (1'b0), .DEN (1'b0), .DI (16'b0), .DWE (1'b0), .PSEN (1'b0), .PSINCDEC (1'b0), .PWRDWN (1'b0), .PSCLK (1'b0), .RST (mmcm_reset) ); // Synchronize MMCM locked output always @ (posedge pipe_clk or negedge gt_pll_lock) begin if (!gt_pll_lock) reg_clock_locked[1:0] <= #TCQ 2'b11; else reg_clock_locked[1:0] <= #TCQ {reg_clock_locked[0], 1'b0}; end assign clock_locked = !reg_clock_locked[1] & mmcm_locked; endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/pcie_endpoint.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : pcie_endpoint.v // Version : 2.4 //-- //-- Description: Virtex6 solution wrapper : Endpoint for PCI Express //-- //-- //-- //-------------------------------------------------------------------------------- `timescale 1ns/1ns (* CORE_GENERATION_INFO = "pcie_endpoint,v6_pcie_v2_5,{LINK_CAP_MAX_LINK_SPEED=1,LINK_CAP_MAX_LINK_WIDTH=08,PCIE_CAP_DEVICE_PORT_TYPE=0000,DEV_CAP_MAX_PAYLOAD_SUPPORTED=2,USER_CLK_FREQ=3,REF_CLK_FREQ=2,MSI_CAP_ON=TRUE,MSI_CAP_MULTIMSGCAP=0,MSI_CAP_MULTIMSG_EXTENSION=0,MSIX_CAP_ON=FALSE,TL_TX_RAM_RADDR_LATENCY=0,TL_TX_RAM_RDATA_LATENCY=2,TL_RX_RAM_RADDR_LATENCY=0,TL_RX_RAM_RDATA_LATENCY=2,TL_RX_RAM_WRITE_LATENCY=0,VC0_TX_LASTPACKET=29,VC0_RX_RAM_LIMIT=7FF,VC0_TOTAL_CREDITS_PH=4,VC0_TOTAL_CREDITS_PD=64,VC0_TOTAL_CREDITS_NPH=4,VC0_TOTAL_CREDITS_CH=72,VC0_TOTAL_CREDITS_CD=850,VC0_CPL_INFINITE=TRUE,DEV_CAP_PHANTOM_FUNCTIONS_SUPPORT=0,DEV_CAP_EXT_TAG_SUPPORTED=FALSE,LINK_STATUS_SLOT_CLOCK_CONFIG=FALSE,ENABLE_RX_TD_ECRC_TRIM=FALSE,DISABLE_LANE_REVERSAL=TRUE,DISABLE_SCRAMBLING=FALSE,DSN_CAP_ON=TRUE,PIPE_PIPELINE_STAGES=0,REVISION_ID=00,VC_CAP_ON=FALSE}" *) module pcie_endpoint # ( parameter ALLOW_X8_GEN2 = "FALSE", parameter BAR0 = 32'hFFFFFC00, parameter BAR1 = 32'h00000000, parameter BAR2 = 32'h00000000, parameter BAR3 = 32'h00000000, parameter BAR4 = 32'h00000000, parameter BAR5 = 32'h00000000, parameter CARDBUS_CIS_POINTER = 32'h00000000, parameter CLASS_CODE = 24'h050000, parameter CMD_INTX_IMPLEMENTED = "TRUE", parameter CPL_TIMEOUT_DISABLE_SUPPORTED = "FALSE", parameter CPL_TIMEOUT_RANGES_SUPPORTED = 4'h2, parameter DEV_CAP_ENDPOINT_L0S_LATENCY = 0, parameter DEV_CAP_ENDPOINT_L1_LATENCY = 7, parameter DEV_CAP_EXT_TAG_SUPPORTED = "FALSE", parameter DEV_CAP_MAX_PAYLOAD_SUPPORTED = 2, parameter DEV_CAP_PHANTOM_FUNCTIONS_SUPPORT = 0, parameter DEVICE_ID = 16'h6018, parameter DISABLE_LANE_REVERSAL = "TRUE", parameter DISABLE_SCRAMBLING = "FALSE", parameter DSN_BASE_PTR = 12'h100, parameter DSN_CAP_NEXTPTR = 12'h000, parameter DSN_CAP_ON = "TRUE", parameter ENABLE_MSG_ROUTE = 11'b00000000000, parameter ENABLE_RX_TD_ECRC_TRIM = "FALSE", parameter EXPANSION_ROM = 32'h00000000, parameter EXT_CFG_CAP_PTR = 6'h3F, parameter EXT_CFG_XP_CAP_PTR = 10'h3FF, parameter HEADER_TYPE = 8'h00, parameter INTERRUPT_PIN = 8'h1, parameter LINK_CAP_DLL_LINK_ACTIVE_REPORTING_CAP = "FALSE", parameter LINK_CAP_LINK_BANDWIDTH_NOTIFICATION_CAP = "FALSE", parameter LINK_CAP_MAX_LINK_SPEED = 4'h1, parameter LINK_CAP_MAX_LINK_WIDTH = 6'h08, parameter LINK_CAP_SURPRISE_DOWN_ERROR_CAPABLE = "FALSE", parameter LINK_CTRL2_DEEMPHASIS = "FALSE", parameter LINK_CTRL2_HW_AUTONOMOUS_SPEED_DISABLE = "FALSE", parameter LINK_CTRL2_TARGET_LINK_SPEED = 4'h0, parameter LINK_STATUS_SLOT_CLOCK_CONFIG = "FALSE", parameter LL_ACK_TIMEOUT = 15'h0000, parameter LL_ACK_TIMEOUT_EN = "FALSE", parameter LL_ACK_TIMEOUT_FUNC = 0, parameter LL_REPLAY_TIMEOUT = 15'h0026, parameter LL_REPLAY_TIMEOUT_EN = "TRUE", parameter LL_REPLAY_TIMEOUT_FUNC = 1, parameter LTSSM_MAX_LINK_WIDTH = 6'h08, parameter MSI_CAP_MULTIMSGCAP = 0, parameter MSI_CAP_MULTIMSG_EXTENSION = 0, parameter MSI_CAP_ON = "TRUE", parameter MSI_CAP_PER_VECTOR_MASKING_CAPABLE = "FALSE", parameter MSI_CAP_64_BIT_ADDR_CAPABLE = "TRUE", parameter MSIX_CAP_ON = "FALSE", parameter MSIX_CAP_PBA_BIR = 0, parameter MSIX_CAP_PBA_OFFSET = 29'h0, parameter MSIX_CAP_TABLE_BIR = 0, parameter MSIX_CAP_TABLE_OFFSET = 29'h0, parameter MSIX_CAP_TABLE_SIZE = 11'h0, parameter PCIE_CAP_DEVICE_PORT_TYPE = 4'b0000, parameter PCIE_CAP_INT_MSG_NUM = 5'h1, parameter PCIE_CAP_NEXTPTR = 8'h00, parameter PCIE_DRP_ENABLE = "FALSE", parameter PIPE_PIPELINE_STAGES = 0, // 0 - 0 stages, 1 - 1 stage, 2 - 2 stages parameter PM_CAP_DSI = "FALSE", parameter PM_CAP_D1SUPPORT = "FALSE", parameter PM_CAP_D2SUPPORT = "FALSE", parameter PM_CAP_NEXTPTR = 8'h48, parameter PM_CAP_PMESUPPORT = 5'h0F, parameter PM_CSR_NOSOFTRST = "TRUE", parameter PM_DATA_SCALE0 = 2'h0, parameter PM_DATA_SCALE1 = 2'h0, parameter PM_DATA_SCALE2 = 2'h0, parameter PM_DATA_SCALE3 = 2'h0, parameter PM_DATA_SCALE4 = 2'h0, parameter PM_DATA_SCALE5 = 2'h0, parameter PM_DATA_SCALE6 = 2'h0, parameter PM_DATA_SCALE7 = 2'h0, parameter PM_DATA0 = 8'h00, parameter PM_DATA1 = 8'h00, parameter PM_DATA2 = 8'h00, parameter PM_DATA3 = 8'h00, parameter PM_DATA4 = 8'h00, parameter PM_DATA5 = 8'h00, parameter PM_DATA6 = 8'h00, parameter PM_DATA7 = 8'h00, parameter REF_CLK_FREQ = 2, // 0 - 100 MHz, 1 - 125 MHz, 2 - 250 MHz parameter REVISION_ID = 8'h00, parameter SPARE_BIT0 = 0, parameter SUBSYSTEM_ID = 16'h0007, parameter SUBSYSTEM_VENDOR_ID = 16'h10EE, parameter TL_RX_RAM_RADDR_LATENCY = 0, parameter TL_RX_RAM_RDATA_LATENCY = 2, parameter TL_RX_RAM_WRITE_LATENCY = 0, parameter TL_TX_RAM_RADDR_LATENCY = 0, parameter TL_TX_RAM_RDATA_LATENCY = 2, parameter TL_TX_RAM_WRITE_LATENCY = 0, parameter UPCONFIG_CAPABLE = "TRUE", parameter USER_CLK_FREQ = 3, parameter VC_BASE_PTR = 12'h0, parameter VC_CAP_NEXTPTR = 12'h000, parameter VC_CAP_ON = "FALSE", parameter VC_CAP_REJECT_SNOOP_TRANSACTIONS = "FALSE", parameter VC0_CPL_INFINITE = "TRUE", parameter VC0_RX_RAM_LIMIT = 13'h7FF, parameter VC0_TOTAL_CREDITS_CD = 850, parameter VC0_TOTAL_CREDITS_CH = 72, parameter VC0_TOTAL_CREDITS_NPH = 4, parameter VC0_TOTAL_CREDITS_PD = 64, parameter VC0_TOTAL_CREDITS_PH = 4, parameter VC0_TX_LASTPACKET = 29, parameter VENDOR_ID = 16'h10EE, parameter VSEC_BASE_PTR = 12'h0, parameter VSEC_CAP_NEXTPTR = 12'h000, parameter VSEC_CAP_ON = "FALSE", parameter AER_BASE_PTR = 12'h128, parameter AER_CAP_ECRC_CHECK_CAPABLE = "FALSE", parameter AER_CAP_ECRC_GEN_CAPABLE = "FALSE", parameter AER_CAP_ID = 16'h0001, parameter AER_CAP_INT_MSG_NUM_MSI = 5'h0a, parameter AER_CAP_INT_MSG_NUM_MSIX = 5'h15, parameter AER_CAP_NEXTPTR = 12'h160, parameter AER_CAP_ON = "FALSE", parameter AER_CAP_PERMIT_ROOTERR_UPDATE = "TRUE", parameter AER_CAP_VERSION = 4'h1, parameter CAPABILITIES_PTR = 8'h40, parameter CRM_MODULE_RSTS = 7'h00, parameter DEV_CAP_ENABLE_SLOT_PWR_LIMIT_SCALE = "TRUE", parameter DEV_CAP_ENABLE_SLOT_PWR_LIMIT_VALUE = "TRUE", parameter DEV_CAP_FUNCTION_LEVEL_RESET_CAPABLE = "FALSE", parameter DEV_CAP_ROLE_BASED_ERROR = "TRUE", parameter DEV_CAP_RSVD_14_12 = 0, parameter DEV_CAP_RSVD_17_16 = 0, parameter DEV_CAP_RSVD_31_29 = 0, parameter DEV_CONTROL_AUX_POWER_SUPPORTED = "FALSE", parameter DISABLE_ASPM_L1_TIMER = "FALSE", parameter DISABLE_BAR_FILTERING = "FALSE", parameter DISABLE_ID_CHECK = "FALSE", parameter DISABLE_RX_TC_FILTER = "FALSE", parameter DNSTREAM_LINK_NUM = 8'h00, parameter DSN_CAP_ID = 16'h0003, parameter DSN_CAP_VERSION = 4'h1, parameter ENTER_RVRY_EI_L0 = "TRUE", parameter INFER_EI = 5'h0c, parameter IS_SWITCH = "FALSE", parameter LAST_CONFIG_DWORD = 10'h3FF, parameter LINK_CAP_ASPM_SUPPORT = 1, parameter LINK_CAP_CLOCK_POWER_MANAGEMENT = "FALSE", parameter LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN1 = 7, parameter LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN2 = 7, parameter LINK_CAP_L0S_EXIT_LATENCY_GEN1 = 7, parameter LINK_CAP_L0S_EXIT_LATENCY_GEN2 = 7, parameter LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN1 = 7, parameter LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN2 = 7, parameter LINK_CAP_L1_EXIT_LATENCY_GEN1 = 7, parameter LINK_CAP_L1_EXIT_LATENCY_GEN2 = 7, parameter LINK_CAP_RSVD_23_22 = 0, parameter LINK_CONTROL_RCB = 0, parameter MSI_BASE_PTR = 8'h48, parameter MSI_CAP_ID = 8'h05, parameter MSI_CAP_NEXTPTR = 8'h60, parameter MSIX_BASE_PTR = 8'h9c, parameter MSIX_CAP_ID = 8'h11, parameter MSIX_CAP_NEXTPTR = 8'h00, parameter N_FTS_COMCLK_GEN1 = 255, parameter N_FTS_COMCLK_GEN2 = 254, parameter N_FTS_GEN1 = 255, parameter N_FTS_GEN2 = 255, parameter PCIE_BASE_PTR = 8'h60, parameter PCIE_CAP_CAPABILITY_ID = 8'h10, parameter PCIE_CAP_CAPABILITY_VERSION = 4'h2, parameter PCIE_CAP_ON = "TRUE", parameter PCIE_CAP_RSVD_15_14 = 0, parameter PCIE_CAP_SLOT_IMPLEMENTED = "FALSE", parameter PCIE_REVISION = 2, parameter PGL0_LANE = 0, parameter PGL1_LANE = 1, parameter PGL2_LANE = 2, parameter PGL3_LANE = 3, parameter PGL4_LANE = 4, parameter PGL5_LANE = 5, parameter PGL6_LANE = 6, parameter PGL7_LANE = 7, parameter PL_AUTO_CONFIG = 0, parameter PL_FAST_TRAIN = "FALSE", parameter PM_BASE_PTR = 8'h40, parameter PM_CAP_AUXCURRENT = 0, parameter PM_CAP_ID = 8'h01, parameter PM_CAP_ON = "TRUE", parameter PM_CAP_PME_CLOCK = "FALSE", parameter PM_CAP_RSVD_04 = 0, parameter PM_CAP_VERSION = 3, parameter PM_CSR_BPCCEN = "FALSE", parameter PM_CSR_B2B3 = "FALSE", parameter RECRC_CHK = 0, parameter RECRC_CHK_TRIM = "FALSE", parameter ROOT_CAP_CRS_SW_VISIBILITY = "FALSE", parameter SELECT_DLL_IF = "FALSE", parameter SLOT_CAP_ATT_BUTTON_PRESENT = "FALSE", parameter SLOT_CAP_ATT_INDICATOR_PRESENT = "FALSE", parameter SLOT_CAP_ELEC_INTERLOCK_PRESENT = "FALSE", parameter SLOT_CAP_HOTPLUG_CAPABLE = "FALSE", parameter SLOT_CAP_HOTPLUG_SURPRISE = "FALSE", parameter SLOT_CAP_MRL_SENSOR_PRESENT = "FALSE", parameter SLOT_CAP_NO_CMD_COMPLETED_SUPPORT = "FALSE", parameter SLOT_CAP_PHYSICAL_SLOT_NUM = 13'h0000, parameter SLOT_CAP_POWER_CONTROLLER_PRESENT = "FALSE", parameter SLOT_CAP_POWER_INDICATOR_PRESENT = "FALSE", parameter SLOT_CAP_SLOT_POWER_LIMIT_SCALE = 0, parameter SLOT_CAP_SLOT_POWER_LIMIT_VALUE = 8'h00, parameter SPARE_BIT1 = 0, parameter SPARE_BIT2 = 0, parameter SPARE_BIT3 = 0, parameter SPARE_BIT4 = 0, parameter SPARE_BIT5 = 0, parameter SPARE_BIT6 = 0, parameter SPARE_BIT7 = 0, parameter SPARE_BIT8 = 0, parameter SPARE_BYTE0 = 8'h00, parameter SPARE_BYTE1 = 8'h00, parameter SPARE_BYTE2 = 8'h00, parameter SPARE_BYTE3 = 8'h00, parameter SPARE_WORD0 = 32'h00000000, parameter SPARE_WORD1 = 32'h00000000, parameter SPARE_WORD2 = 32'h00000000, parameter SPARE_WORD3 = 32'h00000000, parameter TL_RBYPASS = "FALSE", parameter TL_TFC_DISABLE = "FALSE", parameter TL_TX_CHECKS_DISABLE = "FALSE", parameter EXIT_LOOPBACK_ON_EI = "TRUE", parameter UPSTREAM_FACING = "TRUE", parameter UR_INV_REQ = "TRUE", parameter VC_CAP_ID = 16'h0002, parameter VC_CAP_VERSION = 4'h1, parameter VSEC_CAP_HDR_ID = 16'h1234, parameter VSEC_CAP_HDR_LENGTH = 12'h018, parameter VSEC_CAP_HDR_REVISION = 4'h1, parameter VSEC_CAP_ID = 16'h000b, parameter VSEC_CAP_IS_LINK_VISIBLE = "TRUE", parameter VSEC_CAP_VERSION = 4'h1 ) ( //------------------------------------------------------- // 1. PCI Express (pci_exp) Interface //------------------------------------------------------- // Tx output [(LINK_CAP_MAX_LINK_WIDTH - 1):0] pci_exp_txp, output [(LINK_CAP_MAX_LINK_WIDTH - 1):0] pci_exp_txn, // Rx input [(LINK_CAP_MAX_LINK_WIDTH - 1):0] pci_exp_rxp, input [(LINK_CAP_MAX_LINK_WIDTH - 1):0] pci_exp_rxn, //------------------------------------------------------- // 2. AXI-S Interface //------------------------------------------------------- // Common output user_clk_out, output user_reset_out, output user_lnk_up, // Tx output [5:0] tx_buf_av, output tx_err_drop, output tx_cfg_req, output s_axis_tx_tready, input [63:0] s_axis_tx_tdata, input [7:0] s_axis_tx_tkeep, input [3:0] s_axis_tx_tuser, input s_axis_tx_tlast, input s_axis_tx_tvalid, input tx_cfg_gnt, // Rx output [63:0] m_axis_rx_tdata, output [7:0] m_axis_rx_tkeep, output m_axis_rx_tlast, output m_axis_rx_tvalid, input m_axis_rx_tready, output [21:0] m_axis_rx_tuser, input rx_np_ok, // Flow Control output [11:0] fc_cpld, output [7:0] fc_cplh, output [11:0] fc_npd, output [7:0] fc_nph, output [11:0] fc_pd, output [7:0] fc_ph, input [2:0] fc_sel, //------------------------------------------------------- // 3. Configuration (CFG) Interface //------------------------------------------------------- output [31:0] cfg_do, output cfg_rd_wr_done, input [31:0] cfg_di, input [3:0] cfg_byte_en, input [9:0] cfg_dwaddr, input cfg_wr_en, input cfg_rd_en, input cfg_err_cor, input cfg_err_ur, input cfg_err_ecrc, input cfg_err_cpl_timeout, input cfg_err_cpl_abort, input cfg_err_cpl_unexpect, input cfg_err_posted, input cfg_err_locked, input [47:0] cfg_err_tlp_cpl_header, output cfg_err_cpl_rdy, input cfg_interrupt, output cfg_interrupt_rdy, input cfg_interrupt_assert, input [7:0] cfg_interrupt_di, output [7:0] cfg_interrupt_do, output [2:0] cfg_interrupt_mmenable, output cfg_interrupt_msienable, output cfg_interrupt_msixenable, output cfg_interrupt_msixfm, input cfg_turnoff_ok, output cfg_to_turnoff, input cfg_trn_pending, input cfg_pm_wake, output [7:0] cfg_bus_number, output [4:0] cfg_device_number, output [2:0] cfg_function_number, output [15:0] cfg_status, output [15:0] cfg_command, output [15:0] cfg_dstatus, output [15:0] cfg_dcommand, output [15:0] cfg_lstatus, output [15:0] cfg_lcommand, output [15:0] cfg_dcommand2, output [2:0] cfg_pcie_link_state, input [63:0] cfg_dsn, output cfg_pmcsr_pme_en, output cfg_pmcsr_pme_status, output [1:0] cfg_pmcsr_powerstate, //------------------------------------------------------- // 4. Physical Layer Control and Status (PL) Interface //------------------------------------------------------- output [2:0] pl_initial_link_width, output [1:0] pl_lane_reversal_mode, output pl_link_gen2_capable, output pl_link_partner_gen2_supported, output pl_link_upcfg_capable, output [5:0] pl_ltssm_state, output pl_received_hot_rst, output pl_sel_link_rate, output [1:0] pl_sel_link_width, input pl_directed_link_auton, input [1:0] pl_directed_link_change, input pl_directed_link_speed, input [1:0] pl_directed_link_width, input pl_upstream_prefer_deemph, //------------------------------------------------------- // 5. System (SYS) Interface //------------------------------------------------------- input sys_clk, input sys_reset ); wire [63:0] trn_td; wire trn_trem; wire trn_tsof; wire trn_teof; wire trn_tsrc_rdy; wire trn_tdst_rdy_n; wire trn_terr_drop_n; wire trn_tsrc_dsc; wire trn_terrfwd; wire trn_tstr; wire trn_tecrc_gen; wire [63:0] trn_rd; wire trn_rrem_n; wire trn_rsof_n; wire trn_reof_n; wire trn_rsrc_rdy_n; wire trn_rdst_rdy; wire trn_rsrc_dsc_n; wire trn_rerrfwd_n; wire [6:0] trn_rbar_hit_n; wire trn_tcfg_gnt; wire [31:0] trn_rdllp_data; wire trn_rdllp_src_rdy_n; wire rx_func_level_reset_n; wire cfg_msg_received; wire cfg_msg_received_pme_to; wire cfg_cmd_bme; wire cfg_cmd_intdis; wire cfg_cmd_io_en; wire cfg_cmd_mem_en; wire cfg_cmd_serr_en; wire cfg_dev_control_aux_power_en ; wire cfg_dev_control_corr_err_reporting_en ; wire cfg_dev_control_enable_relaxed_order ; wire cfg_dev_control_ext_tag_en ; wire cfg_dev_control_fatal_err_reporting_en ; wire [2:0] cfg_dev_control_maxpayload ; wire [2:0] cfg_dev_control_max_read_req ; wire cfg_dev_control_non_fatal_reporting_en ; wire cfg_dev_control_nosnoop_en ; wire cfg_dev_control_phantom_en ; wire cfg_dev_control_ur_err_reporting_en ; wire cfg_dev_control2_cpltimeout_dis ; wire [3:0] cfg_dev_control2_cpltimeout_val ; wire cfg_dev_status_corr_err_detected ; wire cfg_dev_status_fatal_err_detected ; wire cfg_dev_status_nonfatal_err_detected ; wire cfg_dev_status_ur_detected ; wire cfg_link_control_auto_bandwidth_int_en ; wire cfg_link_control_bandwidth_int_en ; wire cfg_link_control_hw_auto_width_dis ; wire cfg_link_control_clock_pm_en ; wire cfg_link_control_extended_sync ; wire cfg_link_control_common_clock ; wire cfg_link_control_retrain_link ; wire cfg_link_control_linkdisable ; wire cfg_link_control_rcb ; wire [1:0] cfg_link_control_aspm_control ; wire cfg_link_status_autobandwidth_status ; wire cfg_link_status_bandwidth_status ; wire cfg_link_status_dll_active ; wire cfg_link_status_link_training ; wire [3:0] cfg_link_status_negotiated_link_width ; wire [1:0] cfg_link_status_current_speed ; wire [15:0] cfg_msg_data; wire sys_reset_n_d; wire phy_rdy_n; wire trn_lnk_up_n_int; wire trn_lnk_up_n_int1; wire trn_reset_n_int; wire trn_reset_n_int1; wire TxOutClk; wire TxOutClk_bufg; reg [7:0] cfg_bus_number_d; reg [4:0] cfg_device_number_d; reg [2:0] cfg_function_number_d; wire cfg_rd_wr_done_n; wire cfg_interrupt_rdy_n; wire cfg_turnoff_ok_w; wire trn_recrc_err_n; wire cfg_err_cpl_rdy_n; wire trn_tcfg_req_n; // Inversion logic assign cfg_rd_wr_done = !cfg_rd_wr_done_n ; wire [3:0] cfg_byte_en_n = ~cfg_byte_en ; wire cfg_wr_en_n = !cfg_wr_en ; wire cfg_rd_en_n = !cfg_rd_en ; wire cfg_trn_pending_n = !cfg_trn_pending ; wire cfg_turnoff_ok_n = !cfg_turnoff_ok_w ; wire cfg_pm_wake_n = !cfg_pm_wake ; wire cfg_interrupt_n = !cfg_interrupt ; assign cfg_interrupt_rdy = !cfg_interrupt_rdy_n ; wire cfg_interrupt_assert_n = !cfg_interrupt_assert ; wire cfg_err_ecrc_n = !cfg_err_ecrc ; wire cfg_err_ur_n = !cfg_err_ur ; wire cfg_err_cpl_timeout_n = !cfg_err_cpl_timeout ; wire cfg_err_cpl_unexpect_n = !cfg_err_cpl_unexpect ; wire cfg_err_cpl_abort_n = !cfg_err_cpl_abort ; wire cfg_err_posted_n = !cfg_err_posted ; wire cfg_err_cor_n = !cfg_err_cor ; assign cfg_err_cpl_rdy = !cfg_err_cpl_rdy_n ; wire cfg_err_locked_n = !cfg_err_locked ; wire trn_recrc_err = !trn_recrc_err_n; assign tx_err_drop = !trn_terr_drop_n; assign tx_cfg_req = !trn_tcfg_req_n; // assigns to outputs assign cfg_to_turnoff = cfg_msg_received_pme_to; assign cfg_status = {16'b0}; assign cfg_command = {5'b0, cfg_cmd_intdis, 1'b0, cfg_cmd_serr_en, 5'b0, cfg_cmd_bme, cfg_cmd_mem_en, cfg_cmd_io_en}; assign cfg_dstatus = {10'h0, cfg_trn_pending, 1'b0, cfg_dev_status_ur_detected, cfg_dev_status_fatal_err_detected, cfg_dev_status_nonfatal_err_detected, cfg_dev_status_corr_err_detected}; assign cfg_dcommand = {1'b0, cfg_dev_control_max_read_req, cfg_dev_control_nosnoop_en, cfg_dev_control_aux_power_en, cfg_dev_control_phantom_en, cfg_dev_control_ext_tag_en, cfg_dev_control_maxpayload, cfg_dev_control_enable_relaxed_order, cfg_dev_control_ur_err_reporting_en, cfg_dev_control_fatal_err_reporting_en, cfg_dev_control_non_fatal_reporting_en, cfg_dev_control_corr_err_reporting_en }; assign cfg_lstatus = {cfg_link_status_autobandwidth_status, cfg_link_status_bandwidth_status, cfg_link_status_dll_active, (LINK_STATUS_SLOT_CLOCK_CONFIG == "TRUE") ? 1'b1 : 1'b0, cfg_link_status_link_training, 1'b0, {2'b00, cfg_link_status_negotiated_link_width}, {2'b00, cfg_link_status_current_speed} }; assign cfg_lcommand = {4'b0, cfg_link_control_auto_bandwidth_int_en, cfg_link_control_bandwidth_int_en, cfg_link_control_hw_auto_width_dis, cfg_link_control_clock_pm_en, cfg_link_control_extended_sync, cfg_link_control_common_clock, cfg_link_control_retrain_link, cfg_link_control_linkdisable, cfg_link_control_rcb, 1'b0, cfg_link_control_aspm_control }; assign cfg_bus_number = cfg_bus_number_d; assign cfg_device_number = cfg_device_number_d; assign cfg_function_number = cfg_function_number_d; assign cfg_dcommand2 = {11'b0, cfg_dev_control2_cpltimeout_dis, cfg_dev_control2_cpltimeout_val}; // Capture Bus/Device/Function number always @(posedge user_clk_out) begin if (!user_lnk_up) cfg_bus_number_d <= 8'b0; else if (~cfg_msg_received) cfg_bus_number_d <= cfg_msg_data[15:8]; end always @(posedge user_clk_out) begin if (!user_lnk_up) cfg_device_number_d <= 5'b0; else if (~cfg_msg_received) cfg_device_number_d <= cfg_msg_data[7:3]; end always @(posedge user_clk_out) begin if (!user_lnk_up) cfg_function_number_d <= 3'b0; else if (~cfg_msg_received) cfg_function_number_d <= cfg_msg_data[2:0]; end // Generate user_lnk_up FDCP #( .INIT(1'b0) ) trn_lnk_up_n_i ( .Q (user_lnk_up), .D (!trn_lnk_up_n_int1), .C (user_clk_out), .CLR (1'b0), .PRE (1'b0) ); FDCP #( .INIT(1'b1) ) trn_lnk_up_n_int_i ( .Q (trn_lnk_up_n_int1), .D (trn_lnk_up_n_int), .C (user_clk_out), .CLR (1'b0), .PRE (1'b0) ); // Generate user_reset_out FDCP #( .INIT(1'b1) ) trn_reset_n_i ( .Q (user_reset_out), .D (!(trn_reset_n_int1 & ~phy_rdy_n)), .C (user_clk_out), .CLR (~sys_reset_n_d), .PRE (1'b0) ); FDCP #( .INIT(1'b0) ) trn_reset_n_int_i ( .Q (trn_reset_n_int1 ), .D (trn_reset_n_int & ~phy_rdy_n), .C (user_clk_out), .CLR (~sys_reset_n_d), .PRE (1'b0) ); // AXI Basic Bridge // Converts between TRN and AXI axi_basic_top #( .C_DATA_WIDTH (64), // RX/TX interface data width .C_FAMILY ("V6"), // Targeted FPGA family .C_ROOT_PORT ("FALSE"), // PCIe block is in root port mode .C_PM_PRIORITY ("FALSE") // Disable TX packet boundary thrtl ) axi_basic_top ( //---------------------------------------------// // User Design I/O // //---------------------------------------------// // AXI TX //----------- .s_axis_tx_tdata (s_axis_tx_tdata), // input .s_axis_tx_tvalid (s_axis_tx_tvalid), // input .s_axis_tx_tready (s_axis_tx_tready), // output .s_axis_tx_tkeep (s_axis_tx_tkeep), // input .s_axis_tx_tlast (s_axis_tx_tlast), // input .s_axis_tx_tuser (s_axis_tx_tuser), // input // AXI RX //----------- .m_axis_rx_tdata (m_axis_rx_tdata), // output .m_axis_rx_tvalid (m_axis_rx_tvalid), // output .m_axis_rx_tready (m_axis_rx_tready), // input .m_axis_rx_tkeep (m_axis_rx_tkeep), // output .m_axis_rx_tlast (m_axis_rx_tlast), // output .m_axis_rx_tuser (m_axis_rx_tuser), // output // User Misc. //----------- .user_turnoff_ok (cfg_turnoff_ok), // input .user_tcfg_gnt (tx_cfg_gnt), // input //---------------------------------------------// // PCIe Block I/O // //---------------------------------------------// // TRN TX //----------- .trn_td (trn_td), // output .trn_tsof (trn_tsof), // output .trn_teof (trn_teof), // output .trn_tsrc_rdy (trn_tsrc_rdy), // output .trn_tdst_rdy (!trn_tdst_rdy_n), // input .trn_tsrc_dsc (trn_tsrc_dsc), // output .trn_trem (trn_trem), // output .trn_terrfwd (trn_terrfwd), // output .trn_tstr (trn_tstr), // output .trn_tbuf_av (tx_buf_av), // input .trn_tecrc_gen (trn_tecrc_gen), // output // TRN RX //----------- .trn_rd (trn_rd), // input .trn_rsof (!trn_rsof_n), // input .trn_reof (!trn_reof_n), // input .trn_rsrc_rdy (!trn_rsrc_rdy_n), // input .trn_rdst_rdy (trn_rdst_rdy), // output .trn_rsrc_dsc (!trn_rsrc_dsc_n), // input .trn_rrem (~trn_rrem_n), // input .trn_rerrfwd (!trn_rerrfwd_n), // input .trn_rbar_hit (~trn_rbar_hit_n), // input .trn_recrc_err (trn_recrc_err), // input // TRN Misc. //----------- .trn_tcfg_req (tx_cfg_req), // input .trn_tcfg_gnt (trn_tcfg_gnt), // output .trn_lnk_up (user_lnk_up), // input // Artix/Kintex/Virtex PM //----------- .cfg_pcie_link_state (cfg_pcie_link_state), // input // Virtex6 PM //----------- .cfg_pm_send_pme_to (1'b0), // input NOT USED FOR EP .cfg_pmcsr_powerstate (cfg_pmcsr_powerstate), // input .trn_rdllp_data (trn_rdllp_data), // input .trn_rdllp_src_rdy (!trn_rdllp_src_rdy_n), // input // Power Mgmt for S6/V6 //----------- .cfg_to_turnoff (cfg_to_turnoff), // input .cfg_turnoff_ok (cfg_turnoff_ok_w), // output // System //----------- .user_clk (user_clk_out), // input .user_rst (user_reset_out), // input .np_counter () // output ); //------------------------------------------------------- // PCI Express Reset Delay Module //------------------------------------------------------- pcie_reset_delay_v6 #( .PL_FAST_TRAIN ( PL_FAST_TRAIN ), .REF_CLK_FREQ ( REF_CLK_FREQ ) ) pcie_reset_delay_i ( .ref_clk ( TxOutClk_bufg ), .sys_reset_n ( !sys_reset ), .delayed_sys_reset_n ( sys_reset_n_d ) ); //------------------------------------------------------- // PCI Express Clocking Module //------------------------------------------------------- pcie_clocking_v6 #( .CAP_LINK_WIDTH(LINK_CAP_MAX_LINK_WIDTH), .CAP_LINK_SPEED(LINK_CAP_MAX_LINK_SPEED), .REF_CLK_FREQ(REF_CLK_FREQ), .USER_CLK_FREQ(USER_CLK_FREQ) ) pcie_clocking_i ( .sys_clk ( TxOutClk ), .gt_pll_lock ( gt_pll_lock ), .sel_lnk_rate ( pl_sel_link_rate ), .sel_lnk_width ( pl_sel_link_width ), .sys_clk_bufg ( TxOutClk_bufg ), .pipe_clk ( pipe_clk ), .user_clk ( user_clk_out ), .block_clk ( block_clk ), .drp_clk ( drp_clk ), .clock_locked ( clock_locked ) ); //------------------------------------------------------- // Virtex6 PCI Express Block Module //------------------------------------------------------- pcie_2_0_v6 #( .REF_CLK_FREQ ( REF_CLK_FREQ ), .PIPE_PIPELINE_STAGES ( PIPE_PIPELINE_STAGES ), .AER_BASE_PTR ( AER_BASE_PTR ), .AER_CAP_ECRC_CHECK_CAPABLE ( AER_CAP_ECRC_CHECK_CAPABLE ), .AER_CAP_ECRC_GEN_CAPABLE ( AER_CAP_ECRC_GEN_CAPABLE ), .AER_CAP_ID ( AER_CAP_ID ), .AER_CAP_INT_MSG_NUM_MSI ( AER_CAP_INT_MSG_NUM_MSI ), .AER_CAP_INT_MSG_NUM_MSIX ( AER_CAP_INT_MSG_NUM_MSIX ), .AER_CAP_NEXTPTR ( AER_CAP_NEXTPTR ), .AER_CAP_ON ( AER_CAP_ON ), .AER_CAP_PERMIT_ROOTERR_UPDATE ( AER_CAP_PERMIT_ROOTERR_UPDATE ), .AER_CAP_VERSION ( AER_CAP_VERSION ), .ALLOW_X8_GEN2 ( ALLOW_X8_GEN2 ), .BAR0 ( BAR0 ), .BAR1 ( BAR1 ), .BAR2 ( BAR2 ), .BAR3 ( BAR3 ), .BAR4 ( BAR4 ), .BAR5 ( BAR5 ), .CAPABILITIES_PTR ( CAPABILITIES_PTR ), .CARDBUS_CIS_POINTER ( CARDBUS_CIS_POINTER ), .CLASS_CODE ( CLASS_CODE ), .CMD_INTX_IMPLEMENTED ( CMD_INTX_IMPLEMENTED ), .CPL_TIMEOUT_DISABLE_SUPPORTED ( CPL_TIMEOUT_DISABLE_SUPPORTED ), .CPL_TIMEOUT_RANGES_SUPPORTED ( CPL_TIMEOUT_RANGES_SUPPORTED ), .CRM_MODULE_RSTS ( CRM_MODULE_RSTS ), .DEV_CAP_ENABLE_SLOT_PWR_LIMIT_SCALE ( DEV_CAP_ENABLE_SLOT_PWR_LIMIT_SCALE ), .DEV_CAP_ENABLE_SLOT_PWR_LIMIT_VALUE ( DEV_CAP_ENABLE_SLOT_PWR_LIMIT_VALUE ), .DEV_CAP_ENDPOINT_L0S_LATENCY ( DEV_CAP_ENDPOINT_L0S_LATENCY ), .DEV_CAP_ENDPOINT_L1_LATENCY ( DEV_CAP_ENDPOINT_L1_LATENCY ), .DEV_CAP_EXT_TAG_SUPPORTED ( DEV_CAP_EXT_TAG_SUPPORTED ), .DEV_CAP_FUNCTION_LEVEL_RESET_CAPABLE ( DEV_CAP_FUNCTION_LEVEL_RESET_CAPABLE ), .DEV_CAP_MAX_PAYLOAD_SUPPORTED ( DEV_CAP_MAX_PAYLOAD_SUPPORTED ), .DEV_CAP_PHANTOM_FUNCTIONS_SUPPORT ( DEV_CAP_PHANTOM_FUNCTIONS_SUPPORT ), .DEV_CAP_ROLE_BASED_ERROR ( DEV_CAP_ROLE_BASED_ERROR ), .DEV_CAP_RSVD_14_12 ( DEV_CAP_RSVD_14_12 ), .DEV_CAP_RSVD_17_16 ( DEV_CAP_RSVD_17_16 ), .DEV_CAP_RSVD_31_29 ( DEV_CAP_RSVD_31_29 ), .DEV_CONTROL_AUX_POWER_SUPPORTED ( DEV_CONTROL_AUX_POWER_SUPPORTED ), .DEVICE_ID ( DEVICE_ID ), .DISABLE_ASPM_L1_TIMER ( DISABLE_ASPM_L1_TIMER ), .DISABLE_BAR_FILTERING ( DISABLE_BAR_FILTERING ), .DISABLE_ID_CHECK ( DISABLE_ID_CHECK ), .DISABLE_LANE_REVERSAL ( DISABLE_LANE_REVERSAL ), .DISABLE_RX_TC_FILTER ( DISABLE_RX_TC_FILTER ), .DISABLE_SCRAMBLING ( DISABLE_SCRAMBLING ), .DNSTREAM_LINK_NUM ( DNSTREAM_LINK_NUM ), .DSN_BASE_PTR ( DSN_BASE_PTR ), .DSN_CAP_ID ( DSN_CAP_ID ), .DSN_CAP_NEXTPTR ( DSN_CAP_NEXTPTR ), .DSN_CAP_ON ( DSN_CAP_ON ), .DSN_CAP_VERSION ( DSN_CAP_VERSION ), .ENABLE_MSG_ROUTE ( ENABLE_MSG_ROUTE ), .ENABLE_RX_TD_ECRC_TRIM ( ENABLE_RX_TD_ECRC_TRIM ), .ENTER_RVRY_EI_L0 ( ENTER_RVRY_EI_L0 ), .EXPANSION_ROM ( EXPANSION_ROM ), .EXT_CFG_CAP_PTR ( EXT_CFG_CAP_PTR ), .EXT_CFG_XP_CAP_PTR ( EXT_CFG_XP_CAP_PTR ), .HEADER_TYPE ( HEADER_TYPE ), .INFER_EI ( INFER_EI ), .INTERRUPT_PIN ( INTERRUPT_PIN ), .IS_SWITCH ( IS_SWITCH ), .LAST_CONFIG_DWORD ( LAST_CONFIG_DWORD ), .LINK_CAP_ASPM_SUPPORT ( LINK_CAP_ASPM_SUPPORT ), .LINK_CAP_CLOCK_POWER_MANAGEMENT ( LINK_CAP_CLOCK_POWER_MANAGEMENT ), .LINK_CAP_DLL_LINK_ACTIVE_REPORTING_CAP ( LINK_CAP_DLL_LINK_ACTIVE_REPORTING_CAP ), .LINK_CAP_LINK_BANDWIDTH_NOTIFICATION_CAP ( LINK_CAP_LINK_BANDWIDTH_NOTIFICATION_CAP ), .LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN1 ( LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN1 ), .LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN2 ( LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN2 ), .LINK_CAP_L0S_EXIT_LATENCY_GEN1 ( LINK_CAP_L0S_EXIT_LATENCY_GEN1 ), .LINK_CAP_L0S_EXIT_LATENCY_GEN2 ( LINK_CAP_L0S_EXIT_LATENCY_GEN2 ), .LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN1 ( LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN1 ), .LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN2 ( LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN2 ), .LINK_CAP_L1_EXIT_LATENCY_GEN1 ( LINK_CAP_L1_EXIT_LATENCY_GEN1 ), .LINK_CAP_L1_EXIT_LATENCY_GEN2 ( LINK_CAP_L1_EXIT_LATENCY_GEN2 ), .LINK_CAP_MAX_LINK_SPEED ( LINK_CAP_MAX_LINK_SPEED ), .LINK_CAP_MAX_LINK_WIDTH ( LINK_CAP_MAX_LINK_WIDTH ), .LINK_CAP_RSVD_23_22 ( LINK_CAP_RSVD_23_22 ), .LINK_CAP_SURPRISE_DOWN_ERROR_CAPABLE ( LINK_CAP_SURPRISE_DOWN_ERROR_CAPABLE ), .LINK_CONTROL_RCB ( LINK_CONTROL_RCB ), .LINK_CTRL2_DEEMPHASIS ( LINK_CTRL2_DEEMPHASIS ), .LINK_CTRL2_HW_AUTONOMOUS_SPEED_DISABLE ( LINK_CTRL2_HW_AUTONOMOUS_SPEED_DISABLE ), .LINK_CTRL2_TARGET_LINK_SPEED ( LINK_CTRL2_TARGET_LINK_SPEED ), .LINK_STATUS_SLOT_CLOCK_CONFIG ( LINK_STATUS_SLOT_CLOCK_CONFIG ), .LL_ACK_TIMEOUT ( LL_ACK_TIMEOUT ), .LL_ACK_TIMEOUT_EN ( LL_ACK_TIMEOUT_EN ), .LL_ACK_TIMEOUT_FUNC ( LL_ACK_TIMEOUT_FUNC ), .LL_REPLAY_TIMEOUT ( LL_REPLAY_TIMEOUT ), .LL_REPLAY_TIMEOUT_EN ( LL_REPLAY_TIMEOUT_EN ), .LL_REPLAY_TIMEOUT_FUNC ( LL_REPLAY_TIMEOUT_FUNC ), .LTSSM_MAX_LINK_WIDTH ( LTSSM_MAX_LINK_WIDTH ), .MSI_BASE_PTR ( MSI_BASE_PTR ), .MSI_CAP_ID ( MSI_CAP_ID ), .MSI_CAP_MULTIMSGCAP ( MSI_CAP_MULTIMSGCAP ), .MSI_CAP_MULTIMSG_EXTENSION ( MSI_CAP_MULTIMSG_EXTENSION ), .MSI_CAP_NEXTPTR ( MSI_CAP_NEXTPTR ), .MSI_CAP_ON ( MSI_CAP_ON ), .MSI_CAP_PER_VECTOR_MASKING_CAPABLE ( MSI_CAP_PER_VECTOR_MASKING_CAPABLE ), .MSI_CAP_64_BIT_ADDR_CAPABLE ( MSI_CAP_64_BIT_ADDR_CAPABLE ), .MSIX_BASE_PTR ( MSIX_BASE_PTR ), .MSIX_CAP_ID ( MSIX_CAP_ID ), .MSIX_CAP_NEXTPTR ( MSIX_CAP_NEXTPTR ), .MSIX_CAP_ON ( MSIX_CAP_ON ), .MSIX_CAP_PBA_BIR ( MSIX_CAP_PBA_BIR ), .MSIX_CAP_PBA_OFFSET ( MSIX_CAP_PBA_OFFSET ), .MSIX_CAP_TABLE_BIR ( MSIX_CAP_TABLE_BIR ), .MSIX_CAP_TABLE_OFFSET ( MSIX_CAP_TABLE_OFFSET ), .MSIX_CAP_TABLE_SIZE ( MSIX_CAP_TABLE_SIZE ), .N_FTS_COMCLK_GEN1 ( N_FTS_COMCLK_GEN1 ), .N_FTS_COMCLK_GEN2 ( N_FTS_COMCLK_GEN2 ), .N_FTS_GEN1 ( N_FTS_GEN1 ), .N_FTS_GEN2 ( N_FTS_GEN2 ), .PCIE_BASE_PTR ( PCIE_BASE_PTR ), .PCIE_CAP_CAPABILITY_ID ( PCIE_CAP_CAPABILITY_ID ), .PCIE_CAP_CAPABILITY_VERSION ( PCIE_CAP_CAPABILITY_VERSION ), .PCIE_CAP_DEVICE_PORT_TYPE ( PCIE_CAP_DEVICE_PORT_TYPE ), .PCIE_CAP_INT_MSG_NUM ( PCIE_CAP_INT_MSG_NUM ), .PCIE_CAP_NEXTPTR ( PCIE_CAP_NEXTPTR ), .PCIE_CAP_ON ( PCIE_CAP_ON ), .PCIE_CAP_RSVD_15_14 ( PCIE_CAP_RSVD_15_14 ), .PCIE_CAP_SLOT_IMPLEMENTED ( PCIE_CAP_SLOT_IMPLEMENTED ), .PCIE_REVISION ( PCIE_REVISION ), .PGL0_LANE ( PGL0_LANE ), .PGL1_LANE ( PGL1_LANE ), .PGL2_LANE ( PGL2_LANE ), .PGL3_LANE ( PGL3_LANE ), .PGL4_LANE ( PGL4_LANE ), .PGL5_LANE ( PGL5_LANE ), .PGL6_LANE ( PGL6_LANE ), .PGL7_LANE ( PGL7_LANE ), .PL_AUTO_CONFIG ( PL_AUTO_CONFIG ), .PL_FAST_TRAIN ( PL_FAST_TRAIN ), .PM_BASE_PTR ( PM_BASE_PTR ), .PM_CAP_AUXCURRENT ( PM_CAP_AUXCURRENT ), .PM_CAP_DSI ( PM_CAP_DSI ), .PM_CAP_D1SUPPORT ( PM_CAP_D1SUPPORT ), .PM_CAP_D2SUPPORT ( PM_CAP_D2SUPPORT ), .PM_CAP_ID ( PM_CAP_ID ), .PM_CAP_NEXTPTR ( PM_CAP_NEXTPTR ), .PM_CAP_ON ( PM_CAP_ON ), .PM_CAP_PME_CLOCK ( PM_CAP_PME_CLOCK ), .PM_CAP_PMESUPPORT ( PM_CAP_PMESUPPORT ), .PM_CAP_RSVD_04 ( PM_CAP_RSVD_04 ), .PM_CAP_VERSION ( PM_CAP_VERSION ), .PM_CSR_BPCCEN ( PM_CSR_BPCCEN ), .PM_CSR_B2B3 ( PM_CSR_B2B3 ), .PM_CSR_NOSOFTRST ( PM_CSR_NOSOFTRST ), .PM_DATA_SCALE0 ( PM_DATA_SCALE0 ), .PM_DATA_SCALE1 ( PM_DATA_SCALE1 ), .PM_DATA_SCALE2 ( PM_DATA_SCALE2 ), .PM_DATA_SCALE3 ( PM_DATA_SCALE3 ), .PM_DATA_SCALE4 ( PM_DATA_SCALE4 ), .PM_DATA_SCALE5 ( PM_DATA_SCALE5 ), .PM_DATA_SCALE6 ( PM_DATA_SCALE6 ), .PM_DATA_SCALE7 ( PM_DATA_SCALE7 ), .PM_DATA0 ( PM_DATA0 ), .PM_DATA1 ( PM_DATA1 ), .PM_DATA2 ( PM_DATA2 ), .PM_DATA3 ( PM_DATA3 ), .PM_DATA4 ( PM_DATA4 ), .PM_DATA5 ( PM_DATA5 ), .PM_DATA6 ( PM_DATA6 ), .PM_DATA7 ( PM_DATA7 ), .RECRC_CHK ( RECRC_CHK ), .RECRC_CHK_TRIM ( RECRC_CHK_TRIM ), .REVISION_ID ( REVISION_ID ), .ROOT_CAP_CRS_SW_VISIBILITY ( ROOT_CAP_CRS_SW_VISIBILITY ), .SELECT_DLL_IF ( SELECT_DLL_IF ), .SLOT_CAP_ATT_BUTTON_PRESENT ( SLOT_CAP_ATT_BUTTON_PRESENT ), .SLOT_CAP_ATT_INDICATOR_PRESENT ( SLOT_CAP_ATT_INDICATOR_PRESENT ), .SLOT_CAP_ELEC_INTERLOCK_PRESENT ( SLOT_CAP_ELEC_INTERLOCK_PRESENT ), .SLOT_CAP_HOTPLUG_CAPABLE ( SLOT_CAP_HOTPLUG_CAPABLE ), .SLOT_CAP_HOTPLUG_SURPRISE ( SLOT_CAP_HOTPLUG_SURPRISE ), .SLOT_CAP_MRL_SENSOR_PRESENT ( SLOT_CAP_MRL_SENSOR_PRESENT ), .SLOT_CAP_NO_CMD_COMPLETED_SUPPORT ( SLOT_CAP_NO_CMD_COMPLETED_SUPPORT ), .SLOT_CAP_PHYSICAL_SLOT_NUM ( SLOT_CAP_PHYSICAL_SLOT_NUM ), .SLOT_CAP_POWER_CONTROLLER_PRESENT ( SLOT_CAP_POWER_CONTROLLER_PRESENT ), .SLOT_CAP_POWER_INDICATOR_PRESENT ( SLOT_CAP_POWER_INDICATOR_PRESENT ), .SLOT_CAP_SLOT_POWER_LIMIT_SCALE ( SLOT_CAP_SLOT_POWER_LIMIT_SCALE ), .SLOT_CAP_SLOT_POWER_LIMIT_VALUE ( SLOT_CAP_SLOT_POWER_LIMIT_VALUE ), .SPARE_BIT0 ( SPARE_BIT0 ), .SPARE_BIT1 ( SPARE_BIT1 ), .SPARE_BIT2 ( SPARE_BIT2 ), .SPARE_BIT3 ( SPARE_BIT3 ), .SPARE_BIT4 ( SPARE_BIT4 ), .SPARE_BIT5 ( SPARE_BIT5 ), .SPARE_BIT6 ( SPARE_BIT6 ), .SPARE_BIT7 ( SPARE_BIT7 ), .SPARE_BIT8 ( SPARE_BIT8 ), .SPARE_BYTE0 ( SPARE_BYTE0 ), .SPARE_BYTE1 ( SPARE_BYTE1 ), .SPARE_BYTE2 ( SPARE_BYTE2 ), .SPARE_BYTE3 ( SPARE_BYTE3 ), .SPARE_WORD0 ( SPARE_WORD0 ), .SPARE_WORD1 ( SPARE_WORD1 ), .SPARE_WORD2 ( SPARE_WORD2 ), .SPARE_WORD3 ( SPARE_WORD3 ), .SUBSYSTEM_ID ( SUBSYSTEM_ID ), .SUBSYSTEM_VENDOR_ID ( SUBSYSTEM_VENDOR_ID ), .TL_RBYPASS ( TL_RBYPASS ), .TL_RX_RAM_RADDR_LATENCY ( TL_RX_RAM_RADDR_LATENCY ), .TL_RX_RAM_RDATA_LATENCY ( TL_RX_RAM_RDATA_LATENCY ), .TL_RX_RAM_WRITE_LATENCY ( TL_RX_RAM_WRITE_LATENCY ), .TL_TFC_DISABLE ( TL_TFC_DISABLE ), .TL_TX_CHECKS_DISABLE ( TL_TX_CHECKS_DISABLE ), .TL_TX_RAM_RADDR_LATENCY ( TL_TX_RAM_RADDR_LATENCY ), .TL_TX_RAM_RDATA_LATENCY ( TL_TX_RAM_RDATA_LATENCY ), .TL_TX_RAM_WRITE_LATENCY ( TL_TX_RAM_WRITE_LATENCY ), .UPCONFIG_CAPABLE ( UPCONFIG_CAPABLE ), .UPSTREAM_FACING ( UPSTREAM_FACING ), .EXIT_LOOPBACK_ON_EI ( EXIT_LOOPBACK_ON_EI ), .UR_INV_REQ ( UR_INV_REQ ), .USER_CLK_FREQ ( USER_CLK_FREQ ), .VC_BASE_PTR ( VC_BASE_PTR ), .VC_CAP_ID ( VC_CAP_ID ), .VC_CAP_NEXTPTR ( VC_CAP_NEXTPTR ), .VC_CAP_ON ( VC_CAP_ON ), .VC_CAP_REJECT_SNOOP_TRANSACTIONS ( VC_CAP_REJECT_SNOOP_TRANSACTIONS ), .VC_CAP_VERSION ( VC_CAP_VERSION ), .VC0_CPL_INFINITE ( VC0_CPL_INFINITE ), .VC0_RX_RAM_LIMIT ( VC0_RX_RAM_LIMIT ), .VC0_TOTAL_CREDITS_CD ( VC0_TOTAL_CREDITS_CD ), .VC0_TOTAL_CREDITS_CH ( VC0_TOTAL_CREDITS_CH ), .VC0_TOTAL_CREDITS_NPH ( VC0_TOTAL_CREDITS_NPH ), .VC0_TOTAL_CREDITS_PD ( VC0_TOTAL_CREDITS_PD ), .VC0_TOTAL_CREDITS_PH ( VC0_TOTAL_CREDITS_PH ), .VC0_TX_LASTPACKET ( VC0_TX_LASTPACKET ), .VENDOR_ID ( VENDOR_ID ), .VSEC_BASE_PTR ( VSEC_BASE_PTR ), .VSEC_CAP_HDR_ID ( VSEC_CAP_HDR_ID ), .VSEC_CAP_HDR_LENGTH ( VSEC_CAP_HDR_LENGTH ), .VSEC_CAP_HDR_REVISION ( VSEC_CAP_HDR_REVISION ), .VSEC_CAP_ID ( VSEC_CAP_ID ), .VSEC_CAP_IS_LINK_VISIBLE ( VSEC_CAP_IS_LINK_VISIBLE ), .VSEC_CAP_NEXTPTR ( VSEC_CAP_NEXTPTR ), .VSEC_CAP_ON ( VSEC_CAP_ON ), .VSEC_CAP_VERSION ( VSEC_CAP_VERSION ) ) pcie_2_0_i ( .PCIEXPRXN( pci_exp_rxn ), .PCIEXPRXP( pci_exp_rxp ), .PCIEXPTXN( pci_exp_txn ), .PCIEXPTXP( pci_exp_txp ), .SYSCLK( sys_clk ), .TRNLNKUPN( trn_lnk_up_n_int ), .FUNDRSTN (sys_reset_n_d), .PHYRDYN( phy_rdy_n ), .LNKCLKEN ( ), .USERRSTN( trn_reset_n_int ), .RECEIVEDFUNCLVLRSTN( rx_func_level_reset_n ), .SYSRSTN( ~phy_rdy_n ), .PLRSTN( 1'b1 ), .DLRSTN( 1'b1 ), .TLRSTN( 1'b1 ), .FUNCLVLRSTN( 1'b1 ), .CMRSTN( 1'b1 ), .CMSTICKYRSTN( 1'b1 ), .TRNRBARHITN( trn_rbar_hit_n ), .TRNRD( trn_rd ), .TRNRECRCERRN( trn_recrc_err_n ), .TRNREOFN( trn_reof_n ), .TRNRERRFWDN( trn_rerrfwd_n ), .TRNRREMN( trn_rrem_n ), .TRNRSOFN( trn_rsof_n ), .TRNRSRCDSCN( trn_rsrc_dsc_n ), .TRNRSRCRDYN( trn_rsrc_rdy_n ), .TRNRDSTRDYN( !trn_rdst_rdy ), .TRNRNPOKN( !rx_np_ok ), .TRNTBUFAV( tx_buf_av ), .TRNTCFGREQN( trn_tcfg_req_n ), .TRNTDLLPDSTRDYN( ), .TRNTDSTRDYN( trn_tdst_rdy_n ), .TRNTERRDROPN( trn_terr_drop_n ), .TRNTCFGGNTN( !trn_tcfg_gnt ), .TRNTD( trn_td ), .TRNTDLLPDATA( 32'b0 ), .TRNTDLLPSRCRDYN( 1'b1 ), .TRNTECRCGENN( 1'b1 ), .TRNTEOFN( !trn_teof ), .TRNTERRFWDN( !trn_terrfwd ), .TRNTREMN( ~trn_trem ), .TRNTSOFN( !trn_tsof ), .TRNTSRCDSCN( !trn_tsrc_dsc ), .TRNTSRCRDYN( !trn_tsrc_rdy ), .TRNTSTRN( !trn_tstr ), .TRNFCCPLD( fc_cpld ), .TRNFCCPLH( fc_cplh ), .TRNFCNPD( fc_npd ), .TRNFCNPH( fc_nph ), .TRNFCPD( fc_pd ), .TRNFCPH( fc_ph ), .TRNFCSEL( fc_sel ), .CFGAERECRCCHECKEN(), .CFGAERECRCGENEN(), .CFGCOMMANDBUSMASTERENABLE( cfg_cmd_bme ), .CFGCOMMANDINTERRUPTDISABLE( cfg_cmd_intdis ), .CFGCOMMANDIOENABLE( cfg_cmd_io_en ), .CFGCOMMANDMEMENABLE( cfg_cmd_mem_en ), .CFGCOMMANDSERREN( cfg_cmd_serr_en ), .CFGDEVCONTROLAUXPOWEREN( cfg_dev_control_aux_power_en ), .CFGDEVCONTROLCORRERRREPORTINGEN( cfg_dev_control_corr_err_reporting_en ), .CFGDEVCONTROLENABLERO( cfg_dev_control_enable_relaxed_order ), .CFGDEVCONTROLEXTTAGEN( cfg_dev_control_ext_tag_en ), .CFGDEVCONTROLFATALERRREPORTINGEN( cfg_dev_control_fatal_err_reporting_en ), .CFGDEVCONTROLMAXPAYLOAD( cfg_dev_control_maxpayload ), .CFGDEVCONTROLMAXREADREQ( cfg_dev_control_max_read_req ), .CFGDEVCONTROLNONFATALREPORTINGEN( cfg_dev_control_non_fatal_reporting_en ), .CFGDEVCONTROLNOSNOOPEN( cfg_dev_control_nosnoop_en ), .CFGDEVCONTROLPHANTOMEN( cfg_dev_control_phantom_en ), .CFGDEVCONTROLURERRREPORTINGEN( cfg_dev_control_ur_err_reporting_en ), .CFGDEVCONTROL2CPLTIMEOUTDIS( cfg_dev_control2_cpltimeout_dis ), .CFGDEVCONTROL2CPLTIMEOUTVAL( cfg_dev_control2_cpltimeout_val ), .CFGDEVSTATUSCORRERRDETECTED( cfg_dev_status_corr_err_detected ), .CFGDEVSTATUSFATALERRDETECTED( cfg_dev_status_fatal_err_detected ), .CFGDEVSTATUSNONFATALERRDETECTED( cfg_dev_status_nonfatal_err_detected ), .CFGDEVSTATUSURDETECTED( cfg_dev_status_ur_detected ), .CFGDO( cfg_do ), .CFGERRAERHEADERLOGSETN(), .CFGERRCPLRDYN( cfg_err_cpl_rdy_n ), .CFGINTERRUPTDO( cfg_interrupt_do ), .CFGINTERRUPTMMENABLE( cfg_interrupt_mmenable ), .CFGINTERRUPTMSIENABLE( cfg_interrupt_msienable ), .CFGINTERRUPTMSIXENABLE( cfg_interrupt_msixenable ), .CFGINTERRUPTMSIXFM( cfg_interrupt_msixfm ), .CFGINTERRUPTRDYN( cfg_interrupt_rdy_n ), .CFGLINKCONTROLRCB( cfg_link_control_rcb ), .CFGLINKCONTROLASPMCONTROL( cfg_link_control_aspm_control ), .CFGLINKCONTROLAUTOBANDWIDTHINTEN( cfg_link_control_auto_bandwidth_int_en ), .CFGLINKCONTROLBANDWIDTHINTEN( cfg_link_control_bandwidth_int_en ), .CFGLINKCONTROLCLOCKPMEN( cfg_link_control_clock_pm_en ), .CFGLINKCONTROLCOMMONCLOCK( cfg_link_control_common_clock ), .CFGLINKCONTROLEXTENDEDSYNC( cfg_link_control_extended_sync ), .CFGLINKCONTROLHWAUTOWIDTHDIS( cfg_link_control_hw_auto_width_dis ), .CFGLINKCONTROLLINKDISABLE( cfg_link_control_linkdisable ), .CFGLINKCONTROLRETRAINLINK( cfg_link_control_retrain_link ), .CFGLINKSTATUSAUTOBANDWIDTHSTATUS( cfg_link_status_autobandwidth_status ), .CFGLINKSTATUSBANDWITHSTATUS( cfg_link_status_bandwidth_status ), .CFGLINKSTATUSCURRENTSPEED( cfg_link_status_current_speed ), .CFGLINKSTATUSDLLACTIVE( cfg_link_status_dll_active ), .CFGLINKSTATUSLINKTRAINING( cfg_link_status_link_training ), .CFGLINKSTATUSNEGOTIATEDWIDTH( cfg_link_status_negotiated_link_width ), .CFGMSGDATA( cfg_msg_data ), .CFGMSGRECEIVED( cfg_msg_received ), .CFGMSGRECEIVEDASSERTINTA(), .CFGMSGRECEIVEDASSERTINTB(), .CFGMSGRECEIVEDASSERTINTC(), .CFGMSGRECEIVEDASSERTINTD(), .CFGMSGRECEIVEDDEASSERTINTA(), .CFGMSGRECEIVEDDEASSERTINTB(), .CFGMSGRECEIVEDDEASSERTINTC(), .CFGMSGRECEIVEDDEASSERTINTD(), .CFGMSGRECEIVEDERRCOR(), .CFGMSGRECEIVEDERRFATAL(), .CFGMSGRECEIVEDERRNONFATAL(), .CFGMSGRECEIVEDPMASNAK(), .CFGMSGRECEIVEDPMETO( cfg_msg_received_pme_to ), .CFGMSGRECEIVEDPMETOACK(), .CFGMSGRECEIVEDPMPME(), .CFGMSGRECEIVEDSETSLOTPOWERLIMIT(), .CFGMSGRECEIVEDUNLOCK(), .CFGPCIELINKSTATE( cfg_pcie_link_state ), .CFGPMCSRPMEEN ( cfg_pmcsr_pme_en ), .CFGPMCSRPMESTATUS ( cfg_pmcsr_pme_status ), .CFGPMCSRPOWERSTATE ( cfg_pmcsr_powerstate ), .CFGPMRCVASREQL1N(), .CFGPMRCVENTERL1N(), .CFGPMRCVENTERL23N(), .CFGPMRCVREQACKN(), .CFGRDWRDONEN( cfg_rd_wr_done_n ), .CFGSLOTCONTROLELECTROMECHILCTLPULSE(), .CFGTRANSACTION(), .CFGTRANSACTIONADDR(), .CFGTRANSACTIONTYPE(), .CFGVCTCVCMAP(), .CFGBYTEENN( cfg_byte_en_n ), .CFGDI( cfg_di ), .CFGDSBUSNUMBER( 8'b0 ), .CFGDSDEVICENUMBER( 5'b0 ), .CFGDSFUNCTIONNUMBER( 3'b0 ), .CFGDSN( cfg_dsn ), .CFGDWADDR( cfg_dwaddr ), .CFGERRACSN( 1'b1 ), .CFGERRAERHEADERLOG( 128'h0 ), .CFGERRCORN( cfg_err_cor_n ), .CFGERRCPLABORTN( cfg_err_cpl_abort_n ), .CFGERRCPLTIMEOUTN( cfg_err_cpl_timeout_n ), .CFGERRCPLUNEXPECTN( cfg_err_cpl_unexpect_n ), .CFGERRECRCN( cfg_err_ecrc_n ), .CFGERRLOCKEDN( cfg_err_locked_n ), .CFGERRPOSTEDN( cfg_err_posted_n ), .CFGERRTLPCPLHEADER( cfg_err_tlp_cpl_header ), .CFGERRURN( cfg_err_ur_n ), .CFGINTERRUPTASSERTN( cfg_interrupt_assert_n ), .CFGINTERRUPTDI( cfg_interrupt_di ), .CFGINTERRUPTN( cfg_interrupt_n ), .CFGPMDIRECTASPML1N( 1'b1 ), .CFGPMSENDPMACKN( 1'b1 ), .CFGPMSENDPMETON( 1'b1 ), .CFGPMSENDPMNAKN( 1'b1 ), .CFGPMTURNOFFOKN( cfg_turnoff_ok_n ), .CFGPMWAKEN( cfg_pm_wake_n ), .CFGPORTNUMBER( 8'h0 ), .CFGRDENN( cfg_rd_en_n ), .CFGTRNPENDINGN( cfg_trn_pending_n ), .CFGWRENN( cfg_wr_en_n ), .CFGWRREADONLYN( 1'b1 ), .CFGWRRW1CASRWN( 1'b1 ), .PLINITIALLINKWIDTH( pl_initial_link_width ), .PLLANEREVERSALMODE( pl_lane_reversal_mode ), .PLLINKGEN2CAP( pl_link_gen2_capable ), .PLLINKPARTNERGEN2SUPPORTED( pl_link_partner_gen2_supported ), .PLLINKUPCFGCAP( pl_link_upcfg_capable ), .PLLTSSMSTATE( pl_ltssm_state ), .PLPHYLNKUPN( ), // Debug .PLRECEIVEDHOTRST( pl_received_hot_rst ), .PLRXPMSTATE(), // Debug .PLSELLNKRATE( pl_sel_link_rate ), .PLSELLNKWIDTH( pl_sel_link_width ), .PLTXPMSTATE(), // Debug .PLDIRECTEDLINKAUTON( pl_directed_link_auton ), .PLDIRECTEDLINKCHANGE( pl_directed_link_change ), .PLDIRECTEDLINKSPEED( pl_directed_link_speed ), .PLDIRECTEDLINKWIDTH( pl_directed_link_width ), .PLDOWNSTREAMDEEMPHSOURCE( 1'b1 ), .PLUPSTREAMPREFERDEEMPH( pl_upstream_prefer_deemph ), .PLTRANSMITHOTRST( 1'b0 ), .DBGSCLRA(), .DBGSCLRB(), .DBGSCLRC(), .DBGSCLRD(), .DBGSCLRE(), .DBGSCLRF(), .DBGSCLRG(), .DBGSCLRH(), .DBGSCLRI(), .DBGSCLRJ(), .DBGSCLRK(), .DBGVECA(), .DBGVECB(), .DBGVECC(), .PLDBGVEC(), .DBGMODE( 2'b0 ), .DBGSUBMODE( 1'b0 ), .PLDBGMODE( 3'b0 ), .PCIEDRPDO(), .PCIEDRPDRDY(), .PCIEDRPCLK(1'b0), .PCIEDRPDADDR(9'b0), .PCIEDRPDEN(1'b0), .PCIEDRPDI(16'b0), .PCIEDRPDWE(1'b0), .GTPLLLOCK( gt_pll_lock ), .PIPECLK( pipe_clk ), .USERCLK( user_clk_out ), .DRPCLK(drp_clk), .CLOCKLOCKED( clock_locked ), .TxOutClk(TxOutClk), .TRNRDLLPDATA(trn_rdllp_data), .TRNRDLLPSRCRDYN(trn_rdllp_src_rdy_n) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/pcie_gtx_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : pcie_gtx_v6.v // Version : 2.4 //-- Description: GTX module for Virtex6 PCIe Block //-- //-- //-- //-------------------------------------------------------------------------------- `timescale 1ns/1ns module pcie_gtx_v6 # ( parameter TCQ = 1, // clock to out delay model parameter NO_OF_LANES = 8, // 1 - x1 , 2 - x2 , 4 - x4 , 8 - x8 parameter LINK_CAP_MAX_LINK_SPEED = 4'h1, // 1 - Gen1, 2 - Gen2 parameter REF_CLK_FREQ = 0, // 0 - 100 MHz , 1 - 125 MHz , 2 - 250 MHz parameter PL_FAST_TRAIN = "FALSE" ) ( // Pipe Per-Link Signals input wire pipe_tx_rcvr_det , input wire pipe_tx_reset , input wire pipe_tx_rate , input wire pipe_tx_deemph , input wire [2:0] pipe_tx_margin , input wire pipe_tx_swing , // Pipe Per-Lane Signals - Lane 0 output wire [ 1:0] pipe_rx0_char_is_k , output wire [15:0] pipe_rx0_data , output wire pipe_rx0_valid , output wire pipe_rx0_chanisaligned , output wire [ 2:0] pipe_rx0_status , output wire pipe_rx0_phy_status , output wire pipe_rx0_elec_idle , input wire pipe_rx0_polarity , input wire pipe_tx0_compliance , input wire [ 1:0] pipe_tx0_char_is_k , input wire [15:0] pipe_tx0_data , input wire pipe_tx0_elec_idle , input wire [ 1:0] pipe_tx0_powerdown , // Pipe Per-Lane Signals - Lane 1 output wire [ 1:0] pipe_rx1_char_is_k , output wire [15:0] pipe_rx1_data , output wire pipe_rx1_valid , output wire pipe_rx1_chanisaligned , output wire [ 2:0] pipe_rx1_status , output wire pipe_rx1_phy_status , output wire pipe_rx1_elec_idle , input wire pipe_rx1_polarity , input wire pipe_tx1_compliance , input wire [ 1:0] pipe_tx1_char_is_k , input wire [15:0] pipe_tx1_data , input wire pipe_tx1_elec_idle , input wire [ 1:0] pipe_tx1_powerdown , // Pipe Per-Lane Signals - Lane 2 output wire [ 1:0] pipe_rx2_char_is_k , output wire [15:0] pipe_rx2_data , output wire pipe_rx2_valid , output wire pipe_rx2_chanisaligned , output wire [ 2:0] pipe_rx2_status , output wire pipe_rx2_phy_status , output wire pipe_rx2_elec_idle , input wire pipe_rx2_polarity , input wire pipe_tx2_compliance , input wire [ 1:0] pipe_tx2_char_is_k , input wire [15:0] pipe_tx2_data , input wire pipe_tx2_elec_idle , input wire [ 1:0] pipe_tx2_powerdown , // Pipe Per-Lane Signals - Lane 3 output wire [ 1:0] pipe_rx3_char_is_k , output wire [15:0] pipe_rx3_data , output wire pipe_rx3_valid , output wire pipe_rx3_chanisaligned , output wire [ 2:0] pipe_rx3_status , output wire pipe_rx3_phy_status , output wire pipe_rx3_elec_idle , input wire pipe_rx3_polarity , input wire pipe_tx3_compliance , input wire [ 1:0] pipe_tx3_char_is_k , input wire [15:0] pipe_tx3_data , input wire pipe_tx3_elec_idle , input wire [ 1:0] pipe_tx3_powerdown , // Pipe Per-Lane Signals - Lane 4 output wire [ 1:0] pipe_rx4_char_is_k , output wire [15:0] pipe_rx4_data , output wire pipe_rx4_valid , output wire pipe_rx4_chanisaligned , output wire [ 2:0] pipe_rx4_status , output wire pipe_rx4_phy_status , output wire pipe_rx4_elec_idle , input wire pipe_rx4_polarity , input wire pipe_tx4_compliance , input wire [ 1:0] pipe_tx4_char_is_k , input wire [15:0] pipe_tx4_data , input wire pipe_tx4_elec_idle , input wire [ 1:0] pipe_tx4_powerdown , // Pipe Per-Lane Signals - Lane 5 output wire [ 1:0] pipe_rx5_char_is_k , output wire [15:0] pipe_rx5_data , output wire pipe_rx5_valid , output wire pipe_rx5_chanisaligned , output wire [ 2:0] pipe_rx5_status , output wire pipe_rx5_phy_status , output wire pipe_rx5_elec_idle , input wire pipe_rx5_polarity , input wire pipe_tx5_compliance , input wire [ 1:0] pipe_tx5_char_is_k , input wire [15:0] pipe_tx5_data , input wire pipe_tx5_elec_idle , input wire [ 1:0] pipe_tx5_powerdown , // Pipe Per-Lane Signals - Lane 6 output wire [ 1:0] pipe_rx6_char_is_k , output wire [15:0] pipe_rx6_data , output wire pipe_rx6_valid , output wire pipe_rx6_chanisaligned , output wire [ 2:0] pipe_rx6_status , output wire pipe_rx6_phy_status , output wire pipe_rx6_elec_idle , input wire pipe_rx6_polarity , input wire pipe_tx6_compliance , input wire [ 1:0] pipe_tx6_char_is_k , input wire [15:0] pipe_tx6_data , input wire pipe_tx6_elec_idle , input wire [ 1:0] pipe_tx6_powerdown , // Pipe Per-Lane Signals - Lane 7 output wire [ 1:0] pipe_rx7_char_is_k , output wire [15:0] pipe_rx7_data , output wire pipe_rx7_valid , output wire pipe_rx7_chanisaligned , output wire [ 2:0] pipe_rx7_status , output wire pipe_rx7_phy_status , output wire pipe_rx7_elec_idle , input wire pipe_rx7_polarity , input wire pipe_tx7_compliance , input wire [ 1:0] pipe_tx7_char_is_k , input wire [15:0] pipe_tx7_data , input wire pipe_tx7_elec_idle , input wire [ 1:0] pipe_tx7_powerdown , // PCI Express signals output wire [ (NO_OF_LANES-1):0] pci_exp_txn , output wire [ (NO_OF_LANES-1):0] pci_exp_txp , input wire [ (NO_OF_LANES-1):0] pci_exp_rxn , input wire [ (NO_OF_LANES-1):0] pci_exp_rxp , // Non PIPE signals input wire sys_clk , input wire sys_rst_n , input wire pipe_clk , input wire drp_clk , input wire clock_locked , output wire gt_pll_lock , input wire [ 5:0] pl_ltssm_state , output reg phy_rdy_n , output wire TxOutClk ); wire [ 7:0] gt_rx_phy_status_wire ; wire [ 7:0] gt_rxchanisaligned_wire ; wire [127:0] gt_rx_data_k_wire ; wire [127:0] gt_rx_data_wire ; wire [ 7:0] gt_rx_elec_idle_wire ; wire [ 23:0] gt_rx_status_wire ; wire [ 7:0] gt_rx_valid_wire ; wire [ 7:0] gt_rx_polarity ; wire [ 15:0] gt_power_down ; wire [ 7:0] gt_tx_char_disp_mode ; wire [ 15:0] gt_tx_data_k ; wire [127:0] gt_tx_data ; wire gt_tx_detect_rx_loopback ; wire [ 7:0] gt_tx_elec_idle ; wire [ 7:0] gt_rx_elec_idle_reset ; wire [NO_OF_LANES-1:0] plllkdet; wire RxResetDone; reg local_pcs_reset; reg local_pcs_reset_done; reg [3:0] cnt_local_pcs_reset; reg [4:0] phy_rdy_pre_cnt; reg [5:0] pl_ltssm_state_q; wire plm_in_l0 = (pl_ltssm_state_q == 6'h16); wire plm_in_rl = (pl_ltssm_state_q == 6'h1c); wire plm_in_dt = (pl_ltssm_state_q == 6'h2d); wire plm_in_rs = (pl_ltssm_state_q == 6'h1f); gtx_wrapper_v6 #( .NO_OF_LANES(NO_OF_LANES), .REF_CLK_FREQ(REF_CLK_FREQ), .PL_FAST_TRAIN(PL_FAST_TRAIN) ) gtx_v6_i ( // TX .TX(pci_exp_txp[((NO_OF_LANES)-1):0]), .TX_(pci_exp_txn[((NO_OF_LANES)-1):0]), .TxData(gt_tx_data[((16*NO_OF_LANES)-1):0]), .TxDataK(gt_tx_data_k[((2*NO_OF_LANES)-1):0]), .TxElecIdle(gt_tx_elec_idle[((NO_OF_LANES)-1):0]), .TxCompliance(gt_tx_char_disp_mode[((NO_OF_LANES)-1):0]), // RX .RX(pci_exp_rxp[((NO_OF_LANES)-1):0]), .RX_(pci_exp_rxn[((NO_OF_LANES)-1):0]), .RxData(gt_rx_data_wire[((16*NO_OF_LANES)-1):0]), .RxDataK(gt_rx_data_k_wire[((2*NO_OF_LANES)-1):0]), .RxPolarity(gt_rx_polarity[((NO_OF_LANES)-1):0]), .RxValid(gt_rx_valid_wire[((NO_OF_LANES)-1):0]), .RxElecIdle(gt_rx_elec_idle_wire[((NO_OF_LANES)-1):0]), .RxStatus(gt_rx_status_wire[((3*NO_OF_LANES)-1):0]), // other .GTRefClkout(), .plm_in_l0(plm_in_l0), .plm_in_rl(plm_in_rl), .plm_in_dt(plm_in_dt), .plm_in_rs(plm_in_rs), .RxPLLLkDet(plllkdet), .ChanIsAligned(gt_rxchanisaligned_wire[((NO_OF_LANES)-1):0]), .TxDetectRx(gt_tx_detect_rx_loopback), .PhyStatus(gt_rx_phy_status_wire[((NO_OF_LANES)-1):0]), .TXPdownAsynch(~clock_locked), .PowerDown(gt_power_down[((2*NO_OF_LANES)-1):0]), .Rate(pipe_tx_rate), .Reset_n(clock_locked), .GTReset_n(sys_rst_n), .PCLK(pipe_clk), .REFCLK(sys_clk), .DRPCLK(drp_clk), .TxDeemph(pipe_tx_deemph), .TxMargin(pipe_tx_margin[2]), .TxSwing(pipe_tx_swing), .local_pcs_reset(local_pcs_reset), .RxResetDone(RxResetDone), .SyncDone(SyncDone), .TxOutClk(TxOutClk) ); assign pipe_rx0_phy_status = gt_rx_phy_status_wire[0] ; assign pipe_rx1_phy_status = (NO_OF_LANES >= 2 ) ? gt_rx_phy_status_wire[1] : 1'b0; assign pipe_rx2_phy_status = (NO_OF_LANES >= 4 ) ? gt_rx_phy_status_wire[2] : 1'b0; assign pipe_rx3_phy_status = (NO_OF_LANES >= 4 ) ? gt_rx_phy_status_wire[3] : 1'b0; assign pipe_rx4_phy_status = (NO_OF_LANES >= 8 ) ? gt_rx_phy_status_wire[4] : 1'b0; assign pipe_rx5_phy_status = (NO_OF_LANES >= 8 ) ? gt_rx_phy_status_wire[5] : 1'b0; assign pipe_rx6_phy_status = (NO_OF_LANES >= 8 ) ? gt_rx_phy_status_wire[6] : 1'b0; assign pipe_rx7_phy_status = (NO_OF_LANES >= 8 ) ? gt_rx_phy_status_wire[7] : 1'b0; assign pipe_rx0_chanisaligned = gt_rxchanisaligned_wire[0]; assign pipe_rx1_chanisaligned = (NO_OF_LANES >= 2 ) ? gt_rxchanisaligned_wire[1] : 1'b0 ; assign pipe_rx2_chanisaligned = (NO_OF_LANES >= 4 ) ? gt_rxchanisaligned_wire[2] : 1'b0 ; assign pipe_rx3_chanisaligned = (NO_OF_LANES >= 4 ) ? gt_rxchanisaligned_wire[3] : 1'b0 ; assign pipe_rx4_chanisaligned = (NO_OF_LANES >= 8 ) ? gt_rxchanisaligned_wire[4] : 1'b0 ; assign pipe_rx5_chanisaligned = (NO_OF_LANES >= 8 ) ? gt_rxchanisaligned_wire[5] : 1'b0 ; assign pipe_rx6_chanisaligned = (NO_OF_LANES >= 8 ) ? gt_rxchanisaligned_wire[6] : 1'b0 ; assign pipe_rx7_chanisaligned = (NO_OF_LANES >= 8 ) ? gt_rxchanisaligned_wire[7] : 1'b0 ; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< assign pipe_rx0_char_is_k = {gt_rx_data_k_wire[1], gt_rx_data_k_wire[0]}; assign pipe_rx1_char_is_k = (NO_OF_LANES >= 2 ) ? {gt_rx_data_k_wire[3], gt_rx_data_k_wire[2]} : 2'b0 ; assign pipe_rx2_char_is_k = (NO_OF_LANES >= 4 ) ? {gt_rx_data_k_wire[5], gt_rx_data_k_wire[4]} : 2'b0 ; assign pipe_rx3_char_is_k = (NO_OF_LANES >= 4 ) ? {gt_rx_data_k_wire[7], gt_rx_data_k_wire[6]} : 2'b0 ; assign pipe_rx4_char_is_k = (NO_OF_LANES >= 8 ) ? {gt_rx_data_k_wire[9], gt_rx_data_k_wire[8]} : 2'b0 ; assign pipe_rx5_char_is_k = (NO_OF_LANES >= 8 ) ? {gt_rx_data_k_wire[11], gt_rx_data_k_wire[10]} : 2'b0 ; assign pipe_rx6_char_is_k = (NO_OF_LANES >= 8 ) ? {gt_rx_data_k_wire[13], gt_rx_data_k_wire[12]} : 2'b0 ; assign pipe_rx7_char_is_k = (NO_OF_LANES >= 8 ) ? {gt_rx_data_k_wire[15], gt_rx_data_k_wire[14]} : 2'b0 ; assign pipe_rx0_data = {gt_rx_data_wire[ 15: 8], gt_rx_data_wire[ 7: 0]}; assign pipe_rx1_data = (NO_OF_LANES >= 2 ) ? {gt_rx_data_wire[31:24], gt_rx_data_wire[23:16]} : 16'h0 ; assign pipe_rx2_data = (NO_OF_LANES >= 4 ) ? {gt_rx_data_wire[47:40], gt_rx_data_wire[39:32]} : 16'h0 ; assign pipe_rx3_data = (NO_OF_LANES >= 4 ) ? {gt_rx_data_wire[63:56], gt_rx_data_wire[55:48]} : 16'h0 ; assign pipe_rx4_data = (NO_OF_LANES >= 8 ) ? {gt_rx_data_wire[79:72], gt_rx_data_wire[71:64]} : 16'h0 ; assign pipe_rx5_data = (NO_OF_LANES >= 8 ) ? {gt_rx_data_wire[95:88], gt_rx_data_wire[87:80]} : 16'h0 ; assign pipe_rx6_data = (NO_OF_LANES >= 8 ) ? {gt_rx_data_wire[111:104], gt_rx_data_wire[103:96]} : 16'h0 ; assign pipe_rx7_data = (NO_OF_LANES >= 8 ) ? {gt_rx_data_wire[127:120], gt_rx_data_wire[119:112]} : 16'h0 ; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< assign pipe_rx0_elec_idle = gt_rx_elec_idle_wire[0]; assign pipe_rx1_elec_idle = (NO_OF_LANES >= 2 ) ? gt_rx_elec_idle_wire[1] : 1'b1 ; assign pipe_rx2_elec_idle = (NO_OF_LANES >= 4 ) ? gt_rx_elec_idle_wire[2] : 1'b1 ; assign pipe_rx3_elec_idle = (NO_OF_LANES >= 4 ) ? gt_rx_elec_idle_wire[3] : 1'b1 ; assign pipe_rx4_elec_idle = (NO_OF_LANES >= 8 ) ? gt_rx_elec_idle_wire[4] : 1'b1 ; assign pipe_rx5_elec_idle = (NO_OF_LANES >= 8 ) ? gt_rx_elec_idle_wire[5] : 1'b1 ; assign pipe_rx6_elec_idle = (NO_OF_LANES >= 8 ) ? gt_rx_elec_idle_wire[6] : 1'b1 ; assign pipe_rx7_elec_idle = (NO_OF_LANES >= 8 ) ? gt_rx_elec_idle_wire[7] : 1'b1 ; assign pipe_rx0_status = gt_rx_status_wire[ 2: 0]; assign pipe_rx1_status = (NO_OF_LANES >= 2 ) ? gt_rx_status_wire[ 5: 3] : 3'b0 ; assign pipe_rx2_status = (NO_OF_LANES >= 4 ) ? gt_rx_status_wire[ 8: 6] : 3'b0 ; assign pipe_rx3_status = (NO_OF_LANES >= 4 ) ? gt_rx_status_wire[11: 9] : 3'b0 ; assign pipe_rx4_status = (NO_OF_LANES >= 8 ) ? gt_rx_status_wire[14:12] : 3'b0 ; assign pipe_rx5_status = (NO_OF_LANES >= 8 ) ? gt_rx_status_wire[17:15] : 3'b0 ; assign pipe_rx6_status = (NO_OF_LANES >= 8 ) ? gt_rx_status_wire[20:18] : 3'b0 ; assign pipe_rx7_status = (NO_OF_LANES >= 8 ) ? gt_rx_status_wire[23:21] : 3'b0 ; assign pipe_rx0_valid = gt_rx_valid_wire[0]; assign pipe_rx1_valid = (NO_OF_LANES >= 2 ) ? gt_rx_valid_wire[1] : 1'b0 ; assign pipe_rx2_valid = (NO_OF_LANES >= 4 ) ? gt_rx_valid_wire[2] : 1'b0 ; assign pipe_rx3_valid = (NO_OF_LANES >= 4 ) ? gt_rx_valid_wire[3] : 1'b0 ; assign pipe_rx4_valid = (NO_OF_LANES >= 8 ) ? gt_rx_valid_wire[4] : 1'b0 ; assign pipe_rx5_valid = (NO_OF_LANES >= 8 ) ? gt_rx_valid_wire[5] : 1'b0 ; assign pipe_rx6_valid = (NO_OF_LANES >= 8 ) ? gt_rx_valid_wire[6] : 1'b0 ; assign pipe_rx7_valid = (NO_OF_LANES >= 8 ) ? gt_rx_valid_wire[7] : 1'b0 ; assign gt_rx_polarity[0] = pipe_rx0_polarity; assign gt_rx_polarity[1] = pipe_rx1_polarity; assign gt_rx_polarity[2] = pipe_rx2_polarity; assign gt_rx_polarity[3] = pipe_rx3_polarity; assign gt_rx_polarity[4] = pipe_rx4_polarity; assign gt_rx_polarity[5] = pipe_rx5_polarity; assign gt_rx_polarity[6] = pipe_rx6_polarity; assign gt_rx_polarity[7] = pipe_rx7_polarity; assign gt_power_down[ 1: 0] = pipe_tx0_powerdown; assign gt_power_down[ 3: 2] = pipe_tx1_powerdown; assign gt_power_down[ 5: 4] = pipe_tx2_powerdown; assign gt_power_down[ 7: 6] = pipe_tx3_powerdown; assign gt_power_down[ 9: 8] = pipe_tx4_powerdown; assign gt_power_down[11:10] = pipe_tx5_powerdown; assign gt_power_down[13:12] = pipe_tx6_powerdown; assign gt_power_down[15:14] = pipe_tx7_powerdown; assign gt_tx_char_disp_mode = {pipe_tx7_compliance, pipe_tx6_compliance, pipe_tx5_compliance, pipe_tx4_compliance, pipe_tx3_compliance, pipe_tx2_compliance, pipe_tx1_compliance, pipe_tx0_compliance}; assign gt_tx_data_k = {pipe_tx7_char_is_k, pipe_tx6_char_is_k, pipe_tx5_char_is_k, pipe_tx4_char_is_k, pipe_tx3_char_is_k, pipe_tx2_char_is_k, pipe_tx1_char_is_k, pipe_tx0_char_is_k}; assign gt_tx_data = {pipe_tx7_data, pipe_tx6_data, pipe_tx5_data, pipe_tx4_data, pipe_tx3_data, pipe_tx2_data, pipe_tx1_data, pipe_tx0_data}; assign gt_tx_detect_rx_loopback = pipe_tx_rcvr_det; assign gt_tx_elec_idle = {pipe_tx7_elec_idle, pipe_tx6_elec_idle, pipe_tx5_elec_idle, pipe_tx4_elec_idle, pipe_tx3_elec_idle, pipe_tx2_elec_idle, pipe_tx1_elec_idle, pipe_tx0_elec_idle}; assign gt_pll_lock = &plllkdet[NO_OF_LANES-1:0] | ~phy_rdy_pre_cnt[4]; // Asserted after all workarounds have completed. always @(posedge pipe_clk or negedge clock_locked) begin if (!clock_locked) begin phy_rdy_n <= #TCQ 1'b1; end else begin if (~&plllkdet[NO_OF_LANES-1:0]) phy_rdy_n <= #TCQ 1'b1; else if (local_pcs_reset_done && RxResetDone && phy_rdy_n && SyncDone) phy_rdy_n <= #TCQ 1'b0; end end // Handle the warm reset case, where sys_rst_n is asseted when // phy_rdy_n is asserted. phy_rdy_n is to be de-asserted // before gt_pll_lock is de-asserted so that synnchronous // logic see reset de-asset before clock is lost. always @(posedge pipe_clk or negedge clock_locked) begin if (!clock_locked) begin phy_rdy_pre_cnt <= #TCQ 5'b11111; end else begin if (gt_pll_lock && phy_rdy_n) phy_rdy_pre_cnt <= #TCQ phy_rdy_pre_cnt + 1'b1; end end always @(posedge pipe_clk or negedge clock_locked) begin if (!clock_locked) begin cnt_local_pcs_reset <= #TCQ 4'hF; local_pcs_reset <= #TCQ 1'b0; local_pcs_reset_done <= #TCQ 1'b0; end else begin if ((local_pcs_reset == 1'b0) && (cnt_local_pcs_reset == 4'hF)) local_pcs_reset <= #TCQ 1'b1; else if ((local_pcs_reset == 1'b1) && (cnt_local_pcs_reset != 4'h0)) begin local_pcs_reset <= #TCQ 1'b1; cnt_local_pcs_reset <= #TCQ cnt_local_pcs_reset - 1'b1; end else if ((local_pcs_reset == 1'b1) && (cnt_local_pcs_reset == 4'h0)) begin local_pcs_reset <= #TCQ 1'b0; local_pcs_reset_done <= #TCQ 1'b1; end end end always @(posedge pipe_clk or negedge clock_locked) begin if (!clock_locked) pl_ltssm_state_q <= #TCQ 6'b0; else pl_ltssm_state_q <= #TCQ pl_ltssm_state; end //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/pcie_pipe_lane_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : pcie_pipe_lane_v6.v // Version : 2.4 //-- //-- Description: PIPE per lane module for Virtex6 PCIe Block //-- //-- //-- //-------------------------------------------------------------------------------- `timescale 1ns/1ns module pcie_pipe_lane_v6 # ( parameter PIPE_PIPELINE_STAGES = 0, // 0 - 0 stages, 1 - 1 stage, 2 - 2 stages parameter TCQ = 1 // clock to out delay model ) ( output wire [ 1:0] pipe_rx_char_is_k_o , output wire [15:0] pipe_rx_data_o , output wire pipe_rx_valid_o , output wire pipe_rx_chanisaligned_o , output wire [ 2:0] pipe_rx_status_o , output wire pipe_rx_phy_status_o , output wire pipe_rx_elec_idle_o , input wire pipe_rx_polarity_i , input wire pipe_tx_compliance_i , input wire [ 1:0] pipe_tx_char_is_k_i , input wire [15:0] pipe_tx_data_i , input wire pipe_tx_elec_idle_i , input wire [ 1:0] pipe_tx_powerdown_i , input wire [ 1:0] pipe_rx_char_is_k_i , input wire [15:0] pipe_rx_data_i , input wire pipe_rx_valid_i , input wire pipe_rx_chanisaligned_i , input wire [ 2:0] pipe_rx_status_i , input wire pipe_rx_phy_status_i , input wire pipe_rx_elec_idle_i , output wire pipe_rx_polarity_o , output wire pipe_tx_compliance_o , output wire [ 1:0] pipe_tx_char_is_k_o , output wire [15:0] pipe_tx_data_o , output wire pipe_tx_elec_idle_o , output wire [ 1:0] pipe_tx_powerdown_o , input wire pipe_clk , input wire rst_n ); //******************************************************************// // Reality check. // //******************************************************************// reg [ 1:0] pipe_rx_char_is_k_q ; reg [15:0] pipe_rx_data_q ; reg pipe_rx_valid_q ; reg pipe_rx_chanisaligned_q ; reg [ 2:0] pipe_rx_status_q ; reg pipe_rx_phy_status_q ; reg pipe_rx_elec_idle_q ; reg pipe_rx_polarity_q ; reg pipe_tx_compliance_q ; reg [ 1:0] pipe_tx_char_is_k_q ; reg [15:0] pipe_tx_data_q ; reg pipe_tx_elec_idle_q ; reg [ 1:0] pipe_tx_powerdown_q ; reg [ 1:0] pipe_rx_char_is_k_qq ; reg [15:0] pipe_rx_data_qq ; reg pipe_rx_valid_qq ; reg pipe_rx_chanisaligned_qq; reg [ 2:0] pipe_rx_status_qq ; reg pipe_rx_phy_status_qq ; reg pipe_rx_elec_idle_qq ; reg pipe_rx_polarity_qq ; reg pipe_tx_compliance_qq ; reg [ 1:0] pipe_tx_char_is_k_qq ; reg [15:0] pipe_tx_data_qq ; reg pipe_tx_elec_idle_qq ; reg [ 1:0] pipe_tx_powerdown_qq ; generate if (PIPE_PIPELINE_STAGES == 0) begin assign pipe_rx_char_is_k_o = pipe_rx_char_is_k_i; assign pipe_rx_data_o = pipe_rx_data_i; assign pipe_rx_valid_o = pipe_rx_valid_i; assign pipe_rx_chanisaligned_o = pipe_rx_chanisaligned_i; assign pipe_rx_status_o = pipe_rx_status_i; assign pipe_rx_phy_status_o = pipe_rx_phy_status_i; assign pipe_rx_elec_idle_o = pipe_rx_elec_idle_i; assign pipe_rx_polarity_o = pipe_rx_polarity_i; assign pipe_tx_compliance_o = pipe_tx_compliance_i; assign pipe_tx_char_is_k_o = pipe_tx_char_is_k_i; assign pipe_tx_data_o = pipe_tx_data_i; assign pipe_tx_elec_idle_o = pipe_tx_elec_idle_i; assign pipe_tx_powerdown_o = pipe_tx_powerdown_i; end else if (PIPE_PIPELINE_STAGES == 1) begin always @(posedge pipe_clk) begin if (rst_n) begin pipe_rx_char_is_k_q <= #TCQ 0; pipe_rx_data_q <= #TCQ 0; pipe_rx_valid_q <= #TCQ 0; pipe_rx_chanisaligned_q <= #TCQ 0; pipe_rx_status_q <= #TCQ 0; pipe_rx_phy_status_q <= #TCQ 0; pipe_rx_elec_idle_q <= #TCQ 0; pipe_rx_polarity_q <= #TCQ 0; pipe_tx_compliance_q <= #TCQ 0; pipe_tx_char_is_k_q <= #TCQ 0; pipe_tx_data_q <= #TCQ 0; pipe_tx_elec_idle_q <= #TCQ 1'b1; pipe_tx_powerdown_q <= #TCQ 2'b10; end else begin pipe_rx_char_is_k_q <= #TCQ pipe_rx_char_is_k_i; pipe_rx_data_q <= #TCQ pipe_rx_data_i; pipe_rx_valid_q <= #TCQ pipe_rx_valid_i; pipe_rx_chanisaligned_q <= #TCQ pipe_rx_chanisaligned_i; pipe_rx_status_q <= #TCQ pipe_rx_status_i; pipe_rx_phy_status_q <= #TCQ pipe_rx_phy_status_i; pipe_rx_elec_idle_q <= #TCQ pipe_rx_elec_idle_i; pipe_rx_polarity_q <= #TCQ pipe_rx_polarity_i; pipe_tx_compliance_q <= #TCQ pipe_tx_compliance_i; pipe_tx_char_is_k_q <= #TCQ pipe_tx_char_is_k_i; pipe_tx_data_q <= #TCQ pipe_tx_data_i; pipe_tx_elec_idle_q <= #TCQ pipe_tx_elec_idle_i; pipe_tx_powerdown_q <= #TCQ pipe_tx_powerdown_i; end end assign pipe_rx_char_is_k_o = pipe_rx_char_is_k_q; assign pipe_rx_data_o = pipe_rx_data_q; assign pipe_rx_valid_o = pipe_rx_valid_q; assign pipe_rx_chanisaligned_o = pipe_rx_chanisaligned_q; assign pipe_rx_status_o = pipe_rx_status_q; assign pipe_rx_phy_status_o = pipe_rx_phy_status_q; assign pipe_rx_elec_idle_o = pipe_rx_elec_idle_q; assign pipe_rx_polarity_o = pipe_rx_polarity_q; assign pipe_tx_compliance_o = pipe_tx_compliance_q; assign pipe_tx_char_is_k_o = pipe_tx_char_is_k_q; assign pipe_tx_data_o = pipe_tx_data_q; assign pipe_tx_elec_idle_o = pipe_tx_elec_idle_q; assign pipe_tx_powerdown_o = pipe_tx_powerdown_q; end else if (PIPE_PIPELINE_STAGES == 2) begin always @(posedge pipe_clk) begin if (rst_n) begin pipe_rx_char_is_k_q <= #TCQ 0; pipe_rx_data_q <= #TCQ 0; pipe_rx_valid_q <= #TCQ 0; pipe_rx_chanisaligned_q <= #TCQ 0; pipe_rx_status_q <= #TCQ 0; pipe_rx_phy_status_q <= #TCQ 0; pipe_rx_elec_idle_q <= #TCQ 0; pipe_rx_polarity_q <= #TCQ 0; pipe_tx_compliance_q <= #TCQ 0; pipe_tx_char_is_k_q <= #TCQ 0; pipe_tx_data_q <= #TCQ 0; pipe_tx_elec_idle_q <= #TCQ 1'b1; pipe_tx_powerdown_q <= #TCQ 2'b10; pipe_rx_char_is_k_qq <= #TCQ 0; pipe_rx_data_qq <= #TCQ 0; pipe_rx_valid_qq <= #TCQ 0; pipe_rx_chanisaligned_qq <= #TCQ 0; pipe_rx_status_qq <= #TCQ 0; pipe_rx_phy_status_qq <= #TCQ 0; pipe_rx_elec_idle_qq <= #TCQ 0; pipe_rx_polarity_qq <= #TCQ 0; pipe_tx_compliance_qq <= #TCQ 0; pipe_tx_char_is_k_qq <= #TCQ 0; pipe_tx_data_qq <= #TCQ 0; pipe_tx_elec_idle_qq <= #TCQ 1'b1; pipe_tx_powerdown_qq <= #TCQ 2'b10; end else begin pipe_rx_char_is_k_q <= #TCQ pipe_rx_char_is_k_i; pipe_rx_data_q <= #TCQ pipe_rx_data_i; pipe_rx_valid_q <= #TCQ pipe_rx_valid_i; pipe_rx_chanisaligned_q <= #TCQ pipe_rx_chanisaligned_i; pipe_rx_status_q <= #TCQ pipe_rx_status_i; pipe_rx_phy_status_q <= #TCQ pipe_rx_phy_status_i; pipe_rx_elec_idle_q <= #TCQ pipe_rx_elec_idle_i; pipe_rx_polarity_q <= #TCQ pipe_rx_polarity_i; pipe_tx_compliance_q <= #TCQ pipe_tx_compliance_i; pipe_tx_char_is_k_q <= #TCQ pipe_tx_char_is_k_i; pipe_tx_data_q <= #TCQ pipe_tx_data_i; pipe_tx_elec_idle_q <= #TCQ pipe_tx_elec_idle_i; pipe_tx_powerdown_q <= #TCQ pipe_tx_powerdown_i; pipe_rx_char_is_k_qq <= #TCQ pipe_rx_char_is_k_q; pipe_rx_data_qq <= #TCQ pipe_rx_data_q; pipe_rx_valid_qq <= #TCQ pipe_rx_valid_q; pipe_rx_chanisaligned_qq <= #TCQ pipe_rx_chanisaligned_q; pipe_rx_status_qq <= #TCQ pipe_rx_status_q; pipe_rx_phy_status_qq <= #TCQ pipe_rx_phy_status_q; pipe_rx_elec_idle_qq <= #TCQ pipe_rx_elec_idle_q; pipe_rx_polarity_qq <= #TCQ pipe_rx_polarity_q; pipe_tx_compliance_qq <= #TCQ pipe_tx_compliance_q; pipe_tx_char_is_k_qq <= #TCQ pipe_tx_char_is_k_q; pipe_tx_data_qq <= #TCQ pipe_tx_data_q; pipe_tx_elec_idle_qq <= #TCQ pipe_tx_elec_idle_q; pipe_tx_powerdown_qq <= #TCQ pipe_tx_powerdown_q; end end assign pipe_rx_char_is_k_o = pipe_rx_char_is_k_qq; assign pipe_rx_data_o = pipe_rx_data_qq; assign pipe_rx_valid_o = pipe_rx_valid_qq; assign pipe_rx_chanisaligned_o = pipe_rx_chanisaligned_qq; assign pipe_rx_status_o = pipe_rx_status_qq; assign pipe_rx_phy_status_o = pipe_rx_phy_status_qq; assign pipe_rx_elec_idle_o = pipe_rx_elec_idle_qq; assign pipe_rx_polarity_o = pipe_rx_polarity_qq; assign pipe_tx_compliance_o = pipe_tx_compliance_qq; assign pipe_tx_char_is_k_o = pipe_tx_char_is_k_qq; assign pipe_tx_data_o = pipe_tx_data_qq; assign pipe_tx_elec_idle_o = pipe_tx_elec_idle_qq; assign pipe_tx_powerdown_o = pipe_tx_powerdown_qq; end endgenerate endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/pcie_pipe_misc_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : pcie_pipe_misc_v6.v // Version : 2.4 //-- //-- Description: Misc PIPE module for Virtex6 PCIe Block //-- //-- //-- //-------------------------------------------------------------------------------- `timescale 1ns/1ns module pcie_pipe_misc_v6 # ( parameter PIPE_PIPELINE_STAGES = 0 // 0 - 0 stages, 1 - 1 stage, 2 - 2 stages ) ( input wire pipe_tx_rcvr_det_i , input wire pipe_tx_reset_i , input wire pipe_tx_rate_i , input wire pipe_tx_deemph_i , input wire [2:0] pipe_tx_margin_i , input wire pipe_tx_swing_i , output wire pipe_tx_rcvr_det_o , output wire pipe_tx_reset_o , output wire pipe_tx_rate_o , output wire pipe_tx_deemph_o , output wire [2:0] pipe_tx_margin_o , output wire pipe_tx_swing_o , input wire pipe_clk , input wire rst_n ); //******************************************************************// // Reality check. // //******************************************************************// localparam TCQ = 1; // clock to out delay model reg pipe_tx_rcvr_det_q ; reg pipe_tx_reset_q ; reg pipe_tx_rate_q ; reg pipe_tx_deemph_q ; reg [2:0] pipe_tx_margin_q ; reg pipe_tx_swing_q ; reg pipe_tx_rcvr_det_qq ; reg pipe_tx_reset_qq ; reg pipe_tx_rate_qq ; reg pipe_tx_deemph_qq ; reg [2:0] pipe_tx_margin_qq ; reg pipe_tx_swing_qq ; generate if (PIPE_PIPELINE_STAGES == 0) begin assign pipe_tx_rcvr_det_o = pipe_tx_rcvr_det_i; assign pipe_tx_reset_o = pipe_tx_reset_i; assign pipe_tx_rate_o = pipe_tx_rate_i; assign pipe_tx_deemph_o = pipe_tx_deemph_i; assign pipe_tx_margin_o = pipe_tx_margin_i; assign pipe_tx_swing_o = pipe_tx_swing_i; end else if (PIPE_PIPELINE_STAGES == 1) begin always @(posedge pipe_clk) begin if (rst_n) begin pipe_tx_rcvr_det_q <= #TCQ 0; pipe_tx_reset_q <= #TCQ 1'b1; pipe_tx_rate_q <= #TCQ 0; pipe_tx_deemph_q <= #TCQ 1'b1; pipe_tx_margin_q <= #TCQ 0; pipe_tx_swing_q <= #TCQ 0; end else begin pipe_tx_rcvr_det_q <= #TCQ pipe_tx_rcvr_det_i; pipe_tx_reset_q <= #TCQ pipe_tx_reset_i; pipe_tx_rate_q <= #TCQ pipe_tx_rate_i; pipe_tx_deemph_q <= #TCQ pipe_tx_deemph_i; pipe_tx_margin_q <= #TCQ pipe_tx_margin_i; pipe_tx_swing_q <= #TCQ pipe_tx_swing_i; end end assign pipe_tx_rcvr_det_o = pipe_tx_rcvr_det_q; assign pipe_tx_reset_o = pipe_tx_reset_q; assign pipe_tx_rate_o = pipe_tx_rate_q; assign pipe_tx_deemph_o = pipe_tx_deemph_q; assign pipe_tx_margin_o = pipe_tx_margin_q; assign pipe_tx_swing_o = pipe_tx_swing_q; end else if (PIPE_PIPELINE_STAGES == 2) begin always @(posedge pipe_clk) begin if (rst_n) begin pipe_tx_rcvr_det_q <= #TCQ 0; pipe_tx_reset_q <= #TCQ 1'b1; pipe_tx_rate_q <= #TCQ 0; pipe_tx_deemph_q <= #TCQ 1'b1; pipe_tx_margin_q <= #TCQ 0; pipe_tx_swing_q <= #TCQ 0; pipe_tx_rcvr_det_qq <= #TCQ 0; pipe_tx_reset_qq <= #TCQ 1'b1; pipe_tx_rate_qq <= #TCQ 0; pipe_tx_deemph_qq <= #TCQ 1'b1; pipe_tx_margin_qq <= #TCQ 0; pipe_tx_swing_qq <= #TCQ 0; end else begin pipe_tx_rcvr_det_q <= #TCQ pipe_tx_rcvr_det_i; pipe_tx_reset_q <= #TCQ pipe_tx_reset_i; pipe_tx_rate_q <= #TCQ pipe_tx_rate_i; pipe_tx_deemph_q <= #TCQ pipe_tx_deemph_i; pipe_tx_margin_q <= #TCQ pipe_tx_margin_i; pipe_tx_swing_q <= #TCQ pipe_tx_swing_i; pipe_tx_rcvr_det_qq <= #TCQ pipe_tx_rcvr_det_q; pipe_tx_reset_qq <= #TCQ pipe_tx_reset_q; pipe_tx_rate_qq <= #TCQ pipe_tx_rate_q; pipe_tx_deemph_qq <= #TCQ pipe_tx_deemph_q; pipe_tx_margin_qq <= #TCQ pipe_tx_margin_q; pipe_tx_swing_qq <= #TCQ pipe_tx_swing_q; end end assign pipe_tx_rcvr_det_o = pipe_tx_rcvr_det_qq; assign pipe_tx_reset_o = pipe_tx_reset_qq; assign pipe_tx_rate_o = pipe_tx_rate_qq; assign pipe_tx_deemph_o = pipe_tx_deemph_qq; assign pipe_tx_margin_o = pipe_tx_margin_qq; assign pipe_tx_swing_o = pipe_tx_swing_qq; end endgenerate endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/pcie_pipe_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : pcie_pipe_v6.v // Version : 2.4 //-- Description: PIPE module for Virtex6 PCIe Block //-- //-- //-- //-------------------------------------------------------------------------------- `timescale 1ns/1ns module pcie_pipe_v6 # ( parameter NO_OF_LANES = 8, parameter LINK_CAP_MAX_LINK_SPEED = 4'h1, parameter PIPE_PIPELINE_STAGES = 0 // 0 - 0 stages, 1 - 1 stage, 2 - 2 stages ) ( // Pipe Per-Link Signals input wire pipe_tx_rcvr_det_i , input wire pipe_tx_reset_i , input wire pipe_tx_rate_i , input wire pipe_tx_deemph_i , input wire [2:0] pipe_tx_margin_i , input wire pipe_tx_swing_i , output wire pipe_tx_rcvr_det_o , output wire pipe_tx_reset_o , output wire pipe_tx_rate_o , output wire pipe_tx_deemph_o , output wire [2:0] pipe_tx_margin_o , output wire pipe_tx_swing_o , // Pipe Per-Lane Signals - Lane 0 output wire [ 1:0] pipe_rx0_char_is_k_o , output wire [15:0] pipe_rx0_data_o , output wire pipe_rx0_valid_o , output wire pipe_rx0_chanisaligned_o , output wire [ 2:0] pipe_rx0_status_o , output wire pipe_rx0_phy_status_o , output wire pipe_rx0_elec_idle_o , input wire pipe_rx0_polarity_i , input wire pipe_tx0_compliance_i , input wire [ 1:0] pipe_tx0_char_is_k_i , input wire [15:0] pipe_tx0_data_i , input wire pipe_tx0_elec_idle_i , input wire [ 1:0] pipe_tx0_powerdown_i , input wire [ 1:0] pipe_rx0_char_is_k_i , input wire [15:0] pipe_rx0_data_i , input wire pipe_rx0_valid_i , input wire pipe_rx0_chanisaligned_i , input wire [ 2:0] pipe_rx0_status_i , input wire pipe_rx0_phy_status_i , input wire pipe_rx0_elec_idle_i , output wire pipe_rx0_polarity_o , output wire pipe_tx0_compliance_o , output wire [ 1:0] pipe_tx0_char_is_k_o , output wire [15:0] pipe_tx0_data_o , output wire pipe_tx0_elec_idle_o , output wire [ 1:0] pipe_tx0_powerdown_o , // Pipe Per-Lane Signals - Lane 1 output wire [ 1:0] pipe_rx1_char_is_k_o , output wire [15:0] pipe_rx1_data_o , output wire pipe_rx1_valid_o , output wire pipe_rx1_chanisaligned_o , output wire [ 2:0] pipe_rx1_status_o , output wire pipe_rx1_phy_status_o , output wire pipe_rx1_elec_idle_o , input wire pipe_rx1_polarity_i , input wire pipe_tx1_compliance_i , input wire [ 1:0] pipe_tx1_char_is_k_i , input wire [15:0] pipe_tx1_data_i , input wire pipe_tx1_elec_idle_i , input wire [ 1:0] pipe_tx1_powerdown_i , input wire [ 1:0] pipe_rx1_char_is_k_i , input wire [15:0] pipe_rx1_data_i , input wire pipe_rx1_valid_i , input wire pipe_rx1_chanisaligned_i , input wire [ 2:0] pipe_rx1_status_i , input wire pipe_rx1_phy_status_i , input wire pipe_rx1_elec_idle_i , output wire pipe_rx1_polarity_o , output wire pipe_tx1_compliance_o , output wire [ 1:0] pipe_tx1_char_is_k_o , output wire [15:0] pipe_tx1_data_o , output wire pipe_tx1_elec_idle_o , output wire [ 1:0] pipe_tx1_powerdown_o , // Pipe Per-Lane Signals - Lane 2 output wire [ 1:0] pipe_rx2_char_is_k_o , output wire [15:0] pipe_rx2_data_o , output wire pipe_rx2_valid_o , output wire pipe_rx2_chanisaligned_o , output wire [ 2:0] pipe_rx2_status_o , output wire pipe_rx2_phy_status_o , output wire pipe_rx2_elec_idle_o , input wire pipe_rx2_polarity_i , input wire pipe_tx2_compliance_i , input wire [ 1:0] pipe_tx2_char_is_k_i , input wire [15:0] pipe_tx2_data_i , input wire pipe_tx2_elec_idle_i , input wire [ 1:0] pipe_tx2_powerdown_i , input wire [ 1:0] pipe_rx2_char_is_k_i , input wire [15:0] pipe_rx2_data_i , input wire pipe_rx2_valid_i , input wire pipe_rx2_chanisaligned_i , input wire [ 2:0] pipe_rx2_status_i , input wire pipe_rx2_phy_status_i , input wire pipe_rx2_elec_idle_i , output wire pipe_rx2_polarity_o , output wire pipe_tx2_compliance_o , output wire [ 1:0] pipe_tx2_char_is_k_o , output wire [15:0] pipe_tx2_data_o , output wire pipe_tx2_elec_idle_o , output wire [ 1:0] pipe_tx2_powerdown_o , // Pipe Per-Lane Signals - Lane 3 output wire [ 1:0] pipe_rx3_char_is_k_o , output wire [15:0] pipe_rx3_data_o , output wire pipe_rx3_valid_o , output wire pipe_rx3_chanisaligned_o , output wire [ 2:0] pipe_rx3_status_o , output wire pipe_rx3_phy_status_o , output wire pipe_rx3_elec_idle_o , input wire pipe_rx3_polarity_i , input wire pipe_tx3_compliance_i , input wire [ 1:0] pipe_tx3_char_is_k_i , input wire [15:0] pipe_tx3_data_i , input wire pipe_tx3_elec_idle_i , input wire [ 1:0] pipe_tx3_powerdown_i , input wire [ 1:0] pipe_rx3_char_is_k_i , input wire [15:0] pipe_rx3_data_i , input wire pipe_rx3_valid_i , input wire pipe_rx3_chanisaligned_i , input wire [ 2:0] pipe_rx3_status_i , input wire pipe_rx3_phy_status_i , input wire pipe_rx3_elec_idle_i , output wire pipe_rx3_polarity_o , output wire pipe_tx3_compliance_o , output wire [ 1:0] pipe_tx3_char_is_k_o , output wire [15:0] pipe_tx3_data_o , output wire pipe_tx3_elec_idle_o , output wire [ 1:0] pipe_tx3_powerdown_o , // Pipe Per-Lane Signals - Lane 4 output wire [ 1:0] pipe_rx4_char_is_k_o , output wire [15:0] pipe_rx4_data_o , output wire pipe_rx4_valid_o , output wire pipe_rx4_chanisaligned_o , output wire [ 2:0] pipe_rx4_status_o , output wire pipe_rx4_phy_status_o , output wire pipe_rx4_elec_idle_o , input wire pipe_rx4_polarity_i , input wire pipe_tx4_compliance_i , input wire [ 1:0] pipe_tx4_char_is_k_i , input wire [15:0] pipe_tx4_data_i , input wire pipe_tx4_elec_idle_i , input wire [ 1:0] pipe_tx4_powerdown_i , input wire [ 1:0] pipe_rx4_char_is_k_i , input wire [15:0] pipe_rx4_data_i , input wire pipe_rx4_valid_i , input wire pipe_rx4_chanisaligned_i , input wire [ 2:0] pipe_rx4_status_i , input wire pipe_rx4_phy_status_i , input wire pipe_rx4_elec_idle_i , output wire pipe_rx4_polarity_o , output wire pipe_tx4_compliance_o , output wire [ 1:0] pipe_tx4_char_is_k_o , output wire [15:0] pipe_tx4_data_o , output wire pipe_tx4_elec_idle_o , output wire [ 1:0] pipe_tx4_powerdown_o , // Pipe Per-Lane Signals - Lane 5 output wire [ 1:0] pipe_rx5_char_is_k_o , output wire [15:0] pipe_rx5_data_o , output wire pipe_rx5_valid_o , output wire pipe_rx5_chanisaligned_o , output wire [ 2:0] pipe_rx5_status_o , output wire pipe_rx5_phy_status_o , output wire pipe_rx5_elec_idle_o , input wire pipe_rx5_polarity_i , input wire pipe_tx5_compliance_i , input wire [ 1:0] pipe_tx5_char_is_k_i , input wire [15:0] pipe_tx5_data_i , input wire pipe_tx5_elec_idle_i , input wire [ 1:0] pipe_tx5_powerdown_i , input wire [ 1:0] pipe_rx5_char_is_k_i , input wire [15:0] pipe_rx5_data_i , input wire pipe_rx5_valid_i , input wire pipe_rx5_chanisaligned_i , input wire [ 2:0] pipe_rx5_status_i , input wire pipe_rx5_phy_status_i , input wire pipe_rx5_elec_idle_i , output wire pipe_rx5_polarity_o , output wire pipe_tx5_compliance_o , output wire [ 1:0] pipe_tx5_char_is_k_o , output wire [15:0] pipe_tx5_data_o , output wire pipe_tx5_elec_idle_o , output wire [ 1:0] pipe_tx5_powerdown_o , // Pipe Per-Lane Signals - Lane 6 output wire [ 1:0] pipe_rx6_char_is_k_o , output wire [15:0] pipe_rx6_data_o , output wire pipe_rx6_valid_o , output wire pipe_rx6_chanisaligned_o , output wire [ 2:0] pipe_rx6_status_o , output wire pipe_rx6_phy_status_o , output wire pipe_rx6_elec_idle_o , input wire pipe_rx6_polarity_i , input wire pipe_tx6_compliance_i , input wire [ 1:0] pipe_tx6_char_is_k_i , input wire [15:0] pipe_tx6_data_i , input wire pipe_tx6_elec_idle_i , input wire [ 1:0] pipe_tx6_powerdown_i , input wire [ 1:0] pipe_rx6_char_is_k_i , input wire [15:0] pipe_rx6_data_i , input wire pipe_rx6_valid_i , input wire pipe_rx6_chanisaligned_i , input wire [ 2:0] pipe_rx6_status_i , input wire pipe_rx6_phy_status_i , input wire pipe_rx6_elec_idle_i , output wire pipe_rx6_polarity_o , output wire pipe_tx6_compliance_o , output wire [ 1:0] pipe_tx6_char_is_k_o , output wire [15:0] pipe_tx6_data_o , output wire pipe_tx6_elec_idle_o , output wire [ 1:0] pipe_tx6_powerdown_o , // Pipe Per-Lane Signals - Lane 7 output wire [ 1:0] pipe_rx7_char_is_k_o , output wire [15:0] pipe_rx7_data_o , output wire pipe_rx7_valid_o , output wire pipe_rx7_chanisaligned_o , output wire [ 2:0] pipe_rx7_status_o , output wire pipe_rx7_phy_status_o , output wire pipe_rx7_elec_idle_o , input wire pipe_rx7_polarity_i , input wire pipe_tx7_compliance_i , input wire [ 1:0] pipe_tx7_char_is_k_i , input wire [15:0] pipe_tx7_data_i , input wire pipe_tx7_elec_idle_i , input wire [ 1:0] pipe_tx7_powerdown_i , input wire [ 1:0] pipe_rx7_char_is_k_i , input wire [15:0] pipe_rx7_data_i , input wire pipe_rx7_valid_i , input wire pipe_rx7_chanisaligned_i , input wire [ 2:0] pipe_rx7_status_i , input wire pipe_rx7_phy_status_i , input wire pipe_rx7_elec_idle_i , output wire pipe_rx7_polarity_o , output wire pipe_tx7_compliance_o , output wire [ 1:0] pipe_tx7_char_is_k_o , output wire [15:0] pipe_tx7_data_o , output wire pipe_tx7_elec_idle_o , output wire [ 1:0] pipe_tx7_powerdown_o , // Non PIPE signals input wire [ 5:0] pl_ltssm_state , input wire pipe_clk , input wire rst_n ); //******************************************************************// // Reality check. // //******************************************************************// localparam Tc2o = 1; // clock to out delay model wire [ 1:0] pipe_rx0_char_is_k_q ; wire [15:0] pipe_rx0_data_q ; wire [ 1:0] pipe_rx1_char_is_k_q ; wire [15:0] pipe_rx1_data_q ; wire [ 1:0] pipe_rx2_char_is_k_q ; wire [15:0] pipe_rx2_data_q ; wire [ 1:0] pipe_rx3_char_is_k_q ; wire [15:0] pipe_rx3_data_q ; wire [ 1:0] pipe_rx4_char_is_k_q ; wire [15:0] pipe_rx4_data_q ; wire [ 1:0] pipe_rx5_char_is_k_q ; wire [15:0] pipe_rx5_data_q ; wire [ 1:0] pipe_rx6_char_is_k_q ; wire [15:0] pipe_rx6_data_q ; wire [ 1:0] pipe_rx7_char_is_k_q ; wire [15:0] pipe_rx7_data_q ; //synthesis translate_off // initial begin // $display("[%t] %m NO_OF_LANES %0d PIPE_PIPELINE_STAGES %0d", $time, NO_OF_LANES, PIPE_PIPELINE_STAGES); // end //synthesis translate_on generate pcie_pipe_misc_v6 # ( .PIPE_PIPELINE_STAGES(PIPE_PIPELINE_STAGES) ) pipe_misc_i ( .pipe_tx_rcvr_det_i(pipe_tx_rcvr_det_i), .pipe_tx_reset_i(pipe_tx_reset_i), .pipe_tx_rate_i(pipe_tx_rate_i), .pipe_tx_deemph_i(pipe_tx_deemph_i), .pipe_tx_margin_i(pipe_tx_margin_i), .pipe_tx_swing_i(pipe_tx_swing_i), .pipe_tx_rcvr_det_o(pipe_tx_rcvr_det_o), .pipe_tx_reset_o(pipe_tx_reset_o), .pipe_tx_rate_o(pipe_tx_rate_o), .pipe_tx_deemph_o(pipe_tx_deemph_o), .pipe_tx_margin_o(pipe_tx_margin_o), .pipe_tx_swing_o(pipe_tx_swing_o) , .pipe_clk(pipe_clk), .rst_n(rst_n) ); pcie_pipe_lane_v6 # ( .PIPE_PIPELINE_STAGES(PIPE_PIPELINE_STAGES) ) pipe_lane_0_i ( .pipe_rx_char_is_k_o(pipe_rx0_char_is_k_q), .pipe_rx_data_o(pipe_rx0_data_q), .pipe_rx_valid_o(pipe_rx0_valid_o), .pipe_rx_chanisaligned_o(pipe_rx0_chanisaligned_o), .pipe_rx_status_o(pipe_rx0_status_o), .pipe_rx_phy_status_o(pipe_rx0_phy_status_o), .pipe_rx_elec_idle_o(pipe_rx0_elec_idle_o), .pipe_rx_polarity_i(pipe_rx0_polarity_i), .pipe_tx_compliance_i(pipe_tx0_compliance_i), .pipe_tx_char_is_k_i(pipe_tx0_char_is_k_i), .pipe_tx_data_i(pipe_tx0_data_i), .pipe_tx_elec_idle_i(pipe_tx0_elec_idle_i), .pipe_tx_powerdown_i(pipe_tx0_powerdown_i), .pipe_rx_char_is_k_i(pipe_rx0_char_is_k_i), .pipe_rx_data_i(pipe_rx0_data_i), .pipe_rx_valid_i(pipe_rx0_valid_i), .pipe_rx_chanisaligned_i(pipe_rx0_chanisaligned_i), .pipe_rx_status_i(pipe_rx0_status_i), .pipe_rx_phy_status_i(pipe_rx0_phy_status_i), .pipe_rx_elec_idle_i(pipe_rx0_elec_idle_i), .pipe_rx_polarity_o(pipe_rx0_polarity_o), .pipe_tx_compliance_o(pipe_tx0_compliance_o), .pipe_tx_char_is_k_o(pipe_tx0_char_is_k_o), .pipe_tx_data_o(pipe_tx0_data_o), .pipe_tx_elec_idle_o(pipe_tx0_elec_idle_o), .pipe_tx_powerdown_o(pipe_tx0_powerdown_o), .pipe_clk(pipe_clk), .rst_n(rst_n) ); if (NO_OF_LANES >= 2) begin pcie_pipe_lane_v6 # ( .PIPE_PIPELINE_STAGES(PIPE_PIPELINE_STAGES) ) pipe_lane_1_i ( .pipe_rx_char_is_k_o(pipe_rx1_char_is_k_q), .pipe_rx_data_o(pipe_rx1_data_q), .pipe_rx_valid_o(pipe_rx1_valid_o), .pipe_rx_chanisaligned_o(pipe_rx1_chanisaligned_o), .pipe_rx_status_o(pipe_rx1_status_o), .pipe_rx_phy_status_o(pipe_rx1_phy_status_o), .pipe_rx_elec_idle_o(pipe_rx1_elec_idle_o), .pipe_rx_polarity_i(pipe_rx1_polarity_i), .pipe_tx_compliance_i(pipe_tx1_compliance_i), .pipe_tx_char_is_k_i(pipe_tx1_char_is_k_i), .pipe_tx_data_i(pipe_tx1_data_i), .pipe_tx_elec_idle_i(pipe_tx1_elec_idle_i), .pipe_tx_powerdown_i(pipe_tx1_powerdown_i), .pipe_rx_char_is_k_i(pipe_rx1_char_is_k_i), .pipe_rx_data_i(pipe_rx1_data_i), .pipe_rx_valid_i(pipe_rx1_valid_i), .pipe_rx_chanisaligned_i(pipe_rx1_chanisaligned_i), .pipe_rx_status_i(pipe_rx1_status_i), .pipe_rx_phy_status_i(pipe_rx1_phy_status_i), .pipe_rx_elec_idle_i(pipe_rx1_elec_idle_i), .pipe_rx_polarity_o(pipe_rx1_polarity_o), .pipe_tx_compliance_o(pipe_tx1_compliance_o), .pipe_tx_char_is_k_o(pipe_tx1_char_is_k_o), .pipe_tx_data_o(pipe_tx1_data_o), .pipe_tx_elec_idle_o(pipe_tx1_elec_idle_o), .pipe_tx_powerdown_o(pipe_tx1_powerdown_o), .pipe_clk(pipe_clk), .rst_n(rst_n) ); end else begin //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< assign pipe_rx1_char_is_k_o = 2'b00; assign pipe_rx1_data_o = 16'h0000; assign pipe_rx1_valid_o = 1'b0; assign pipe_rx1_chanisaligned_o = 1'b0; assign pipe_rx1_status_o = 3'b000; assign pipe_rx1_phy_status_o = 1'b0; assign pipe_rx1_elec_idle_o = 1'b1; assign pipe_rx1_polarity_o = 1'b0; assign pipe_tx1_compliance_o = 1'b0; assign pipe_tx1_char_is_k_o = 2'b00; assign pipe_tx1_data_o = 16'h0000; assign pipe_tx1_elec_idle_o = 1'b1; assign pipe_tx1_powerdown_o = 2'b00; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end if (NO_OF_LANES >= 4) begin pcie_pipe_lane_v6 # ( .PIPE_PIPELINE_STAGES(PIPE_PIPELINE_STAGES) ) pipe_lane_2_i ( .pipe_rx_char_is_k_o(pipe_rx2_char_is_k_q), .pipe_rx_data_o(pipe_rx2_data_q), .pipe_rx_valid_o(pipe_rx2_valid_o), .pipe_rx_chanisaligned_o(pipe_rx2_chanisaligned_o), .pipe_rx_status_o(pipe_rx2_status_o), .pipe_rx_phy_status_o(pipe_rx2_phy_status_o), .pipe_rx_elec_idle_o(pipe_rx2_elec_idle_o), .pipe_rx_polarity_i(pipe_rx2_polarity_i), .pipe_tx_compliance_i(pipe_tx2_compliance_i), .pipe_tx_char_is_k_i(pipe_tx2_char_is_k_i), .pipe_tx_data_i(pipe_tx2_data_i), .pipe_tx_elec_idle_i(pipe_tx2_elec_idle_i), .pipe_tx_powerdown_i(pipe_tx2_powerdown_i), .pipe_rx_char_is_k_i(pipe_rx2_char_is_k_i), .pipe_rx_data_i(pipe_rx2_data_i), .pipe_rx_valid_i(pipe_rx2_valid_i), .pipe_rx_chanisaligned_i(pipe_rx2_chanisaligned_i), .pipe_rx_status_i(pipe_rx2_status_i), .pipe_rx_phy_status_i(pipe_rx2_phy_status_i), .pipe_rx_elec_idle_i(pipe_rx2_elec_idle_i), .pipe_rx_polarity_o(pipe_rx2_polarity_o), .pipe_tx_compliance_o(pipe_tx2_compliance_o), .pipe_tx_char_is_k_o(pipe_tx2_char_is_k_o), .pipe_tx_data_o(pipe_tx2_data_o), .pipe_tx_elec_idle_o(pipe_tx2_elec_idle_o), .pipe_tx_powerdown_o(pipe_tx2_powerdown_o), .pipe_clk(pipe_clk), .rst_n(rst_n) ); pcie_pipe_lane_v6 # ( .PIPE_PIPELINE_STAGES(PIPE_PIPELINE_STAGES) ) pipe_lane_3_i ( .pipe_rx_char_is_k_o(pipe_rx3_char_is_k_q), .pipe_rx_data_o(pipe_rx3_data_q), .pipe_rx_valid_o(pipe_rx3_valid_o), .pipe_rx_chanisaligned_o(pipe_rx3_chanisaligned_o), .pipe_rx_status_o(pipe_rx3_status_o), .pipe_rx_phy_status_o(pipe_rx3_phy_status_o), .pipe_rx_elec_idle_o(pipe_rx3_elec_idle_o), .pipe_rx_polarity_i(pipe_rx3_polarity_i), .pipe_tx_compliance_i(pipe_tx3_compliance_i), .pipe_tx_char_is_k_i(pipe_tx3_char_is_k_i), .pipe_tx_data_i(pipe_tx3_data_i), .pipe_tx_elec_idle_i(pipe_tx3_elec_idle_i), .pipe_tx_powerdown_i(pipe_tx3_powerdown_i), .pipe_rx_char_is_k_i(pipe_rx3_char_is_k_i), .pipe_rx_data_i(pipe_rx3_data_i), .pipe_rx_valid_i(pipe_rx3_valid_i), .pipe_rx_chanisaligned_i(pipe_rx3_chanisaligned_i), .pipe_rx_status_i(pipe_rx3_status_i), .pipe_rx_phy_status_i(pipe_rx3_phy_status_i), .pipe_rx_elec_idle_i(pipe_rx3_elec_idle_i), .pipe_rx_polarity_o(pipe_rx3_polarity_o), .pipe_tx_compliance_o(pipe_tx3_compliance_o), .pipe_tx_char_is_k_o(pipe_tx3_char_is_k_o), .pipe_tx_data_o(pipe_tx3_data_o), .pipe_tx_elec_idle_o(pipe_tx3_elec_idle_o), .pipe_tx_powerdown_o(pipe_tx3_powerdown_o), .pipe_clk(pipe_clk), .rst_n(rst_n) ); end else begin //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< assign pipe_rx2_char_is_k_o = 2'b00; assign pipe_rx2_data_o = 16'h0000; assign pipe_rx2_valid_o = 1'b0; assign pipe_rx2_chanisaligned_o = 1'b0; assign pipe_rx2_status_o = 3'b000; assign pipe_rx2_phy_status_o = 1'b0; assign pipe_rx2_elec_idle_o = 1'b1; assign pipe_rx2_polarity_o = 1'b0; assign pipe_tx2_compliance_o = 1'b0; assign pipe_tx2_char_is_k_o = 2'b00; assign pipe_tx2_data_o = 16'h0000; assign pipe_tx2_elec_idle_o = 1'b1; assign pipe_tx2_powerdown_o = 2'b00; assign pipe_rx3_char_is_k_o = 2'b00; assign pipe_rx3_data_o = 16'h0000; assign pipe_rx3_valid_o = 1'b0; assign pipe_rx3_chanisaligned_o = 1'b0; assign pipe_rx3_status_o = 3'b000; assign pipe_rx3_phy_status_o = 1'b0; assign pipe_rx3_elec_idle_o = 1'b1; assign pipe_rx3_polarity_o = 1'b0; assign pipe_tx3_compliance_o = 1'b0; assign pipe_tx3_char_is_k_o = 2'b00; assign pipe_tx3_data_o = 16'h0000; assign pipe_tx3_elec_idle_o = 1'b1; assign pipe_tx3_powerdown_o = 2'b00; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end if (NO_OF_LANES >= 8) begin pcie_pipe_lane_v6 # ( .PIPE_PIPELINE_STAGES(PIPE_PIPELINE_STAGES) ) pipe_lane_4_i ( .pipe_rx_char_is_k_o(pipe_rx4_char_is_k_q), .pipe_rx_data_o(pipe_rx4_data_q), .pipe_rx_valid_o(pipe_rx4_valid_o), .pipe_rx_chanisaligned_o(pipe_rx4_chanisaligned_o), .pipe_rx_status_o(pipe_rx4_status_o), .pipe_rx_phy_status_o(pipe_rx4_phy_status_o), .pipe_rx_elec_idle_o(pipe_rx4_elec_idle_o), .pipe_rx_polarity_i(pipe_rx4_polarity_i), .pipe_tx_compliance_i(pipe_tx4_compliance_i), .pipe_tx_char_is_k_i(pipe_tx4_char_is_k_i), .pipe_tx_data_i(pipe_tx4_data_i), .pipe_tx_elec_idle_i(pipe_tx4_elec_idle_i), .pipe_tx_powerdown_i(pipe_tx4_powerdown_i), .pipe_rx_char_is_k_i(pipe_rx4_char_is_k_i), .pipe_rx_data_i(pipe_rx4_data_i), .pipe_rx_valid_i(pipe_rx4_valid_i), .pipe_rx_chanisaligned_i(pipe_rx4_chanisaligned_i), .pipe_rx_status_i(pipe_rx4_status_i), .pipe_rx_phy_status_i(pipe_rx4_phy_status_i), .pipe_rx_elec_idle_i(pipe_rx4_elec_idle_i), .pipe_rx_polarity_o(pipe_rx4_polarity_o), .pipe_tx_compliance_o(pipe_tx4_compliance_o), .pipe_tx_char_is_k_o(pipe_tx4_char_is_k_o), .pipe_tx_data_o(pipe_tx4_data_o), .pipe_tx_elec_idle_o(pipe_tx4_elec_idle_o), .pipe_tx_powerdown_o(pipe_tx4_powerdown_o), .pipe_clk(pipe_clk), .rst_n(rst_n) ); pcie_pipe_lane_v6 # ( .PIPE_PIPELINE_STAGES(PIPE_PIPELINE_STAGES) ) pipe_lane_5_i ( .pipe_rx_char_is_k_o(pipe_rx5_char_is_k_q), .pipe_rx_data_o(pipe_rx5_data_q), .pipe_rx_valid_o(pipe_rx5_valid_o), .pipe_rx_chanisaligned_o(pipe_rx5_chanisaligned_o), .pipe_rx_status_o(pipe_rx5_status_o), .pipe_rx_phy_status_o(pipe_rx5_phy_status_o), .pipe_rx_elec_idle_o(pipe_rx5_elec_idle_o), .pipe_rx_polarity_i(pipe_rx5_polarity_i), .pipe_tx_compliance_i(pipe_tx5_compliance_i), .pipe_tx_char_is_k_i(pipe_tx5_char_is_k_i), .pipe_tx_data_i(pipe_tx5_data_i), .pipe_tx_elec_idle_i(pipe_tx5_elec_idle_i), .pipe_tx_powerdown_i(pipe_tx5_powerdown_i), .pipe_rx_char_is_k_i(pipe_rx5_char_is_k_i), .pipe_rx_data_i(pipe_rx5_data_i), .pipe_rx_valid_i(pipe_rx5_valid_i), .pipe_rx_chanisaligned_i(pipe_rx5_chanisaligned_i), .pipe_rx_status_i(pipe_rx5_status_i), .pipe_rx_phy_status_i(pipe_rx4_phy_status_i), .pipe_rx_elec_idle_i(pipe_rx4_elec_idle_i), .pipe_rx_polarity_o(pipe_rx5_polarity_o), .pipe_tx_compliance_o(pipe_tx5_compliance_o), .pipe_tx_char_is_k_o(pipe_tx5_char_is_k_o), .pipe_tx_data_o(pipe_tx5_data_o), .pipe_tx_elec_idle_o(pipe_tx5_elec_idle_o), .pipe_tx_powerdown_o(pipe_tx5_powerdown_o), .pipe_clk(pipe_clk), .rst_n(rst_n) ); pcie_pipe_lane_v6 # ( .PIPE_PIPELINE_STAGES(PIPE_PIPELINE_STAGES) ) pipe_lane_6_i ( .pipe_rx_char_is_k_o(pipe_rx6_char_is_k_q), .pipe_rx_data_o(pipe_rx6_data_q), .pipe_rx_valid_o(pipe_rx6_valid_o), .pipe_rx_chanisaligned_o(pipe_rx6_chanisaligned_o), .pipe_rx_status_o(pipe_rx6_status_o), .pipe_rx_phy_status_o(pipe_rx6_phy_status_o), .pipe_rx_elec_idle_o(pipe_rx6_elec_idle_o), .pipe_rx_polarity_i(pipe_rx6_polarity_i), .pipe_tx_compliance_i(pipe_tx6_compliance_i), .pipe_tx_char_is_k_i(pipe_tx6_char_is_k_i), .pipe_tx_data_i(pipe_tx6_data_i), .pipe_tx_elec_idle_i(pipe_tx6_elec_idle_i), .pipe_tx_powerdown_i(pipe_tx6_powerdown_i), .pipe_rx_char_is_k_i(pipe_rx6_char_is_k_i), .pipe_rx_data_i(pipe_rx6_data_i), .pipe_rx_valid_i(pipe_rx6_valid_i), .pipe_rx_chanisaligned_i(pipe_rx6_chanisaligned_i), .pipe_rx_status_i(pipe_rx6_status_i), .pipe_rx_phy_status_i(pipe_rx4_phy_status_i), .pipe_rx_elec_idle_i(pipe_rx6_elec_idle_i), .pipe_rx_polarity_o(pipe_rx6_polarity_o), .pipe_tx_compliance_o(pipe_tx6_compliance_o), .pipe_tx_char_is_k_o(pipe_tx6_char_is_k_o), .pipe_tx_data_o(pipe_tx6_data_o), .pipe_tx_elec_idle_o(pipe_tx6_elec_idle_o), .pipe_tx_powerdown_o(pipe_tx6_powerdown_o), .pipe_clk(pipe_clk), .rst_n(rst_n) ); pcie_pipe_lane_v6 # ( .PIPE_PIPELINE_STAGES(PIPE_PIPELINE_STAGES) ) pipe_lane_7_i ( .pipe_rx_char_is_k_o(pipe_rx7_char_is_k_q), .pipe_rx_data_o(pipe_rx7_data_q), .pipe_rx_valid_o(pipe_rx7_valid_o), .pipe_rx_chanisaligned_o(pipe_rx7_chanisaligned_o), .pipe_rx_status_o(pipe_rx7_status_o), .pipe_rx_phy_status_o(pipe_rx7_phy_status_o), .pipe_rx_elec_idle_o(pipe_rx7_elec_idle_o), .pipe_rx_polarity_i(pipe_rx7_polarity_i), .pipe_tx_compliance_i(pipe_tx7_compliance_i), .pipe_tx_char_is_k_i(pipe_tx7_char_is_k_i), .pipe_tx_data_i(pipe_tx7_data_i), .pipe_tx_elec_idle_i(pipe_tx7_elec_idle_i), .pipe_tx_powerdown_i(pipe_tx7_powerdown_i), .pipe_rx_char_is_k_i(pipe_rx7_char_is_k_i), .pipe_rx_data_i(pipe_rx7_data_i), .pipe_rx_valid_i(pipe_rx7_valid_i), .pipe_rx_chanisaligned_i(pipe_rx7_chanisaligned_i), .pipe_rx_status_i(pipe_rx7_status_i), .pipe_rx_phy_status_i(pipe_rx4_phy_status_i), .pipe_rx_elec_idle_i(pipe_rx7_elec_idle_i), .pipe_rx_polarity_o(pipe_rx7_polarity_o), .pipe_tx_compliance_o(pipe_tx7_compliance_o), .pipe_tx_char_is_k_o(pipe_tx7_char_is_k_o), .pipe_tx_data_o(pipe_tx7_data_o), .pipe_tx_elec_idle_o(pipe_tx7_elec_idle_o), .pipe_tx_powerdown_o(pipe_tx7_powerdown_o), .pipe_clk(pipe_clk), .rst_n(rst_n) ); end else begin //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< assign pipe_rx4_char_is_k_o = 2'b00; assign pipe_rx4_data_o = 16'h0000; assign pipe_rx4_valid_o = 1'b0; assign pipe_rx4_chanisaligned_o = 1'b0; assign pipe_rx4_status_o = 3'b000; assign pipe_rx4_phy_status_o = 1'b0; assign pipe_rx4_elec_idle_o = 1'b1; assign pipe_rx4_polarity_o = 1'b0; assign pipe_tx4_compliance_o = 1'b0; assign pipe_tx4_char_is_k_o = 2'b00; assign pipe_tx4_data_o = 16'h0000; assign pipe_tx4_elec_idle_o = 1'b1; assign pipe_tx4_powerdown_o = 2'b00; assign pipe_rx5_char_is_k_o = 2'b00; assign pipe_rx5_data_o = 16'h0000; assign pipe_rx5_valid_o = 1'b0; assign pipe_rx5_chanisaligned_o = 1'b0; assign pipe_rx5_status_o = 3'b000; assign pipe_rx5_phy_status_o = 1'b0; assign pipe_rx5_elec_idle_o = 1'b1; assign pipe_rx5_polarity_o = 1'b0; assign pipe_tx5_compliance_o = 1'b0; assign pipe_tx5_char_is_k_o = 2'b00; assign pipe_tx5_data_o = 16'h0000; assign pipe_tx5_elec_idle_o = 1'b1; assign pipe_tx5_powerdown_o = 2'b00; assign pipe_rx6_char_is_k_o = 2'b00; assign pipe_rx6_data_o = 16'h0000; assign pipe_rx6_valid_o = 1'b0; assign pipe_rx6_chanisaligned_o = 1'b0; assign pipe_rx6_status_o = 3'b000; assign pipe_rx6_phy_status_o = 1'b0; assign pipe_rx6_elec_idle_o = 1'b1; assign pipe_rx6_polarity_o = 1'b0; assign pipe_tx6_compliance_o = 1'b0; assign pipe_tx6_char_is_k_o = 2'b00; assign pipe_tx6_data_o = 16'h0000; assign pipe_tx6_elec_idle_o = 1'b1; assign pipe_tx6_powerdown_o = 2'b00; assign pipe_rx7_char_is_k_o = 2'b00; assign pipe_rx7_data_o = 16'h0000; assign pipe_rx7_valid_o = 1'b0; assign pipe_rx7_chanisaligned_o = 1'b0; assign pipe_rx7_status_o = 3'b000; assign pipe_rx7_phy_status_o = 1'b0; assign pipe_rx7_elec_idle_o = 1'b1; assign pipe_rx7_polarity_o = 1'b0; assign pipe_tx7_compliance_o = 1'b0; assign pipe_tx7_char_is_k_o = 2'b00; assign pipe_tx7_data_o = 16'h0000; assign pipe_tx7_elec_idle_o = 1'b1; assign pipe_tx7_powerdown_o = 2'b00; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end endgenerate //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< assign pipe_rx0_char_is_k_o = pipe_rx0_char_is_k_q; assign pipe_rx0_data_o = pipe_rx0_data_q; assign pipe_rx1_char_is_k_o = pipe_rx1_char_is_k_q; assign pipe_rx1_data_o = pipe_rx1_data_q; assign pipe_rx2_char_is_k_o = pipe_rx2_char_is_k_q; assign pipe_rx2_data_o = pipe_rx2_data_q; assign pipe_rx3_char_is_k_o = pipe_rx3_char_is_k_q; assign pipe_rx3_data_o = pipe_rx3_data_q; assign pipe_rx4_char_is_k_o = pipe_rx4_char_is_k_q; assign pipe_rx4_data_o = pipe_rx4_data_q; assign pipe_rx5_char_is_k_o = pipe_rx5_char_is_k_q; assign pipe_rx5_data_o = pipe_rx5_data_q; assign pipe_rx6_char_is_k_o = pipe_rx6_char_is_k_q; assign pipe_rx6_data_o = pipe_rx6_data_q; assign pipe_rx7_char_is_k_o = pipe_rx7_char_is_k_q; assign pipe_rx7_data_o = pipe_rx7_data_q; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/pcie_reset_delay_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : pcie_reset_delay_v6.v // Version : 2.4 //-- //-- Description: sys_reset_n delay (20ms) for Virtex6 PCIe Block //-- //-- //-- //-------------------------------------------------------------------------------- `timescale 1ns/1ns module pcie_reset_delay_v6 # ( parameter PL_FAST_TRAIN = "FALSE", parameter REF_CLK_FREQ = 0, // 0 - 100 MHz, 1 - 125 MHz, 2 - 250 MHz parameter TCQ = 1 ) ( input wire ref_clk, input wire sys_reset_n, output delayed_sys_reset_n ); localparam TBIT = (PL_FAST_TRAIN == "FALSE") ? ((REF_CLK_FREQ == 1) ? 20: (REF_CLK_FREQ == 0) ? 20 : 21) : 2; reg [7:0] reg_count_7_0; reg [7:0] reg_count_15_8; reg [7:0] reg_count_23_16; wire [23:0] concat_count; assign concat_count = {reg_count_23_16, reg_count_15_8, reg_count_7_0}; always @(posedge ref_clk or negedge sys_reset_n) begin if (!sys_reset_n) begin reg_count_7_0 <= #TCQ 8'h0; reg_count_15_8 <= #TCQ 8'h0; reg_count_23_16 <= #TCQ 8'h0; end else begin if (delayed_sys_reset_n != 1'b1) begin reg_count_7_0 <= #TCQ reg_count_7_0 + 1'b1; reg_count_15_8 <= #TCQ (reg_count_7_0 == 8'hff)? reg_count_15_8 + 1'b1 : reg_count_15_8 ; reg_count_23_16 <= #TCQ ((reg_count_15_8 == 8'hff) & (reg_count_7_0 == 8'hff)) ? reg_count_23_16 + 1'b1 : reg_count_23_16; end end end assign delayed_sys_reset_n = concat_count[TBIT]; endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/pcie_upconfig_fix_3451_v6.v ================================================ //----------------------------------------------------------------------------- // // (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. // // This file contains confidential and proprietary information // of Xilinx, Inc. and is protected under U.S. and // international copyright and other intellectual property // laws. // // DISCLAIMER // This disclaimer is not a license and does not grant any // rights to the materials distributed herewith. Except as // otherwise provided in a valid license issued to you by // Xilinx, and to the maximum extent permitted by applicable // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and // (2) Xilinx shall not be liable (whether in contract or tort, // including negligence, or under any other theory of // liability) for any loss or damage of any kind or nature // related to, arising under or in connection with these // materials, including for any direct, or any indirect, // special, incidental, or consequential loss or damage // (including loss of data, profits, goodwill, or any type of // loss or damage suffered as a result of any action brought // by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the // possibility of the same. // // CRITICAL APPLICATIONS // Xilinx products are not designed or intended to be fail- // safe, or for use in any application requiring fail-safe // performance, such as life-support or safety devices or // systems, Class III medical devices, nuclear facilities, // applications related to the deployment of airbags, or any // other applications that could lead to death, personal // injury, or severe property or environmental damage // (individually and collectively, "Critical // Applications"). Customer assumes the sole risk and // liability of any use of Xilinx products in Critical // Applications, subject only to applicable laws and // regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS // PART OF THIS FILE AT ALL TIMES. // //----------------------------------------------------------------------------- // Project : Virtex-6 Integrated Block for PCI Express // File : pcie_upconfig_fix_3451_v6.v // Version : 2.4 //-- //-- Description: Virtex6 Workaround for Root Port Upconfigurability Bug //-- //-- //-------------------------------------------------------------------------------- `timescale 1ns/1ns module pcie_upconfig_fix_3451_v6 # ( parameter UPSTREAM_FACING = "TRUE", parameter PL_FAST_TRAIN = "FALSE", parameter LINK_CAP_MAX_LINK_WIDTH = 6'h08, parameter TCQ = 1 ) ( input pipe_clk, input pl_phy_lnkup_n, input [5:0] pl_ltssm_state, input pl_sel_lnk_rate, input [1:0] pl_directed_link_change, input [3:0] cfg_link_status_negotiated_width, input [15:0] pipe_rx0_data, input [1:0] pipe_rx0_char_isk, output filter_pipe ); reg reg_filter_pipe; reg [15:0] reg_tsx_counter; wire [15:0] tsx_counter; wire [5:0] cap_link_width; // Corrupting all Tsx on all lanes as soon as we do R.RC->R.RI transition to allow time for // the core to see the TS1s on all the lanes being configured at the same time // R.RI has a 2ms timeout.Corrupting tsxs for ~1/4 of that time // 225 pipe_clk cycles-sim_fast_train // 60000 pipe_clk cycles-without sim_fast_train // Not taking any action when PLDIRECTEDLINKCHANGE is set // Detect xx, COM then PAD,xx or COM,PAD then PAD,xx // data0 will be the first symbol on lane 0, data1 will be the next symbol. // Don't look for PAD on data1 since it's unnecessary. // COM=0xbc and PAD=0xf7 (and isk). // detect if (data & 0xb4) == 0xb4 and isk, and then // if (data & 0x4b) == 0x08 or 0x43. This distinguishes COM and PAD, using // no more than a 6-input LUT, so should be "free". reg reg_filter_used, reg_com_then_pad; reg reg_data0_b4, reg_data0_08, reg_data0_43; reg reg_data1_b4, reg_data1_08, reg_data1_43; reg reg_data0_com, reg_data1_com, reg_data1_pad; wire data0_b4 = pipe_rx0_char_isk[0] && ((pipe_rx0_data[7:0] & 8'hb4) == 8'hb4); wire data0_08 = ((pipe_rx0_data[7:0] & 8'h4b) == 8'h08); wire data0_43 = ((pipe_rx0_data[7:0] & 8'h4b) == 8'h43); wire data1_b4 = pipe_rx0_char_isk[1] && ((pipe_rx0_data[15:8] & 8'hb4) == 8'hb4); wire data1_08 = ((pipe_rx0_data[15:8] & 8'h4b) == 8'h08); wire data1_43 = ((pipe_rx0_data[15:8] & 8'h4b) == 8'h43); wire data0_com = reg_data0_b4 && reg_data0_08; wire data1_com = reg_data1_b4 && reg_data1_08; wire data0_pad = reg_data0_b4 && reg_data0_43; wire data1_pad = reg_data1_b4 && reg_data1_43; wire com_then_pad0 = reg_data0_com && reg_data1_pad && data0_pad; wire com_then_pad1 = reg_data1_com && data0_pad && data1_pad; wire com_then_pad = (com_then_pad0 || com_then_pad1) && ~reg_filter_used; wire filter_used = (pl_ltssm_state == 6'h20) && (reg_filter_pipe || reg_filter_used); always @(posedge pipe_clk) begin reg_data0_b4 <= #TCQ data0_b4; reg_data0_08 <= #TCQ data0_08; reg_data0_43 <= #TCQ data0_43; reg_data1_b4 <= #TCQ data1_b4; reg_data1_08 <= #TCQ data1_08; reg_data1_43 <= #TCQ data1_43; reg_data0_com <= #TCQ data0_com; reg_data1_com <= #TCQ data1_com; reg_data1_pad <= #TCQ data1_pad; reg_com_then_pad <= #TCQ (~pl_phy_lnkup_n) ? com_then_pad : 1'b0; reg_filter_used <= #TCQ (~pl_phy_lnkup_n) ? filter_used : 1'b0; end always @ (posedge pipe_clk) begin if (pl_phy_lnkup_n) begin reg_tsx_counter <= #TCQ 16'h0; reg_filter_pipe <= #TCQ 1'b0; end else if ((pl_ltssm_state == 6'h20) && reg_com_then_pad && (cfg_link_status_negotiated_width != cap_link_width) && (pl_directed_link_change[1:0] == 2'b00)) begin reg_tsx_counter <= #TCQ 16'h0; reg_filter_pipe <= #TCQ 1'b1; end else if (filter_pipe == 1'b1) begin if (tsx_counter < ((PL_FAST_TRAIN == "TRUE") ? 16'd225: pl_sel_lnk_rate ? 16'd800 : 16'd400)) begin reg_tsx_counter <= #TCQ tsx_counter + 1'b1; reg_filter_pipe <= #TCQ 1'b1; end else begin reg_tsx_counter <= #TCQ 16'h0; reg_filter_pipe <= #TCQ 1'b0; end end end assign filter_pipe = (UPSTREAM_FACING == "TRUE") ? 1'b0 : reg_filter_pipe; assign tsx_counter = reg_tsx_counter; assign cap_link_width = LINK_CAP_MAX_LINK_WIDTH; endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/ram_1clk_1w_1r.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: ram_1clk_1w_1r.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: An inferrable RAM module. Single clock, 1 write port, 1 // read port. In Xilinx designs, specify RAM_STYLE="BLOCK" // to use BRAM memory or RAM_STYLE="DISTRIBUTED" to use // LUT memory. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module ram_1clk_1w_1r ( CLK, ADDRA, WEA, DINA, ADDRB, DOUTB ); `include "common_functions.v" parameter C_RAM_WIDTH = 32; parameter C_RAM_DEPTH = 1024; //Local parameters parameter C_RAM_ADDR_BITS = clog2s(C_RAM_DEPTH); input CLK; input [C_RAM_ADDR_BITS-1:0] ADDRA; input WEA; input [C_RAM_ADDR_BITS-1:0] ADDRB; input [C_RAM_WIDTH-1:0] DINA; output [C_RAM_WIDTH-1:0] DOUTB; reg [C_RAM_WIDTH-1:0] rRAM [C_RAM_DEPTH-1:0]; reg [C_RAM_WIDTH-1:0] rDout; assign DOUTB = rDout; always @(posedge CLK) begin if (WEA) rRAM[ADDRA] <= #1 DINA; rDout <= #1 rRAM[ADDRB]; end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/ram_2clk_1w_1r.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: ram_2clk_1w_1r.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: An inferrable RAM module. Dual clocks, 1 write port, 1 // read port. In Xilinx designs, specify RAM_STYLE="BLOCK" // to use BRAM memory or RAM_STYLE="DISTRIBUTED" to use // LUT memory. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module ram_2clk_1w_1r ( CLKA, ADDRA, WEA, DINA, CLKB, ADDRB, DOUTB ); `include "common_functions.v" parameter C_RAM_WIDTH = 32; parameter C_RAM_DEPTH = 1024; //Local parameters parameter C_RAM_ADDR_BITS = clog2s(C_RAM_DEPTH); input CLKA; input CLKB; input WEA; input [C_RAM_ADDR_BITS-1:0] ADDRA; input [C_RAM_ADDR_BITS-1:0] ADDRB; input [C_RAM_WIDTH-1:0] DINA; output [C_RAM_WIDTH-1:0] DOUTB; reg [C_RAM_WIDTH-1:0] rRAM [C_RAM_DEPTH-1:0]; reg [C_RAM_WIDTH-1:0] rDout; assign DOUTB = rDout; always @(posedge CLKA) begin if (WEA) rRAM[ADDRA] <= #1 DINA; end always @(posedge CLKB) begin rDout <= #1 rRAM[ADDRB]; end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/recv_credit_flow_ctrl.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: recv_credit_flow_ctrl.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Monitors the receive completion credits for headers and // data to make sure the rx_port modules don't request too // much data from the root complex, as this could result in // some data being dropped/lost. // Author: Matt Jacobsen // Author: Dustin Richmond // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module recv_credit_flow_ctrl ( input CLK, input RST, input [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // Maximum read payload: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B input [11:0] CONFIG_MAX_CPL_DATA, // Receive credit limit for data input [7:0] CONFIG_MAX_CPL_HDR, // Receive credit limit for headers input CONFIG_CPL_BOUNDARY_SEL, // Read completion boundary (0=64 bytes, 1=128 bytes)w input RX_ENG_RD_DONE, // Read completed input TX_ENG_RD_REQ_SENT, // Read completion request issued output RXBUF_SPACE_AVAIL // High if enough read completion credits exist to make a read completion request ); reg rCreditAvail=0; reg rCplDAvail=0; reg rCplHAvail=0; reg [12:0] rMaxRecv=0; reg [11:0] rCplDAmt=0; reg [7:0] rCplHAmt=0; reg [11:0] rCplD=0; reg [7:0] rCplH=0; assign RXBUF_SPACE_AVAIL = rCreditAvail; // Determine the completions required for a max read completion request. always @(posedge CLK) begin rMaxRecv <= #1 (13'd128<>({2'b11, CONFIG_CPL_BOUNDARY_SEL})); rCplDAmt <= #1 (rMaxRecv>>4); rCplHAvail <= #1 (rCplH <= CONFIG_MAX_CPL_HDR); rCplDAvail <= #1 (rCplD <= CONFIG_MAX_CPL_DATA); rCreditAvail <= #1 (rCplHAvail & rCplDAvail); end // Count the number of outstanding read completion requests. always @ (posedge CLK) begin if (RST) begin rCplH <= #1 0; rCplD <= #1 0; end else if (RX_ENG_RD_DONE & TX_ENG_RD_REQ_SENT) begin rCplH <= #1 rCplH; rCplD <= #1 rCplD; end else if (TX_ENG_RD_REQ_SENT) begin rCplH <= #1 rCplH + rCplHAmt; rCplD <= #1 rCplD + rCplDAmt; end else if (RX_ENG_RD_DONE) begin rCplH <= #1 rCplH - rCplHAmt; rCplD <= #1 rCplD - rCplDAmt; end end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/reorder_queue.v ================================================ `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 19:27:32 06/14/2012 // Design Name: // Module Name: reorder_queue // Project Name: // Target Devices: // Tool versions: // Description: // Reorders downstream TLPs to output in increasing tag sequence. Input packets // are stored in RAM and then read out when all previous sequence numbers have // arrived and been read out. This module also provides the next available tag // for the TX engine to use when sending memory request TLPs. // // Dependencies: // reorder_queue_input.v // reorder_queue_output.v // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module reorder_queue #( parameter C_PCI_DATA_WIDTH = 9'd128, parameter C_NUM_CHNL = 4'd12, parameter C_MAX_READ_REQ_BYTES = 512, // Max size of read requests (in bytes) parameter C_TAG_WIDTH = 5, // Number of outstanding requests // Local parameters parameter C_PCI_DATA_WORD = C_PCI_DATA_WIDTH/32, parameter C_PCI_DATA_COUNT_WIDTH = clog2(C_PCI_DATA_WORD+1), parameter C_NUM_TAGS = 2**C_TAG_WIDTH, parameter C_DW_PER_TAG = C_MAX_READ_REQ_BYTES/4, parameter C_TAG_DW_COUNT_WIDTH = clog2s(C_DW_PER_TAG+1), parameter C_DATA_ADDR_STRIDE_WIDTH = clog2s(C_DW_PER_TAG/C_PCI_DATA_WORD), // div by C_PCI_DATA_WORD b/c there are C_PCI_DATA_WORD RAMs parameter C_DATA_ADDR_WIDTH = C_TAG_WIDTH + C_DATA_ADDR_STRIDE_WIDTH ) ( input CLK, // Clock input RST, // Synchronous reset input VALID, // Valid input packet input [C_PCI_DATA_WIDTH-1:0] DATA, // Input packet payload input [C_PCI_DATA_WORD-1:0] DATA_EN, // Input packet payload data enable input [C_PCI_DATA_COUNT_WIDTH-1:0] DATA_EN_COUNT, // Input packet payload data enable count input DONE, // Input packet done input ERR, // Input packet has error input [C_TAG_WIDTH-1:0] TAG, // Input packet tag (external tag) input [5:0] INT_TAG, // Internal tag to exchange with external input INT_TAG_VALID, // High to signal tag exchange output [C_TAG_WIDTH-1:0] EXT_TAG, // External tag to provide in exchange for internal tag output EXT_TAG_VALID, // High to signal external tag is valid output [C_PCI_DATA_WIDTH-1:0] ENG_DATA, // Engine data output [(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)-1:0] MAIN_DATA_EN, // Main data enable output [C_NUM_CHNL-1:0] MAIN_DONE, // Main data complete output [C_NUM_CHNL-1:0] MAIN_ERR, // Main data completed with error output [(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)-1:0] SG_RX_DATA_EN, // Scatter gather for RX data enable output [C_NUM_CHNL-1:0] SG_RX_DONE, // Scatter gather for RX data complete output [C_NUM_CHNL-1:0] SG_RX_ERR, // Scatter gather for RX data completed with error output [(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)-1:0] SG_TX_DATA_EN, // Scatter gather for TX data enable output [C_NUM_CHNL-1:0] SG_TX_DONE, // Scatter gather for TX data complete output [C_NUM_CHNL-1:0] SG_TX_ERR // Scatter gather for TX data completed with error ); `include "common_functions.v" wire [(C_DATA_ADDR_WIDTH*C_PCI_DATA_WORD)-1:0] wWrDataAddr; wire [C_PCI_DATA_WIDTH-1:0] wWrData; wire [C_PCI_DATA_WORD-1:0] wWrDataEn; wire [C_TAG_WIDTH-1:0] wWrPktTag; wire [C_TAG_DW_COUNT_WIDTH-1:0] wWrPktWords; wire wWrPktWordsLTE1; wire wWrPktWordsLTE2; wire wWrPktValid; wire wWrPktDone; wire wWrPktErr; wire [C_DATA_ADDR_WIDTH-1:0] wRdDataAddr; wire [C_PCI_DATA_WIDTH-1:0] wRdData; wire [C_TAG_WIDTH-1:0] wRdPktTag; wire [(1+1+1+1+C_TAG_DW_COUNT_WIDTH)-1:0] wRdPktInfo; wire [5:0] wRdTagMap; reg [C_TAG_WIDTH-1:0] rPos=0; reg rValid=0; wire [C_NUM_TAGS-1:0] wFinish; reg [C_NUM_TAGS-1:0] rFinished=0; reg [C_NUM_TAGS-1:0] rUse=0; reg [C_NUM_TAGS-1:0] rUsing=0; wire [C_NUM_TAGS-1:0] wClear; assign EXT_TAG = rPos; assign EXT_TAG_VALID = rValid; // Move through tag/slot/bucket space. always @ (posedge CLK) begin if (RST) begin rPos <= #1 0; rUse <= #1 0; rValid <= #1 0; end else begin if (INT_TAG_VALID & EXT_TAG_VALID) begin rPos <= #1 rPos + 1'd1; rUse <= #1 1<>rTag[0*C_TAG_WIDTH +:C_TAG_WIDTH]); rValidCount <= #1 (RST ? 0 : rValid[0]<>(C_PCI_DATA_WORD-rShift)); // To cover the gap b/t reads and writes to RAM, next cycle we might need // to use the existing or even the previous rPos values if the tags match. rUseCurrPos <= #1 (rTag[2*C_TAG_WIDTH +:C_TAG_WIDTH] == rTag[3*C_TAG_WIDTH +:C_TAG_WIDTH] && rValid[3]); rUsePrevPos <= #1 (rTag[2*C_TAG_WIDTH +:C_TAG_WIDTH] == rTag[4*C_TAG_WIDTH +:C_TAG_WIDTH] && rValid[4]); for (i = 0; i < C_PCI_DATA_WORD; i = i + 1) begin rPrevPos[C_DATA_ADDR_STRIDE_WIDTH*i +:C_DATA_ADDR_STRIDE_WIDTH] <= #1 (RST ? wZero[C_DATA_ADDR_STRIDE_WIDTH-1:0] : rPos[C_DATA_ADDR_STRIDE_WIDTH*i +:C_DATA_ADDR_STRIDE_WIDTH]); end // See if we need to reset the positions rPosValid <= #1 (RST ? 1'd0 : rPosRst>>rTag[2*C_TAG_WIDTH +:C_TAG_WIDTH]); rValidPos <= #1 (RST ? 0 : rValid[2]<>rShiftDown); rLTE1Pkt <= #1 (rWords[1*C_TAG_DW_COUNT_WIDTH +:C_TAG_DW_COUNT_WIDTH] <= C_PCI_DATA_WORD); rLTE2Pkt <= #1 (rWords[1*C_TAG_DW_COUNT_WIDTH +:C_TAG_DW_COUNT_WIDTH] <= (C_PCI_DATA_WORD*2)); rFinish <= #1 (rValid[4] & (rDone[4] | rErr[4]))<>(32*rDataIn[29])); wire [C_PCI_DATA_WIDTH-1:0] wDataIn64bShftB = (rDataIn>>(32*rNext4DWHeader)); always @ (posedge CLK) begin rReqState <= #1 (RST ? `S_RXENG128_REQ_PARSE : _rReqState); rReqWen <= #1 (RST ? 1'd0 : _rReqWen); rTC <= #1 _rTC; rTD <= #1 _rTD; rEP <= #1 _rEP; rAttr <= #1 _rAttr; rReqLen <= #1 _rReqLen; rReqId <= #1 _rReqId; rReqTag <= #1 _rReqTag; rBE <= #1 _rBE; rRNW <= #1 _rRNW; rReqData <= #1 _rReqData; rReqAddr <= #1 _rReqAddr; rNQWA <= #1 _rNQWA; rNextTC <= #1 _rNextTC; rNextTD <= #1 _rNextTD; rNextEP <= #1 _rNextEP; rNextAttr <= #1 _rNextAttr; rNextReqLen <= #1 _rNextReqLen; rNextReqId <= #1 _rNextReqId; rNextReqTag <= #1 _rNextReqTag; rNextBE <= #1 _rNextBE; rNextRNW <= #1 _rNextRNW; rNext4DWHeader <= #1 _rNext4DWHeader; end always @ (*) begin _rReqState = rReqState; _rTC = rTC; _rTD = rTD; _rEP = rEP; _rAttr = rAttr; _rReqLen = rReqLen; _rReqId = rReqId; _rReqTag = rReqTag; _rBE = rBE; _rRNW = rRNW; _rReqData = rReqData; _rReqAddr = rReqAddr; _rReqWen = rReqWen; _rNQWA = rNQWA; _rNextTC = (rValid ? rDataIn[86:84] : rNextTC); _rNextTD = (rValid ? rDataIn[79] : rNextTD); _rNextEP = (rValid ? rDataIn[78] : rNextEP); _rNextAttr = (rValid ? rDataIn[77:76] : rNextAttr); _rNextReqLen = (rValid ? rDataIn[73:64] : rNextReqLen); _rNextReqId = (rValid ? rDataIn[127:112] : rNextReqId); _rNextReqTag = (rValid ? rDataIn[111:104] : rNextReqTag); _rNextBE = (rValid ? rDataIn[99:96] : rNextBE); _rNextRNW = (rValid ? rFmtHi[0] : rNextRNW); _rNext4DWHeader = (rValid ? rDataIn[93] : rNext4DWHeader); case (rReqState) `S_RXENG128_REQ_PARSE : begin _rNQWA = RX_DATA[98] & RX_DATA[29] & wALTERA; // 98 is 3rd address bit, 29 is 4 DW header, _rTC = rDataIn[22:20]; _rTD = rDataIn[15]; _rEP = rDataIn[14]; _rAttr = rDataIn[13:12]; _rReqLen = rDataIn[9:0]; _rReqId = rDataIn[63:48]; _rReqTag = rDataIn[47:40]; _rBE = rDataIn[35:32]; _rRNW = rFmtLo[0]; _rReqAddr = wDataIn64bShftA[95:66]; _rReqData = rDataIn[127:96]; // Write the request to the fifo if it's a read (no data) or it's a write with a 3DWH and a non-QWA address (EOF) // (rFmtLo checks for SOF) _rReqWen = rLenOneLo & ((rFmtLo == 3'd1) || ((rFmtLo == 3'd2) && (rEOF == 1'b1))); // rFmtHi/rFmtLo non-zero if the packet is valid, only one will have a non-zero value case ({rFmtHi, rFmtLo}) {3'd1, 3'd0} : _rReqState = (rLenOneHi ? `S_RXENG128_REQ_ASSIGN : `S_RXENG128_REQ_PARSE); {3'd0, 3'd2} : _rReqState = (rLenOneLo & ~rEOF) ? `S_RXENG128_REQ_DATA : `S_RXENG128_REQ_PARSE; {3'd2, 3'd0} : _rReqState = (rLenOneHi ? `S_RXENG128_REQ_ASSIGN : `S_RXENG128_REQ_PARSE); default : _rReqState = `S_RXENG128_REQ_PARSE; endcase end `S_RXENG128_REQ_ASSIGN : begin _rTC = rNextTC; _rTD = rNextTD; _rEP = rNextEP; _rAttr = rNextAttr; _rReqLen = rNextReqLen; _rReqId = rNextReqId; _rReqTag = rNextReqTag; _rBE = rNextBE; _rRNW = rNextRNW; _rReqAddr = wDataIn64bShftB[31:2]; _rReqData = wDataIn64bShftB[63:32]; _rReqWen = rValid; if (rValid) begin case (rFmtHi) 3'd1 : _rReqState = (rLenOneHi ? `S_RXENG128_REQ_ASSIGN : `S_RXENG128_REQ_PARSE); 3'd2 : _rReqState = (rLenOneHi ? `S_RXENG128_REQ_ASSIGN : `S_RXENG128_REQ_PARSE); default : _rReqState = `S_RXENG128_REQ_PARSE; endcase end end `S_RXENG128_REQ_DATA : begin _rReqData = rDataIn >> ({5'd0,rNQWA}<<5); _rReqWen = rValid; if (rValid) begin case (rFmtHi) 3'd1 : _rReqState = (rLenOneHi ? `S_RXENG128_REQ_ASSIGN : `S_RXENG128_REQ_PARSE); 3'd2 : _rReqState = (rLenOneHi ? `S_RXENG128_REQ_ASSIGN : `S_RXENG128_REQ_PARSE); default : _rReqState = `S_RXENG128_REQ_PARSE; endcase end end default : begin _rReqState = `S_RXENG128_REQ_PARSE; end endcase end // Handle cpls and cplds. always @ (posedge CLK) begin rCplState <= #1 (RST ? `S_RXENG128_CPL_PARSE : _rCplState); rDataEn <= #1 (RST ? 4'd0 : _rDataEn); rDataCount <= #1 (RST ? 3'd0 : _rDataCount); rDone <= #1 (RST ? 1'd0 : _rDone); rErr <= #1 (RST ? 1'd0 : _rErr); rLastCPLD <= #1 _rLastCPLD; rData <= #1 _rData; rNextCplErr <= #1 _rNextCplErr; rNextLastCPLD <= #1 _rNextLastCPLD; rOutValid <= #1 _rOutValid; rShft <= #1 _rShft; end always @ (*) begin _rCplState = rCplState; _rLastCPLD = rLastCPLD; _rDataEn = rDataEn; _rDataCount = rDataCount; _rDone = rDone; _rErr = rErr; _rShft = rShft; _rOutValid = rValid; _rData = (rDataIn>>(32*rCplState)); // See state values _rNextCplErr = (rValid ? rCplErrHi : rNextCplErr); // Completion status code _rNextLastCPLD = (rValid ? (rDataIn[107:96] == (rDataIn[73:64]<<2)) : rNextLastCPLD); // byte_count == length ? case (rCplState) `S_RXENG128_CPL_PARSE : begin _rShft = rDataIn[79:72]; // Tag _rDataEn = (rFmtLo[2] & rFmtLo[1] & (~rQWACpl | ~wALTERA)); // 1 if rFmtLo == 6 _rDataCount = (rFmtLo[2] & rFmtLo[1] & (~rQWACpl | ~wALTERA)); // 1 if rFmtLo == 6 _rErr = (rFmtLo[2] & rCplErrLo); // If rFmtLo == 4 or rFmtLo == 6 _rDone = (rFmtLo[2] & (!rFmtLo[1] | rEOF)); // If rFmtLo == 4 or (rFmtLo == 6 && length == 1) // Save for S_RXENG128_CPL_DATA_CONT _rLastCPLD = (rDataIn[43:32] == (rDataIn[9:0]<<2)); // byte_count == length ? // rFmtHi/rFmtLo non-zero if the packet is valid, only one will have a non-zero value case ({rFmtHi, rFmtLo}) {3'd0, 3'd4} : _rCplState = `S_RXENG128_CPL_PARSE; {3'd4, 3'd0} : _rCplState = `S_RXENG128_CPL_NO_DATA; {3'd0, 3'd6} : _rCplState = (`S_RXENG128_CPL_PARSE & {2{(rEOF | rCplErrLo)}}); // Changes to S_RXENG128_CPL_DATA_CONT {3'd6, 3'd0} : _rCplState = `S_RXENG128_CPL_DATA; default : _rCplState = `S_RXENG128_CPL_PARSE; endcase end `S_RXENG128_CPL_NO_DATA : begin _rShft = rDataIn[15:8]; // Tag _rDataEn = 0; _rDataCount = 0; _rErr = rNextCplErr; _rDone = 1; if (rValid) begin case (rFmtHi) 3'd4 : _rCplState = `S_RXENG128_CPL_NO_DATA; 3'd6 : _rCplState = `S_RXENG128_CPL_DATA; default : _rCplState = `S_RXENG128_CPL_PARSE; endcase end end `S_RXENG128_CPL_DATA : begin _rShft = rDataIn[15:8]; // Tag _rDataEn = ({3{!rEOF}} | wEOFPosEn[5:3]); _rDataCount = ({2{!rEOF}} | rEOFPos); _rErr = rNextCplErr; _rDone = (rEOF & rNextLastCPLD); // Save for S_RXENG128_CPL_DATA_CONT _rLastCPLD = rNextLastCPLD; if (rValid) begin if (rEOF) begin // Ends in this packet case (rFmtHi) 3'd4 : _rCplState = `S_RXENG128_CPL_NO_DATA; 3'd6 : _rCplState = `S_RXENG128_CPL_DATA; default : _rCplState = `S_RXENG128_CPL_PARSE; endcase end else if (rNextCplErr) begin // Bad completion code _rCplState = `S_RXENG128_CPL_PARSE; end else begin // Continues past this packet, send 1 DW now _rCplState = `S_RXENG128_CPL_DATA_CONT; end end end `S_RXENG128_CPL_DATA_CONT : begin // Process TLP until end _rDataEn = ({4{!rEOF}} | wEOFCountEn[7:4]); _rDataCount = (rEOFCount | {!rEOF, 2'd0}); _rErr = 0; _rDone = (rEOF & rLastCPLD); if (rValid) begin // Process and write until last packet if (rEOF) begin case (rFmtHi) 3'd4 : _rCplState = `S_RXENG128_CPL_NO_DATA; 3'd6 : _rCplState = `S_RXENG128_CPL_DATA; default : _rCplState = `S_RXENG128_CPL_PARSE; endcase end end end endcase end // Output the data and enables always @ (posedge CLK) begin rDataValid <= #1 (RST ? 1'd0 : _rDataValid); rDataOutEn <= #1 _rDataOutEn; rDataOutCount <= #1 _rDataOutCount; rDataDone <= #1 _rDataDone; rDataErr <= #1 _rDataErr; rDataTag <= #1 _rDataTag; rDataOut <= #1 _rDataOut; end always @ (*) begin _rDataValid = (rOutValid && ((rDataCount | rDone | rErr) != 3'd0)); _rDataOutEn = rDataEn; _rDataOutCount = rDataCount; _rDataDone = (rDone | rErr); _rDataErr = rErr; _rDataTag = rShft[C_TAG_WIDTH-1:0]; _rDataOut = rData; end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/rx_engine_32.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: rx_engine_32.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Receive engine for PCIe using AXI interface from Xilinx // PCIe Endpoint core. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: Very good PCIe header reference: // http://www.pzk-agro.com/0321156307_ch04lev1sec5.html#ch04lev4sec14 // Also byte swap each payload word due to Xilinx incorrect mapping, see // http://forums.xilinx.com/t5/PCI-Express/PCI-Express-payload-required-to-be-Big-Endian-by-specification/td-p/285551 //----------------------------------------------------------------------------- `define FMT_RXENG32_RD32 7'b00_00000 `define FMT_RXENG32_WR32 7'b10_00000 `define FMT_RXENG32_RD64 7'b01_00000 `define FMT_RXENG32_WR64 7'b11_00000 `define FMT_RXENG32_CPL 7'b00_01010 `define FMT_RXENG32_CPLD 7'b10_01010 `define S_RXENG32_REQ_PARSE 3'd0 `define S_RXENG32_REQ_UNHANDLED 3'd1 `define S_RXENG32_REQ_MEM_0 3'd2 `define S_RXENG32_REQ_MEM_1 3'd3 `define S_RXENG32_REQ_MEM_2 3'd4 `define S_RXENG32_REQ_MEM_WR 3'd5 `define S_RXENG32_CPL_PARSE 3'd0 `define S_RXENG32_CPL_WAIT_FOR_END 3'd1 `define S_RXENG32_CPL_0 3'd2 `define S_RXENG32_CPL_1 3'd3 `define S_RXENG32_CPL_DATA 3'd4 module rx_engine_32 #( parameter C_PCI_DATA_WIDTH = 9'd32, parameter C_NUM_CHNL = 4'd12, parameter C_MAX_READ_REQ_BYTES = 512, // Max size of read requests (in bytes) parameter C_TAG_WIDTH = 5, // Number of outstanding requests // Local parameters parameter C_PCI_DATA_WORD = C_PCI_DATA_WIDTH/32, parameter C_PCI_DATA_COUNT_WIDTH = clog2s(C_PCI_DATA_WORD+1) ) ( input CLK, input RST, // Receive input [C_PCI_DATA_WIDTH-1:0] RX_DATA, input RX_TLP_END_FLAG, input RX_DATA_VALID, output RX_DATA_READY, input RX_TLP_ERROR_POISON, // Received read/write memory requests output REQ_WR, // Memory write request input REQ_WR_DONE, // Memory write completed output REQ_RD, // Memory read request input REQ_RD_DONE, // Memory read complete output [9:0] REQ_LEN, // Memory length (1DW) output [29:0] REQ_ADDR, // Memory address (bottom 2 bits are always 00) output [31:0] REQ_DATA, // Memory write data output [3:0] REQ_BE, // Memory byte enables output [2:0] REQ_TC, // Memory traffic class output REQ_TD, // Memory packet digest output REQ_EP, // Memory poisoned packet output [1:0] REQ_ATTR, // Memory packet relaxed ordering, no snoop output [15:0] REQ_ID, // Memory requestor id output [7:0] REQ_TAG, // Memory packet tag // Tag exchange input [5:0] INT_TAG, // Internal tag to exchange with external input INT_TAG_VALID, // High to signal tag exchange output [C_TAG_WIDTH-1:0] EXT_TAG, // External tag to provide in exchange for internal tag output EXT_TAG_VALID, // High to signal external tag is valid // Received read completions output ENG_RD_COMPLETE, output [C_PCI_DATA_WIDTH-1:0] ENG_DATA, // Engine data output [(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)-1:0] MAIN_DATA_EN, // Main data enable output [C_NUM_CHNL-1:0] MAIN_DONE, // Main data complete output [C_NUM_CHNL-1:0] MAIN_ERR, // Main data completed with error output [(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)-1:0] SG_RX_DATA_EN, // Scatter gather for RX data enable output [C_NUM_CHNL-1:0] SG_RX_DONE, // Scatter gather for RX data complete output [C_NUM_CHNL-1:0] SG_RX_ERR, // Scatter gather for RX data completed with error output [(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)-1:0] SG_TX_DATA_EN, // Scatter gather for TX data enable output [C_NUM_CHNL-1:0] SG_TX_DONE, // Scatter gather for TX data complete output [C_NUM_CHNL-1:0] SG_TX_ERR // Scatter gather for TX data completed with error ); `include "common_functions.v" reg [2:0] rTrigger=0, _rTrigger=0; reg [C_PCI_DATA_WIDTH-1:0] rDataIn=0, _rDataIn=0; reg rValidIn=0, _rValidIn=0; reg rLastIn=0, _rLastIn=0; reg rLenOneIn=0, _rLenOneIn=0; reg [2:0] rReqState=`S_RXENG32_REQ_PARSE, _rReqState=`S_RXENG32_REQ_PARSE; reg [29:0] rReqAddr=0, _rReqAddr=0; reg [31:0] rReqData=0, _rReqData=0; reg rReqWen=0, _rReqWen=0; reg rRNW=0, _rRNW=0; reg [3:0] rBE=0, _rBE=0; reg [2:0] rTC=0, _rTC=0; reg rTD=0, _rTD=0; reg rEP=0, _rEP=0; reg [1:0] rAttr=0, _rAttr=0; reg [9:0] rReqLen=0, _rReqLen=0; reg [15:0] rReqId=0, _rReqId=0; reg [7:0] rReqTag=0, _rReqTag=0; reg r3DWHeader=0, _r3DWHeader=0; reg [2:0] rCplState=`S_RXENG32_CPL_PARSE, _rCplState=`S_RXENG32_CPL_PARSE; reg rCplErr=0, _rCplErr=0; reg rLastCPLD=0, _rLastCPLD=0; reg [C_PCI_DATA_COUNT_WIDTH-1:0] rDataOutCount=0, _rDataOutCount=0; reg [C_PCI_DATA_WORD-1:0] rDataOutEn=0, _rDataOutEn=0; reg [C_PCI_DATA_WIDTH-1:0] rDataOut={C_PCI_DATA_WIDTH{1'b0}}, _rDataOut={C_PCI_DATA_WIDTH{1'b0}}; reg rDataDone=0, _rDataDone=0; reg rDataErr=0, _rDataErr=0; reg rDataValid=0, _rDataValid=0; reg [7:0] rChnlShft=0, _rChnlShft=0; reg [9:0] rLen=0, _rLen=0; reg rWithData=0, _rWithData=0; wire [31:0] wReqData = {rReqData[7:0], rReqData[15:8], rReqData[23:16], rReqData[31:24]}; wire [C_PCI_DATA_WIDTH-1:0] wDataOut = {rDataOut[7:0], rDataOut[15:8], rDataOut[23:16], rDataOut[31:24]}; assign RX_DATA_READY = 1; assign ENG_RD_COMPLETE = rDataDone; // Handle servicing write & read memory requests in a separate state machine. rx_engine_req #( .C_NUM_CHNL(C_NUM_CHNL) ) rxEngReq ( .CLK(CLK), .RST(RST), .REQ_WR(REQ_WR), .REQ_WR_DONE(REQ_WR_DONE), .REQ_RD(REQ_RD), .REQ_RD_DONE(REQ_RD_DONE), .REQ_LEN(REQ_LEN), .REQ_ADDR(REQ_ADDR), .REQ_DATA(REQ_DATA), .REQ_BE(REQ_BE), .REQ_TC(REQ_TC), .REQ_TD(REQ_TD), .REQ_EP(REQ_EP), .REQ_ATTR(REQ_ATTR), .REQ_ID(REQ_ID), .REQ_TAG(REQ_TAG), .WEN(rReqWen), .RNW(rRNW), .LEN(rReqLen), .ADDR(rReqAddr), .DATA(wReqData), .BE(rBE), .TC(rTC), .TD(rTD), .EP(rEP), .ATTR(rAttr), .ID(rReqId), .TAG(rReqTag) ); // Handle reordering completion data. reorder_queue #( .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH), .C_NUM_CHNL(C_NUM_CHNL), .C_MAX_READ_REQ_BYTES(C_MAX_READ_REQ_BYTES), .C_TAG_WIDTH(C_TAG_WIDTH) ) reorderQueue ( .CLK(CLK), .RST(RST), .VALID(rDataValid), .DATA(wDataOut), .DATA_EN(rDataOutEn), .DATA_EN_COUNT(rDataOutCount), .DONE(rDataDone), .ERR(rDataErr), .TAG(rChnlShft[C_TAG_WIDTH-1:0]), .INT_TAG(INT_TAG), .INT_TAG_VALID(INT_TAG_VALID), .EXT_TAG(EXT_TAG), .EXT_TAG_VALID(EXT_TAG_VALID), .ENG_DATA(ENG_DATA), .MAIN_DATA_EN(MAIN_DATA_EN), .MAIN_DONE(MAIN_DONE), .MAIN_ERR(MAIN_ERR), .SG_RX_DATA_EN(SG_RX_DATA_EN), .SG_RX_DONE(SG_RX_DONE), .SG_RX_ERR(SG_RX_ERR), .SG_TX_DATA_EN(SG_TX_DATA_EN), .SG_TX_DONE(SG_TX_DONE), .SG_TX_ERR(SG_TX_ERR) ); // Handle receiving data from PCIe receive channel. wire wValid = (RX_DATA_VALID & !RX_TLP_ERROR_POISON); always @ (posedge CLK) begin rTrigger <= #1 (RST ? 3'd0 : _rTrigger); rValidIn <= #1 (RST ? 1'd0 : _rValidIn); rDataIn <= #1 _rDataIn; rLastIn <= #1 _rLastIn; rLenOneIn <= #1 _rLenOneIn; end always @ (*) begin _rDataIn = rDataIn; _rValidIn = rValidIn; _rLastIn = rLastIn; _rLenOneIn = rLenOneIn; _rTrigger = rTrigger; // Buffer the incoming data _rDataIn = RX_DATA; _rValidIn = (RX_DATA_VALID && !RX_TLP_ERROR_POISON); _rLastIn = RX_TLP_END_FLAG; _rLenOneIn = (RX_DATA[9:0] == 10'd1); // Direct the main FSM with what kind of packet this represents case (RX_DATA[30:24]) `FMT_RXENG32_RD32 : _rTrigger = 3'd1 & ({3{wValid}}); `FMT_RXENG32_RD64 : _rTrigger = 3'd1 & ({3{wValid}}); `FMT_RXENG32_WR32 : _rTrigger = 3'd2 & ({3{wValid}}); `FMT_RXENG32_WR64 : _rTrigger = 3'd2 & ({3{wValid}}); `FMT_RXENG32_CPL : _rTrigger = 3'd3 & ({3{wValid}}); `FMT_RXENG32_CPLD : _rTrigger = 3'd4 & ({3{wValid}}); default : _rTrigger = 3'd5 & ({3{wValid}}); endcase end // Handle receiving memory reads and writes. always @ (posedge CLK) begin rReqState <= #1 (RST ? `S_RXENG32_REQ_PARSE : _rReqState); rReqWen <= #1 (RST ? 1'd0 : _rReqWen); rRNW <= #1 _rRNW; rTC <= #1 _rTC; rTD <= #1 _rTD; rEP <= #1 _rEP; rAttr <= #1 _rAttr; rReqLen <= #1 _rReqLen; rReqId <= #1 _rReqId; rReqTag <= #1 _rReqTag; rBE <= #1 _rBE; r3DWHeader <= #1 _r3DWHeader; rReqData <= #1 _rReqData; rReqAddr <= #1 _rReqAddr; end always @ (*) begin _rReqState = rReqState; _rTC = rTC; _rTD = rTD; _rEP = rEP; _rAttr = rAttr; _rReqLen = rReqLen; _rReqId = rReqId; _rReqTag = rReqTag; _rBE = rBE; _r3DWHeader = r3DWHeader; _rReqData = rReqData; _rReqAddr = rReqAddr; _rReqWen = rReqWen; _rRNW = rRNW; case (rReqState) `S_RXENG32_REQ_PARSE : begin // Process DW0, DW1 _rTC = rDataIn[22:20]; _rTD = rDataIn[15]; _rEP = rDataIn[14]; _rAttr = rDataIn[13:12]; _rReqLen = rDataIn[9:0]; _r3DWHeader = !rDataIn[29]; _rRNW = (rTrigger == 3'd1); _rReqWen = 0; // Trigger only set if the packet is valid case (rTrigger) 3'd0 : _rReqState = rReqState; 3'd1 : _rReqState = (rLenOneIn ? `S_RXENG32_REQ_MEM_0 : `S_RXENG32_REQ_UNHANDLED); 3'd2 : _rReqState = (rLenOneIn ? `S_RXENG32_REQ_MEM_0 : `S_RXENG32_REQ_UNHANDLED); default : _rReqState = `S_RXENG32_REQ_UNHANDLED; endcase end `S_RXENG32_REQ_UNHANDLED : begin if (rValidIn & rLastIn) _rReqState = `S_RXENG32_REQ_PARSE; end `S_RXENG32_REQ_MEM_0 : begin _rReqId = rDataIn[31:16]; _rReqTag = rDataIn[15:8]; _rBE = rDataIn[3:0]; if (rValidIn) _rReqState = (rLastIn ? `S_RXENG32_REQ_PARSE : `S_RXENG32_REQ_MEM_1); end `S_RXENG32_REQ_MEM_1 : begin _rReqAddr = rDataIn[31:2]; _rReqWen = (rRNW & r3DWHeader & rValidIn & rLastIn); if (rValidIn) begin case ({rRNW, r3DWHeader, rLastIn}) 3'b000: _rReqState = `S_RXENG32_REQ_MEM_2; // 4DW Write 3'b010: _rReqState = `S_RXENG32_REQ_MEM_WR; // 3DW Write 3'b100: _rReqState = `S_RXENG32_REQ_MEM_2; // 4DW Read 3'b110: _rReqState = `S_RXENG32_REQ_UNHANDLED; 3'b111: _rReqState = `S_RXENG32_REQ_PARSE; // 3DW Read default: _rReqState = `S_RXENG32_REQ_PARSE; endcase end end `S_RXENG32_REQ_MEM_2 : begin _rReqAddr = rDataIn[31:2]; _rReqWen = (rRNW & rValidIn & rLastIn); if (rValidIn) begin case ({rRNW, rLastIn}) 2'b00: _rReqState = `S_RXENG32_REQ_MEM_WR; // 4DW Write 2'b01: _rReqState = `S_RXENG32_REQ_PARSE; 2'b10: _rReqState = `S_RXENG32_REQ_UNHANDLED; 2'b11: _rReqState = `S_RXENG32_REQ_PARSE; // 4DW Read endcase end end `S_RXENG32_REQ_MEM_WR : begin _rReqData = rDataIn[31:0]; _rReqWen = (rValidIn & rLastIn); if (rValidIn) _rReqState = (rLastIn ? `S_RXENG32_REQ_PARSE : `S_RXENG32_REQ_UNHANDLED); end default : begin _rReqState = `S_RXENG32_REQ_PARSE; end endcase end // When signaled, start processing the packet, handle cpls and cplds. always @ (posedge CLK) begin rCplState <= #1 (RST ? `S_RXENG32_CPL_PARSE : _rCplState); rDataOutEn <= #1 (RST ? 1'd0 : _rDataOutEn); rDataOutCount <= #1 (RST ? 1'd0 : _rDataOutCount); rDataDone <= #1 (RST ? 1'd0 : _rDataDone); rDataErr <= #1 (RST ? 1'd0 : _rDataErr); rDataValid <= #1 (RST ? 1'd0 : _rDataValid); rCplErr <= #1 _rCplErr; rLastCPLD <= #1 _rLastCPLD; rDataOut <= #1 _rDataOut; rChnlShft <= #1 _rChnlShft; rWithData <= #1 _rWithData; rLen <= #1 _rLen; end always @ (*) begin _rCplState = rCplState; _rCplErr = rCplErr; _rLastCPLD = rLastCPLD; _rDataOut = rDataOut; _rDataOutEn = rDataOutEn; _rDataOutCount = rDataOutCount; _rDataDone = rDataDone; _rDataErr = rDataErr; _rDataValid = rDataValid; _rChnlShft = rChnlShft; _rWithData = rWithData; _rLen = rLen; case (rCplState) `S_RXENG32_CPL_PARSE : begin // Process DW0, DW1 _rDataOutEn = 0; _rDataOutCount = 0; _rDataDone = 0; _rDataErr = 0; _rDataValid = 0; _rLen = rDataIn[9:0]; _rWithData = (rTrigger == 3'd4); // Trigger only set if the packet is valid case (rTrigger) 3'd0 : _rCplState = rCplState; 3'd3 : _rCplState = `S_RXENG32_CPL_0; 3'd4 : _rCplState = `S_RXENG32_CPL_0; default : _rCplState = `S_RXENG32_CPL_WAIT_FOR_END; endcase end `S_RXENG32_CPL_WAIT_FOR_END : begin // Wait until the end of the TLP _rDataOutEn = 0; _rDataOutCount = 0; _rDataDone = 0; _rDataErr = 0; _rDataValid = 0; if (rValidIn & rLastIn) _rCplState = `S_RXENG32_CPL_PARSE; end `S_RXENG32_CPL_0 : begin _rCplErr = (rDataIn[15:13] != 3'b000); // Completion status code _rLastCPLD = (rDataIn[11:0] == (rLen<<2)); // byte_count == length ? if (rValidIn) begin _rCplState = (rLastIn ? `S_RXENG32_CPL_PARSE : `S_RXENG32_CPL_1); end end `S_RXENG32_CPL_1 : begin _rChnlShft = rDataIn[15:8]; // Tag is [15:8] _rDataValid = rValidIn; if (rValidIn) begin _rDataErr = rCplErr; _rDataDone = (rCplErr | (rLastIn & rLastCPLD)); if (rLastIn) // Ends in this packet _rCplState = `S_RXENG32_CPL_PARSE; else if (rCplErr | !rWithData) // Bad completion code or just CPL _rCplState = `S_RXENG32_CPL_WAIT_FOR_END; else // Continues past this packet _rCplState = `S_RXENG32_CPL_DATA; end end `S_RXENG32_CPL_DATA : begin _rDataValid = rValidIn; _rDataOut = rDataIn; if (rValidIn) begin _rDataOutEn = 1; _rDataOutCount = 1; _rDataDone = (rLastIn & rLastCPLD); _rCplState = (rLastIn ? `S_RXENG32_CPL_PARSE : `S_RXENG32_CPL_DATA); end end default : begin _rCplState = `S_RXENG32_CPL_PARSE; end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/rx_engine_64.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: rx_engine_64.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Receive engine for PCIe using AXI interface from Xilinx // PCIe Endpoint core. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: Very good PCIe header reference: // http://www.pzk-agro.com/0321156307_ch04lev1sec5.html#ch04lev4sec14 // Also byte swap each payload word due to Xilinx incorrect mapping, see // http://forums.xilinx.com/t5/PCI-Express/PCI-Express-payload-required-to-be-Big-Endian-by-specification/td-p/285551 //----------------------------------------------------------------------------- `define FMT_RXENG64_RD32 7'b00_00000 `define FMT_RXENG64_WR32 7'b10_00000 `define FMT_RXENG64_RD64 7'b01_00000 `define FMT_RXENG64_WR64 7'b11_00000 `define FMT_RXENG64_CPL 7'b00_01010 `define FMT_RXENG64_CPLD 7'b10_01010 `define S_RXENG64_REQ_PARSE 3'd0 `define S_RXENG64_REQ_UNHANDLED 3'd1 `define S_RXENG64_REQ_MEM_RD_0 3'd2 `define S_RXENG64_REQ_MEM_WR_0 3'd3 `define S_RXENG64_REQ_MEM_WR_1 3'd4 `define S_RXENG64_CPL_PARSE 3'd0 `define S_RXENG64_CPL_WAIT_FOR_END 3'd1 `define S_RXENG64_CPL_NO_DATA 3'd2 `define S_RXENG64_CPL_DATA 3'd3 `define S_RXENG64_CPL_DATA_CONT 3'd4 module rx_engine_64 #( parameter C_PCI_DATA_WIDTH = 9'd64, parameter C_NUM_CHNL = 4'd12, parameter C_MAX_READ_REQ_BYTES = 512, // Max size of read requests (in bytes) parameter C_TAG_WIDTH = 5, // Number of outstanding requests parameter C_ALTERA = 1'b1, // 1 if Altera, 0 if Xilinx // Local parameters parameter C_PCI_DATA_WORD = C_PCI_DATA_WIDTH/32, parameter C_PCI_DATA_COUNT_WIDTH = clog2s(C_PCI_DATA_WORD+1) ) ( input CLK, input RST, // Receive input [C_PCI_DATA_WIDTH-1:0] RX_DATA, input [(C_PCI_DATA_WIDTH/8)-1:0] RX_DATA_BYTE_ENABLE, input RX_TLP_END_FLAG, input RX_DATA_VALID, output RX_DATA_READY, input RX_TLP_ERROR_POISON, // Received read/write memory requests output REQ_WR, // Memory write request input REQ_WR_DONE, // Memory write completed output REQ_RD, // Memory read request input REQ_RD_DONE, // Memory read complete output [9:0] REQ_LEN, // Memory length (1DW) output [29:0] REQ_ADDR, // Memory address (bottom 2 bits are always 00) output [31:0] REQ_DATA, // Memory write data output [3:0] REQ_BE, // Memory byte enables output [2:0] REQ_TC, // Memory traffic class output REQ_TD, // Memory packet digest output REQ_EP, // Memory poisoned packet output [1:0] REQ_ATTR, // Memory packet relaxed ordering, no snoop output [15:0] REQ_ID, // Memory requestor id output [7:0] REQ_TAG, // Memory packet tag // Tag exchange input [5:0] INT_TAG, // Internal tag to exchange with external input INT_TAG_VALID, // High to signal tag exchange output [C_TAG_WIDTH-1:0] EXT_TAG, // External tag to provide in exchange for internal tag output EXT_TAG_VALID, // High to signal external tag is valid // Received read completions output ENG_RD_COMPLETE, output [C_PCI_DATA_WIDTH-1:0] ENG_DATA, // Engine data output [(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)-1:0] MAIN_DATA_EN, // Main data enable output [C_NUM_CHNL-1:0] MAIN_DONE, // Main data complete output [C_NUM_CHNL-1:0] MAIN_ERR, // Main data completed with error output [(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)-1:0] SG_RX_DATA_EN, // Scatter gather for RX data enable output [C_NUM_CHNL-1:0] SG_RX_DONE, // Scatter gather for RX data complete output [C_NUM_CHNL-1:0] SG_RX_ERR, // Scatter gather for RX data completed with error output [(C_NUM_CHNL*C_PCI_DATA_COUNT_WIDTH)-1:0] SG_TX_DATA_EN, // Scatter gather for TX data enable output [C_NUM_CHNL-1:0] SG_TX_DONE, // Scatter gather for TX data complete output [C_NUM_CHNL-1:0] SG_TX_ERR // Scatter gather for TX data completed with error ); `include "common_functions.v" reg [2:0] rTrigger=0, _rTrigger=0; reg [C_PCI_DATA_WIDTH-1:0] rDataIn=0, _rDataIn=0; reg rValidIn=0, _rValidIn=0; reg rKeepBothIn=0, _rKeepBothIn=0; reg rLastIn=0, _rLastIn=0; reg rLenOneIn=0, _rLenOneIn=0; reg [2:0] rReqState=`S_RXENG64_REQ_PARSE, _rReqState=`S_RXENG64_REQ_PARSE; reg [29:0] rReqAddr=0, _rReqAddr=0; reg [31:0] rReqData=0, _rReqData=0; reg rReqWen=0, _rReqWen=0; reg rRNW=0, _rRNW=0; reg [3:0] rBE=0, _rBE=0; reg [2:0] rTC=0, _rTC=0; reg rTD=0, _rTD=0; reg rEP=0, _rEP=0; reg [1:0] rAttr=0, _rAttr=0; reg [9:0] rReqLen=0, _rReqLen=0; reg [15:0] rReqId=0, _rReqId=0; reg [7:0] rReqTag=0, _rReqTag=0; reg r3DWHeader=0, _r3DWHeader=0; reg [2:0] rCplState=`S_RXENG64_CPL_PARSE, _rCplState=`S_RXENG64_CPL_PARSE; reg rCplErr=0, _rCplErr=0; reg rLastCPLD=0, _rLastCPLD=0; reg [C_PCI_DATA_COUNT_WIDTH-1:0]rDataOutCount=0, _rDataOutCount=0; reg [C_PCI_DATA_WORD-1:0] rDataOutEn=0, _rDataOutEn=0; reg [C_PCI_DATA_WIDTH-1:0] rDataOut={C_PCI_DATA_WIDTH{1'b0}}, _rDataOut={C_PCI_DATA_WIDTH{1'b0}}; reg rDataDone=0, _rDataDone=0; reg rDataErr=0, _rDataErr=0; reg rDataValid=0, _rDataValid=0; reg [7:0] rChnlShft=0, _rChnlShft=0; reg rQWACpl,_rQWACpl; reg rQWAReq,_rQWAReq; wire wALTERA = C_ALTERA; wire [31:0] wReqData; wire [C_PCI_DATA_WIDTH-1:0] wDataOut; assign wReqData = wALTERA? rReqData :{rReqData[7:0], rReqData[15:8], rReqData[23:16], rReqData[31:24]}; assign wDataOut = wALTERA? rDataOut :{rDataOut[39:32], rDataOut[47:40], rDataOut[55:48], rDataOut[63:56], rDataOut[07:00], rDataOut[15:08], rDataOut[23:16], rDataOut[31:24]}; assign RX_DATA_READY = 1; assign ENG_RD_COMPLETE = rDataDone; // Handle servicing write & read memory requests in a separate state machine. rx_engine_req #( .C_NUM_CHNL(C_NUM_CHNL) ) rxEngReq ( .CLK(CLK), .RST(RST), .REQ_WR(REQ_WR), .REQ_WR_DONE(REQ_WR_DONE), .REQ_RD(REQ_RD), .REQ_RD_DONE(REQ_RD_DONE), .REQ_LEN(REQ_LEN), .REQ_ADDR(REQ_ADDR), .REQ_DATA(REQ_DATA), .REQ_BE(REQ_BE), .REQ_TC(REQ_TC), .REQ_TD(REQ_TD), .REQ_EP(REQ_EP), .REQ_ATTR(REQ_ATTR), .REQ_ID(REQ_ID), .REQ_TAG(REQ_TAG), .WEN(rReqWen), .RNW(rRNW), .LEN(rReqLen), .ADDR(rReqAddr), .DATA(wReqData), .BE(rBE), .TC(rTC), .TD(rTD), .EP(rEP), .ATTR(rAttr), .ID(rReqId), .TAG(rReqTag) ); // Handle reordering completion data. reorder_queue #( .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH), .C_NUM_CHNL(C_NUM_CHNL), .C_MAX_READ_REQ_BYTES(C_MAX_READ_REQ_BYTES), .C_TAG_WIDTH(C_TAG_WIDTH) ) reorderQueue ( .CLK(CLK), .RST(RST), .VALID(rDataValid), .DATA(wDataOut), .DATA_EN(rDataOutEn), .DATA_EN_COUNT(rDataOutCount), .DONE(rDataDone), .ERR(rDataErr), .TAG(rChnlShft[C_TAG_WIDTH-1:0]), .INT_TAG(INT_TAG), .INT_TAG_VALID(INT_TAG_VALID), .EXT_TAG(EXT_TAG), .EXT_TAG_VALID(EXT_TAG_VALID), .ENG_DATA(ENG_DATA), .MAIN_DATA_EN(MAIN_DATA_EN), .MAIN_DONE(MAIN_DONE), .MAIN_ERR(MAIN_ERR), .SG_RX_DATA_EN(SG_RX_DATA_EN), .SG_RX_DONE(SG_RX_DONE), .SG_RX_ERR(SG_RX_ERR), .SG_TX_DATA_EN(SG_TX_DATA_EN), .SG_TX_DONE(SG_TX_DONE), .SG_TX_ERR(SG_TX_ERR) ); // Handle receiving data from PCIe receive channel. wire wValid = (RX_DATA_VALID & !RX_TLP_ERROR_POISON); always @ (posedge CLK) begin rTrigger <= #1 (RST ? 3'd0 : _rTrigger); rValidIn <= #1 (RST ? 1'd0 : _rValidIn); rDataIn <= #1 _rDataIn; rKeepBothIn <= #1 _rKeepBothIn; rLastIn <= #1 _rLastIn; rLenOneIn <= #1 _rLenOneIn; rQWACpl <= #1 _rQWACpl; end always @ (*) begin _rDataIn = rDataIn; _rValidIn = rValidIn; _rKeepBothIn = rKeepBothIn; _rLastIn = rLastIn; _rLenOneIn = rLenOneIn; _rTrigger = rTrigger; _rQWACpl = rQWACpl; // Buffer the incoming data _rDataIn = RX_DATA; _rValidIn = (RX_DATA_VALID && !RX_TLP_ERROR_POISON); _rKeepBothIn = (RX_DATA_BYTE_ENABLE == 8'hFF); _rLastIn = RX_TLP_END_FLAG; _rLenOneIn = (RX_DATA[9:0] == 10'd1); _rQWACpl = ~RX_DATA[2]; // Direct the main FSM with what kind of packet this represents case (RX_DATA[30:24]) `FMT_RXENG64_RD32 : _rTrigger = 3'd1 & ({3{wValid}}); `FMT_RXENG64_RD64 : _rTrigger = 3'd1 & ({3{wValid}}); `FMT_RXENG64_WR32 : _rTrigger = 3'd2 & ({3{wValid}}); `FMT_RXENG64_WR64 : _rTrigger = 3'd2 & ({3{wValid}}); `FMT_RXENG64_CPL : _rTrigger = 3'd3 & ({3{wValid}}); `FMT_RXENG64_CPLD : _rTrigger = 3'd4 & ({3{wValid}}); default : _rTrigger = 3'd5 & ({3{wValid}}); endcase end // Handle receiving memory reads and writes. always @ (posedge CLK) begin rReqState <= #1 (RST ? `S_RXENG64_REQ_PARSE : _rReqState); rReqWen <= #1 (RST ? 1'd0 : _rReqWen); rRNW <= #1 _rRNW; rTC <= #1 _rTC; rTD <= #1 _rTD; rEP <= #1 _rEP; rAttr <= #1 _rAttr; rReqLen <= #1 _rReqLen; rReqId <= #1 _rReqId; rReqTag <= #1 _rReqTag; rBE <= #1 _rBE; r3DWHeader <= #1 _r3DWHeader; rReqData <= #1 _rReqData; rReqAddr <= #1 _rReqAddr; rQWAReq <= #1 _rQWAReq; end always @ (*) begin _rReqState = rReqState; _rTC = rTC; _rTD = rTD; _rEP = rEP; _rAttr = rAttr; _rReqLen = rReqLen; _rReqId = rReqId; _rReqTag = rReqTag; _rBE = rBE; _r3DWHeader = r3DWHeader; _rReqData = rReqData; _rReqAddr = rReqAddr; _rReqWen = rReqWen; _rRNW = rRNW; _rQWAReq = rQWAReq; case (rReqState) `S_RXENG64_REQ_PARSE : begin // Process DW0, DW1 _rTC = rDataIn[22:20]; _rTD = rDataIn[15]; _rEP = rDataIn[14]; _rAttr = rDataIn[13:12]; _rReqLen = rDataIn[9:0]; _rReqId = rDataIn[63:48]; _rReqTag = rDataIn[47:40]; _rBE = rDataIn[35:32]; _r3DWHeader = !rDataIn[29]; _rReqWen = 0; // Trigger only set if the packet is valid case (rTrigger) 3'd0 : _rReqState = rReqState; 3'd1 : _rReqState = (rLenOneIn ? `S_RXENG64_REQ_MEM_RD_0 : `S_RXENG64_REQ_UNHANDLED); 3'd2 : _rReqState = (rLenOneIn ? `S_RXENG64_REQ_MEM_WR_0 : `S_RXENG64_REQ_UNHANDLED); default : _rReqState = `S_RXENG64_REQ_UNHANDLED; endcase end `S_RXENG64_REQ_UNHANDLED : begin if (rValidIn & rLastIn) _rReqState = `S_RXENG64_REQ_PARSE; end `S_RXENG64_REQ_MEM_RD_0 : begin _rReqAddr = (r3DWHeader ? rDataIn[31:2] : rDataIn[63:34]); _rRNW = 1; _rReqWen = (rValidIn & rLastIn); if (rValidIn) _rReqState = (rLastIn ? `S_RXENG64_REQ_PARSE : `S_RXENG64_REQ_UNHANDLED); end `S_RXENG64_REQ_MEM_WR_0 : begin _rReqData = rDataIn[63:32]; _rReqAddr = (r3DWHeader ? rDataIn[31:2] : rDataIn[63:34]); _rQWAReq = (~rDataIn[2] & r3DWHeader) | (~r3DWHeader & ~rDataIn[34]); _rRNW = 0; _rReqWen = (rValidIn & rLastIn); if (rValidIn) begin _rReqState = (rLastIn ? `S_RXENG64_REQ_PARSE : `S_RXENG64_REQ_MEM_WR_1); end end `S_RXENG64_REQ_MEM_WR_1 : begin _rReqData = rDataIn >> ({5'd0,~(rQWAReq | (~wALTERA))} << 5); _rReqWen = (rValidIn & rLastIn); if (rValidIn) _rReqState = (rLastIn ? `S_RXENG64_REQ_PARSE : `S_RXENG64_REQ_UNHANDLED); end default : begin _rReqState = `S_RXENG64_REQ_PARSE; end endcase end // When signaled, start processing the packet, handle cpls and cplds. always @ (posedge CLK) begin rCplState <= #1 (RST ? `S_RXENG64_CPL_PARSE : _rCplState); rDataOutEn <= #1 (RST ? 2'd0 : _rDataOutEn); rDataOutCount <= #1 (RST ? 2'd0 : _rDataOutCount); rDataDone <= #1 (RST ? 1'd0 : _rDataDone); rDataErr <= #1 (RST ? 1'd0 : _rDataErr); rDataValid <= #1 (RST ? 1'd0 : _rDataValid); rCplErr <= #1 _rCplErr; rLastCPLD <= #1 _rLastCPLD; rDataOut <= #1 _rDataOut; rChnlShft <= #1 _rChnlShft; end always @ (*) begin _rCplState = rCplState; _rCplErr = rCplErr; _rLastCPLD = rLastCPLD; _rDataOut = rDataOut; _rDataOutEn = rDataOutEn; _rDataOutCount = rDataOutCount; _rDataDone = rDataDone; _rDataErr = rDataErr; _rDataValid = rDataValid; _rChnlShft = rChnlShft; case (rCplState) `S_RXENG64_CPL_PARSE : begin // Process DW0, DW1 _rDataOutEn = 0; _rDataOutCount = 0; _rDataDone = 0; _rDataErr = 0; _rDataValid = 0; _rCplErr = (rDataIn[47:45] != 3'b000); // Completion status code _rLastCPLD = (rDataIn[43:32] == (rDataIn[9:0]<<2)); // byte_count == length ? // Trigger only set if the packet is valid case (rTrigger) 3'd0 : _rCplState = rCplState; 3'd3 : _rCplState = `S_RXENG64_CPL_NO_DATA; 3'd4 : _rCplState = `S_RXENG64_CPL_DATA; default : _rCplState = `S_RXENG64_CPL_WAIT_FOR_END; endcase end `S_RXENG64_CPL_WAIT_FOR_END : begin // Wait until the end of the TLP _rDataOutEn = 0; _rDataOutCount = 0; _rDataDone = 0; _rDataErr = 0; _rDataValid = 0; if (rValidIn & rLastIn) _rCplState = `S_RXENG64_CPL_PARSE; end `S_RXENG64_CPL_NO_DATA : begin // Process DW2 _rChnlShft = rDataIn[15:8]; // Tag is [15:8] _rDataValid = rValidIn; if (rValidIn) begin _rDataOutEn = 0; _rDataOutCount = 0; _rDataErr = rCplErr; _rDataDone = 1; _rCplState = (rLastIn ? `S_RXENG64_CPL_PARSE : `S_RXENG64_CPL_WAIT_FOR_END); end end `S_RXENG64_CPL_DATA : begin // Process DW2, DW3 _rChnlShft = rDataIn[15:8]; // Tag is [15:8] _rDataValid = rValidIn; _rDataOut = (rDataIn>>32); if (rValidIn) begin _rDataOutEn = rKeepBothIn & (~rQWACpl | ~wALTERA); _rDataOutCount = rKeepBothIn & (~rQWACpl | ~wALTERA); _rDataDone = (rCplErr | (rLastIn & rLastCPLD)); _rDataErr = rCplErr; if (rLastIn) // Ends in this packet _rCplState = `S_RXENG64_CPL_PARSE; else if (rCplErr) // Bad completion code _rCplState = `S_RXENG64_CPL_WAIT_FOR_END; else // Continues past this packet, send 1 DW now _rCplState = `S_RXENG64_CPL_DATA_CONT; end end `S_RXENG64_CPL_DATA_CONT : begin // Process packet until end _rDataValid = rValidIn; _rDataOut = rDataIn; if (rValidIn) begin // Process and write until last packet _rDataOutEn = {(!rLastIn | rKeepBothIn), 1'b1}; _rDataOutCount = (2'd1<<(!rLastIn | rKeepBothIn)); _rDataDone = (rLastIn & rLastCPLD); _rDataErr = 0; _rCplState = (rLastIn ? `S_RXENG64_CPL_PARSE : `S_RXENG64_CPL_DATA_CONT); end end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/rx_engine_req.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: rx_engine_req.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Handles write and read memory requests for the rx_engine // by queuing them up and processing in a separate state machine. This allows // the rx_engine to process incoming TLPs at line rate. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: //----------------------------------------------------------------------------- `define S_RXENGREQ_IDLE 2'd0 `define S_RXENGREQ_PAUSE 2'd1 `define S_RXENGREQ_ASSIGN 2'd2 `define S_RXENGREQ_WAIT 2'd3 module rx_engine_req #( parameter C_NUM_CHNL = 4'd12, // Local parameters parameter C_FIFO_DEPTH = 6*C_NUM_CHNL, parameter C_WR_DATA_WIDTH = 30+32, // 62 parameter C_RD_DATA_WIDTH = 30+10+4+3+1+1+2+16+8, // 75 parameter C_FIFO_WIDTH = (C_WR_DATA_WIDTH > C_RD_DATA_WIDTH ? C_WR_DATA_WIDTH : C_RD_DATA_WIDTH) + 1 ) ( input CLK, input RST, // Received read/write memory requests output REQ_WR, // Memory write request input REQ_WR_DONE, // Memory write completed output REQ_RD, // Memory read request input REQ_RD_DONE, // Memory read complete output [9:0] REQ_LEN, // Memory length (1DW) output [29:0] REQ_ADDR, // Memory address (bottom 2 bits are always 00) output [31:0] REQ_DATA, // Memory write data output [3:0] REQ_BE, // Memory byte enables output [2:0] REQ_TC, // Memory traffic class output REQ_TD, // Memory packet digest output REQ_EP, // Memory poisoned packet output [1:0] REQ_ATTR, // Memory packet relaxed ordering, no snoop output [15:0] REQ_ID, // Memory requestor id output [7:0] REQ_TAG, // Memory packet tag // Memory requests input WEN, // Memory request write enable input RNW, // Memory read (not write) request input [9:0] LEN, // Memory length (1DW) input [29:0] ADDR, // Memory address (bottom 2 bits are always 00) input [31:0] DATA, // Memory write data input [3:0] BE, // Memory byte enables input [2:0] TC, // Memory traffic class input TD, // Memory packet digest input EP, // Memory poisoned packet input [1:0] ATTR, // Memory packet relaxed ordering, no snoop input [15:0] ID, // Memory requestor id input [7:0] TAG // Memory packet tag ); `include "common_functions.v" reg [1:0] rState=`S_RXENGREQ_IDLE, _rState=`S_RXENGREQ_IDLE; reg rRd=0, _rRd=0; reg rWr=0, _rWr=0; reg rRen=0, _rRen=0; reg [29:0] rAddr=0, _rAddr=0; reg [31:0] rData=0, _rData=0; reg [2:0] rTC=0, _rTC=0; reg rTD=0, _rTD=0; reg rEP=0, _rEP=0; reg [1:0] rAttr=0, _rAttr=0; reg [9:0] rLen=0, _rLen=0; reg [15:0] rId=0, _rId=0; reg [7:0] rTag=0, _rTag=0; reg [3:0] rBE=0, _rBE=0; wire wFifoEmpty; wire [C_FIFO_WIDTH-1:0] wDataOut; wire [C_FIFO_WIDTH-1:0] wDataIn = ({LEN, BE, TC, TD, EP, ATTR, ID, TAG, ADDR, RNW, DATA, RNW})>>(33*RNW); assign REQ_RD = rRd; assign REQ_WR = rWr; assign REQ_ADDR = rAddr; assign REQ_DATA = rData; assign REQ_BE = rBE; assign REQ_TC = rTC; assign REQ_TD = rTD; assign REQ_EP = rEP; assign REQ_ATTR = rAttr; assign REQ_LEN = rLen; assign REQ_ID = rId; assign REQ_TAG = rTag; // FIFO for storing data for read/write requests. (* RAM_STYLE="DISTRIBUTED" *) sync_fifo #(.C_WIDTH(C_FIFO_WIDTH), .C_DEPTH(C_FIFO_DEPTH)) fifo ( .RST(RST), .CLK(CLK), .WR_EN(WEN), .WR_DATA(wDataIn), .FULL(), .COUNT(), .RD_EN(rRen), .RD_DATA(wDataOut), .EMPTY(wFifoEmpty) ); // Process writes and reads when the FIFOs are not empty. This will always // process writes over reads. always @ (posedge CLK) begin rState <= #1 (RST ? `S_RXENGREQ_IDLE : _rState); rRd <= #1 (RST ? 1'd0 : _rRd); rWr <= #1 (RST ? 1'd0 : _rWr); rRen <= #1 (RST ? 1'd0 : _rRen); rAddr <= #1 _rAddr; rData <= #1 _rData; rLen <= #1 _rLen; rBE <= #1 _rBE; rTC <= #1 _rTC; rTD <= #1 _rTD; rEP <= #1 _rEP; rAttr <= #1 _rAttr; rId <= #1 _rId; rTag <= #1 _rTag; end always @ (*) begin _rState = rState; _rRd = rRd; _rWr = rWr; _rRen = rRen; _rAddr = rAddr; _rData = rData; _rLen = rLen; _rBE = rBE; _rTC = rTC; _rTD = rTD; _rEP = rEP; _rAttr = rAttr; _rId = rId; _rTag = rTag; case (rState) `S_RXENGREQ_IDLE: begin if (!wFifoEmpty) begin _rRen = 1; _rState = `S_RXENGREQ_PAUSE; end end `S_RXENGREQ_PAUSE: begin _rRen = 0; _rState = `S_RXENGREQ_ASSIGN; end `S_RXENGREQ_ASSIGN: begin _rWr = !wDataOut[0]; // !RNW _rRd = wDataOut[0]; // RNW if (wDataOut[0]) begin {_rLen, _rBE, _rTC, _rTD, _rEP, _rAttr, _rId, _rTag, _rAddr} = wDataOut[C_FIFO_WIDTH-1:1]; end else begin _rAddr = wDataOut[63:34]; _rData = wDataOut[32:1]; end _rState = `S_RXENGREQ_WAIT; end `S_RXENGREQ_WAIT: begin if (rWr & REQ_WR_DONE) begin _rWr = 0; _rState = `S_RXENGREQ_IDLE; end else if (rRd & REQ_RD_DONE) begin _rRd = 0; _rState = `S_RXENGREQ_IDLE; end end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/rx_port_128.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: rx_port_128.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Receives data from the rx_engine and buffers the output // for the RIFFA channel. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module rx_port_128 #( parameter C_DATA_WIDTH = 9'd128, parameter C_MAIN_FIFO_DEPTH = 1024, parameter C_SG_FIFO_DEPTH = 512, parameter C_MAX_READ_REQ = 2, // Max read: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B // Local parameters parameter C_DATA_WORD_WIDTH = clog2((C_DATA_WIDTH/32)+1), parameter C_MAIN_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_MAIN_FIFO_DEPTH))+1), parameter C_SG_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_SG_FIFO_DEPTH))+1) ) ( input CLK, input RST, input [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // Maximum read payload: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B output SG_RX_BUF_RECVD, // Scatter gather RX buffer completely read (ready for next if applicable) input [31:0] SG_RX_BUF_DATA, // Scatter gather RX buffer data input SG_RX_BUF_LEN_VALID, // Scatter gather RX buffer length valid input SG_RX_BUF_ADDR_HI_VALID, // Scatter gather RX buffer high address valid input SG_RX_BUF_ADDR_LO_VALID, // Scatter gather RX buffer low address valid output SG_TX_BUF_RECVD, // Scatter gather TX buffer completely read (ready for next if applicable) input [31:0] SG_TX_BUF_DATA, // Scatter gather TX buffer data input SG_TX_BUF_LEN_VALID, // Scatter gather TX buffer length valid input SG_TX_BUF_ADDR_HI_VALID, // Scatter gather TX buffer high address valid input SG_TX_BUF_ADDR_LO_VALID, // Scatter gather TX buffer low address valid output [C_DATA_WIDTH-1:0] SG_DATA, // Scatter gather TX buffer data output SG_DATA_EMPTY, // Scatter gather TX buffer data empty input SG_DATA_REN, // Scatter gather TX buffer data read enable input SG_RST, // Scatter gather TX buffer data reset output SG_ERR, // Scatter gather TX encountered an error input [31:0] TXN_DATA, // Read transaction data input TXN_LEN_VALID, // Read transaction length valid input TXN_OFF_LAST_VALID, // Read transaction offset/last valid output [31:0] TXN_DONE_LEN, // Read transaction actual transfer length output TXN_DONE, // Read transaction done input TXN_DONE_ACK, // Read transaction actual transfer length read output RX_REQ, // Read request input RX_REQ_ACK, // Read request accepted output [1:0] RX_REQ_TAG, // Read request data tag output [63:0] RX_REQ_ADDR, // Read request address output [9:0] RX_REQ_LEN, // Read request length input [C_DATA_WIDTH-1:0] MAIN_DATA, // Main incoming data input [C_DATA_WORD_WIDTH-1:0] MAIN_DATA_EN, // Main incoming data enable input MAIN_DONE, // Main incoming data complete input MAIN_ERR, // Main incoming data completed with error input [C_DATA_WIDTH-1:0] SG_RX_DATA, // Scatter gather for RX incoming data input [C_DATA_WORD_WIDTH-1:0] SG_RX_DATA_EN, // Scatter gather for RX incoming data enable input SG_RX_DONE, // Scatter gather for RX incoming data complete input SG_RX_ERR, // Scatter gather for RX incoming data completed with error input [C_DATA_WIDTH-1:0] SG_TX_DATA, // Scatter gather for TX incoming data input [C_DATA_WORD_WIDTH-1:0] SG_TX_DATA_EN, // Scatter gather for TX incoming data enable input SG_TX_DONE, // Scatter gather for TX incoming data complete input SG_TX_ERR, // Scatter gather for TX incoming data completed with error input CHNL_CLK, // Channel read clock output CHNL_RX, // Channel read receive signal input CHNL_RX_ACK, // Channle read received signal output CHNL_RX_LAST, // Channel last read output [31:0] CHNL_RX_LEN, // Channel read length output [30:0] CHNL_RX_OFF, // Channel read offset output [C_DATA_WIDTH-1:0] CHNL_RX_DATA, // Channel read data output CHNL_RX_DATA_VALID, // Channel read data valid input CHNL_RX_DATA_REN // Channel read data has been recieved ); `include "common_functions.v" assign SG_ERR = (wPackedSgTxDone & wPackedSgTxErr); wire [C_DATA_WIDTH-1:0] wPackedMainData; wire wPackedMainWen; wire wPackedMainDone; wire wPackedMainErr; wire wMainFlush; wire wMainFlushed; wire [C_DATA_WIDTH-1:0] wPackedSgRxData; wire wPackedSgRxWen; wire wPackedSgRxDone; wire wPackedSgRxErr; wire wSgRxFlush; wire wSgRxFlushed; wire [C_DATA_WIDTH-1:0] wPackedSgTxData; wire wPackedSgTxWen; wire wPackedSgTxDone; wire wPackedSgTxErr; wire wSgTxFlush; wire wSgTxFlushed; wire wMainDataRen; wire wMainDataEmpty; wire [C_DATA_WIDTH-1:0] wMainData; wire wSgRxRst; wire wSgRxDataRen; wire wSgRxDataEmpty; wire [C_DATA_WIDTH-1:0] wSgRxData; wire [C_SG_FIFO_DEPTH_WIDTH-1:0] wSgRxFifoCount; wire wSgTxRst; wire [C_SG_FIFO_DEPTH_WIDTH-1:0] wSgTxFifoCount; wire wSgRxReq; wire [63:0] wSgRxReqAddr; wire [9:0] wSgRxReqLen; wire wSgTxReq; wire [63:0] wSgTxReqAddr; wire [9:0] wSgTxReqLen; wire wSgRxReqProc; wire wSgTxReqProc; wire wMainReqProc; wire wReqAck; wire wSgElemRdy; wire wSgElemRen; wire [63:0] wSgElemAddr; wire [31:0] wSgElemLen; wire wSgRst; wire wMainReq; wire [63:0] wMainReqAddr; wire [9:0] wMainReqLen; wire wTxnErr; wire wChnlRx; wire wChnlRxRecvd; wire wChnlRxAckRecvd; wire wChnlRxLast; wire [31:0] wChnlRxLen; wire [30:0] wChnlRxOff; wire [31:0] wChnlRxConsumed; reg [4:0] rWideRst=0; reg rRst=0; // Generate a wide reset from the input reset. always @ (posedge CLK) begin rRst <= #1 rWideRst[4]; if (RST) rWideRst <= #1 5'b11111; else rWideRst <= (rWideRst<<1); end // Pack received data tightly into our FIFOs fifo_packer_128 mainFifoPacker ( .CLK(CLK), .RST(rRst), .DATA_IN(MAIN_DATA), .DATA_IN_EN(MAIN_DATA_EN), .DATA_IN_DONE(MAIN_DONE), .DATA_IN_ERR(MAIN_ERR), .DATA_IN_FLUSH(wMainFlush), .PACKED_DATA(wPackedMainData), .PACKED_WEN(wPackedMainWen), .PACKED_DATA_DONE(wPackedMainDone), .PACKED_DATA_ERR(wPackedMainErr), .PACKED_DATA_FLUSHED(wMainFlushed) ); fifo_packer_128 sgRxFifoPacker ( .CLK(CLK), .RST(rRst), .DATA_IN(SG_RX_DATA), .DATA_IN_EN(SG_RX_DATA_EN), .DATA_IN_DONE(SG_RX_DONE), .DATA_IN_ERR(SG_RX_ERR), .DATA_IN_FLUSH(wSgRxFlush), .PACKED_DATA(wPackedSgRxData), .PACKED_WEN(wPackedSgRxWen), .PACKED_DATA_DONE(wPackedSgRxDone), .PACKED_DATA_ERR(wPackedSgRxErr), .PACKED_DATA_FLUSHED(wSgRxFlushed) ); fifo_packer_128 sgTxFifoPacker ( .CLK(CLK), .RST(rRst), .DATA_IN(SG_TX_DATA), .DATA_IN_EN(SG_TX_DATA_EN), .DATA_IN_DONE(SG_TX_DONE), .DATA_IN_ERR(SG_TX_ERR), .DATA_IN_FLUSH(wSgTxFlush), .PACKED_DATA(wPackedSgTxData), .PACKED_WEN(wPackedSgTxWen), .PACKED_DATA_DONE(wPackedSgTxDone), .PACKED_DATA_ERR(wPackedSgTxErr), .PACKED_DATA_FLUSHED(wSgTxFlushed) ); // FIFOs for storing received data for the channel. (* RAM_STYLE="BLOCK" *) async_fifo_fwft #(.C_WIDTH(C_DATA_WIDTH), .C_DEPTH(C_MAIN_FIFO_DEPTH)) mainFifo ( .WR_CLK(CLK), .WR_RST(rRst | (wTxnErr & TXN_DONE) | wSgRst), .WR_EN(wPackedMainWen), .WR_DATA(wPackedMainData), .WR_FULL(), .RD_CLK(CHNL_CLK), .RD_RST(rRst | (wTxnErr & TXN_DONE) | wSgRst), .RD_EN(wMainDataRen), .RD_DATA(wMainData), .RD_EMPTY(wMainDataEmpty) ); (* RAM_STYLE="BLOCK" *) sync_fifo #(.C_WIDTH(C_DATA_WIDTH), .C_DEPTH(C_SG_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) sgRxFifo ( .RST(rRst | wSgRxRst), .CLK(CLK), .WR_EN(wPackedSgRxWen), .WR_DATA(wPackedSgRxData), .FULL(), .RD_EN(wSgRxDataRen), .RD_DATA(wSgRxData), .EMPTY(wSgRxDataEmpty), .COUNT(wSgRxFifoCount) ); (* RAM_STYLE="BLOCK" *) sync_fifo #(.C_WIDTH(C_DATA_WIDTH), .C_DEPTH(C_SG_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) sgTxFifo ( .RST(rRst | wSgTxRst), .CLK(CLK), .WR_EN(wPackedSgTxWen), .WR_DATA(wPackedSgTxData), .FULL(), .RD_EN(SG_DATA_REN), .RD_DATA(SG_DATA), .EMPTY(SG_DATA_EMPTY), .COUNT(wSgTxFifoCount) ); // Manage requesting and acknowledging scatter gather data. Note that // these modules will share the main requestor's RX channel. They will // take priority over the main logic's use of the RX channel. sg_list_requester #(.C_FIFO_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_SG_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ)) sgRxReq ( .CLK(CLK), .RST(rRst), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE), .USER_RST(wSgRst), .BUF_RECVD(SG_RX_BUF_RECVD), .BUF_DATA(SG_RX_BUF_DATA), .BUF_LEN_VALID(SG_RX_BUF_LEN_VALID), .BUF_ADDR_HI_VALID(SG_RX_BUF_ADDR_HI_VALID), .BUF_ADDR_LO_VALID(SG_RX_BUF_ADDR_LO_VALID), .FIFO_COUNT(wSgRxFifoCount), .FIFO_FLUSH(wSgRxFlush), .FIFO_FLUSHED(wSgRxFlushed), .FIFO_RST(wSgRxRst), .RX_REQ(wSgRxReq), .RX_ADDR(wSgRxReqAddr), .RX_LEN(wSgRxReqLen), .RX_REQ_ACK(wReqAck & wSgRxReqProc), .RX_DONE(wPackedSgRxDone) ); sg_list_requester #(.C_FIFO_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_SG_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ)) sgTxReq ( .CLK(CLK), .RST(rRst), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE), .USER_RST(SG_RST), .BUF_RECVD(SG_TX_BUF_RECVD), .BUF_DATA(SG_TX_BUF_DATA), .BUF_LEN_VALID(SG_TX_BUF_LEN_VALID), .BUF_ADDR_HI_VALID(SG_TX_BUF_ADDR_HI_VALID), .BUF_ADDR_LO_VALID(SG_TX_BUF_ADDR_LO_VALID), .FIFO_COUNT(wSgTxFifoCount), .FIFO_FLUSH(wSgTxFlush), .FIFO_FLUSHED(wSgTxFlushed), .FIFO_RST(wSgTxRst), .RX_REQ(wSgTxReq), .RX_ADDR(wSgTxReqAddr), .RX_LEN(wSgTxReqLen), .RX_REQ_ACK(wReqAck & wSgTxReqProc), .RX_DONE(wPackedSgTxDone) ); // A read requester for the channel and scatter gather requesters. rx_port_requester_mux requesterMux ( .RST(rRst), .CLK(CLK), .SG_RX_REQ(wSgRxReq), .SG_RX_LEN(wSgRxReqLen), .SG_RX_ADDR(wSgRxReqAddr), .SG_RX_REQ_PROC(wSgRxReqProc), .SG_TX_REQ(wSgTxReq), .SG_TX_LEN(wSgTxReqLen), .SG_TX_ADDR(wSgTxReqAddr), .SG_TX_REQ_PROC(wSgTxReqProc), .MAIN_REQ(wMainReq), .MAIN_LEN(wMainReqLen), .MAIN_ADDR(wMainReqAddr), .MAIN_REQ_PROC(wMainReqProc), .RX_REQ(RX_REQ), .RX_REQ_ACK(RX_REQ_ACK), .RX_REQ_TAG(RX_REQ_TAG), .RX_REQ_ADDR(RX_REQ_ADDR), .RX_REQ_LEN(RX_REQ_LEN), .REQ_ACK(wReqAck) ); // Read the scatter gather buffer address and length, continuously so that // we have it ready whenever the next buffer is needed. sg_list_reader_128 #(.C_DATA_WIDTH(C_DATA_WIDTH)) sgListReader ( .CLK(CLK), .RST(rRst | wSgRst), .BUF_DATA(wSgRxData), .BUF_DATA_EMPTY(wSgRxDataEmpty), .BUF_DATA_REN(wSgRxDataRen), .VALID(wSgElemRdy), .EMPTY(), .REN(wSgElemRen), .ADDR(wSgElemAddr), .LEN(wSgElemLen) ); // Main port reader logic rx_port_reader #(.C_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_MAIN_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ)) reader ( .CLK(CLK), .RST(rRst), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE), .TXN_DATA(TXN_DATA), .TXN_LEN_VALID(TXN_LEN_VALID), .TXN_OFF_LAST_VALID(TXN_OFF_LAST_VALID), .TXN_DONE_LEN(TXN_DONE_LEN), .TXN_DONE(TXN_DONE), .TXN_ERR(wTxnErr), .TXN_DONE_ACK(TXN_DONE_ACK), .TXN_DATA_FLUSH(wMainFlush), .TXN_DATA_FLUSHED(wMainFlushed), .RX_REQ(wMainReq), .RX_ADDR(wMainReqAddr), .RX_LEN(wMainReqLen), .RX_REQ_ACK(wReqAck & wMainReqProc), .RX_DATA_EN(MAIN_DATA_EN), .RX_DONE(wPackedMainDone), .RX_ERR(wPackedMainErr), .SG_DONE(wPackedSgRxDone), .SG_ERR(wPackedSgRxErr), .SG_ELEM_ADDR(wSgElemAddr), .SG_ELEM_LEN(wSgElemLen), .SG_ELEM_RDY(wSgElemRdy), .SG_ELEM_REN(wSgElemRen), .SG_RST(wSgRst), .CHNL_RX(wChnlRx), .CHNL_RX_LEN(wChnlRxLen), .CHNL_RX_LAST(wChnlRxLast), .CHNL_RX_OFF(wChnlRxOff), .CHNL_RX_RECVD(wChnlRxRecvd), .CHNL_RX_ACK_RECVD(wChnlRxAckRecvd), .CHNL_RX_CONSUMED(wChnlRxConsumed) ); // Manage the CHNL_RX* signals in the CHNL_CLK domain. rx_port_channel_gate #(.C_DATA_WIDTH(C_DATA_WIDTH)) gate ( .RST(rRst), .CLK(CLK), .RX(wChnlRx), .RX_RECVD(wChnlRxRecvd), .RX_ACK_RECVD(wChnlRxAckRecvd), .RX_LAST(wChnlRxLast), .RX_LEN(wChnlRxLen), .RX_OFF(wChnlRxOff), .RX_CONSUMED(wChnlRxConsumed), .RD_DATA(wMainData), .RD_EMPTY(wMainDataEmpty), .RD_EN(wMainDataRen), .CHNL_CLK(CHNL_CLK), .CHNL_RX(CHNL_RX), .CHNL_RX_ACK(CHNL_RX_ACK), .CHNL_RX_LAST(CHNL_RX_LAST), .CHNL_RX_LEN(CHNL_RX_LEN), .CHNL_RX_OFF(CHNL_RX_OFF), .CHNL_RX_DATA(CHNL_RX_DATA), .CHNL_RX_DATA_VALID(CHNL_RX_DATA_VALID), .CHNL_RX_DATA_REN(CHNL_RX_DATA_REN) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/rx_port_32.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: rx_port_32.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Receives data from the rx_engine and buffers the output // for the RIFFA channel. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module rx_port_32 #( parameter C_DATA_WIDTH = 9'd32, parameter C_MAIN_FIFO_DEPTH = 1024, parameter C_SG_FIFO_DEPTH = 512, parameter C_MAX_READ_REQ = 2, // Max read: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B // Local parameters parameter C_DATA_WORD_WIDTH = clog2((C_DATA_WIDTH/32)+1), parameter C_MAIN_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_MAIN_FIFO_DEPTH))+1), parameter C_SG_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_SG_FIFO_DEPTH))+1) ) ( input CLK, input RST, input [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // Maximum read payload: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B output SG_RX_BUF_RECVD, // Scatter gather RX buffer completely read (ready for next if applicable) input [31:0] SG_RX_BUF_DATA, // Scatter gather RX buffer data input SG_RX_BUF_LEN_VALID, // Scatter gather RX buffer length valid input SG_RX_BUF_ADDR_HI_VALID, // Scatter gather RX buffer high address valid input SG_RX_BUF_ADDR_LO_VALID, // Scatter gather RX buffer low address valid output SG_TX_BUF_RECVD, // Scatter gather TX buffer completely read (ready for next if applicable) input [31:0] SG_TX_BUF_DATA, // Scatter gather TX buffer data input SG_TX_BUF_LEN_VALID, // Scatter gather TX buffer length valid input SG_TX_BUF_ADDR_HI_VALID, // Scatter gather TX buffer high address valid input SG_TX_BUF_ADDR_LO_VALID, // Scatter gather TX buffer low address valid output [C_DATA_WIDTH-1:0] SG_DATA, // Scatter gather TX buffer data output SG_DATA_EMPTY, // Scatter gather TX buffer data empty input SG_DATA_REN, // Scatter gather TX buffer data read enable input SG_RST, // Scatter gather TX buffer data reset output SG_ERR, // Scatter gather TX encountered an error input [31:0] TXN_DATA, // Read transaction data input TXN_LEN_VALID, // Read transaction length valid input TXN_OFF_LAST_VALID, // Read transaction offset/last valid output [31:0] TXN_DONE_LEN, // Read transaction actual transfer length output TXN_DONE, // Read transaction done input TXN_DONE_ACK, // Read transaction actual transfer length read output RX_REQ, // Read request input RX_REQ_ACK, // Read request accepted output [1:0] RX_REQ_TAG, // Read request data tag output [63:0] RX_REQ_ADDR, // Read request address output [9:0] RX_REQ_LEN, // Read request length input [C_DATA_WIDTH-1:0] MAIN_DATA, // Main incoming data input [C_DATA_WORD_WIDTH-1:0] MAIN_DATA_EN, // Main incoming data enable input MAIN_DONE, // Main incoming data complete input MAIN_ERR, // Main incoming data completed with error input [C_DATA_WIDTH-1:0] SG_RX_DATA, // Scatter gather for RX incoming data input [C_DATA_WORD_WIDTH-1:0] SG_RX_DATA_EN, // Scatter gather for RX incoming data enable input SG_RX_DONE, // Scatter gather for RX incoming data complete input SG_RX_ERR, // Scatter gather for RX incoming data completed with error input [C_DATA_WIDTH-1:0] SG_TX_DATA, // Scatter gather for TX incoming data input [C_DATA_WORD_WIDTH-1:0] SG_TX_DATA_EN, // Scatter gather for TX incoming data enable input SG_TX_DONE, // Scatter gather for TX incoming data complete input SG_TX_ERR, // Scatter gather for TX incoming data completed with error input CHNL_CLK, // Channel read clock output CHNL_RX, // Channel read receive signal input CHNL_RX_ACK, // Channle read received signal output CHNL_RX_LAST, // Channel last read output [31:0] CHNL_RX_LEN, // Channel read length output [30:0] CHNL_RX_OFF, // Channel read offset output [C_DATA_WIDTH-1:0] CHNL_RX_DATA, // Channel read data output CHNL_RX_DATA_VALID, // Channel read data valid input CHNL_RX_DATA_REN // Channel read data has been recieved ); `include "common_functions.v" assign SG_ERR = (wPackedSgTxDone & wPackedSgTxErr); wire [C_DATA_WIDTH-1:0] wPackedMainData; wire wPackedMainWen; wire wPackedMainDone; wire wPackedMainErr; wire wMainFlush; wire wMainFlushed; wire [C_DATA_WIDTH-1:0] wPackedSgRxData; wire wPackedSgRxWen; wire wPackedSgRxDone; wire wPackedSgRxErr; wire wSgRxFlush; wire wSgRxFlushed; wire [C_DATA_WIDTH-1:0] wPackedSgTxData; wire wPackedSgTxWen; wire wPackedSgTxDone; wire wPackedSgTxErr; wire wSgTxFlush; wire wSgTxFlushed; wire wMainDataRen; wire wMainDataEmpty; wire [C_DATA_WIDTH-1:0] wMainData; wire wSgRxRst; wire wSgRxDataRen; wire wSgRxDataEmpty; wire [C_DATA_WIDTH-1:0] wSgRxData; wire [C_SG_FIFO_DEPTH_WIDTH-1:0] wSgRxFifoCount; wire wSgTxRst; wire [C_SG_FIFO_DEPTH_WIDTH-1:0] wSgTxFifoCount; wire wSgRxReq; wire [63:0] wSgRxReqAddr; wire [9:0] wSgRxReqLen; wire wSgTxReq; wire [63:0] wSgTxReqAddr; wire [9:0] wSgTxReqLen; wire wSgRxReqProc; wire wSgTxReqProc; wire wMainReqProc; wire wReqAck; wire wSgElemRdy; wire wSgElemRen; wire [63:0] wSgElemAddr; wire [31:0] wSgElemLen; wire wSgRst; wire wMainReq; wire [63:0] wMainReqAddr; wire [9:0] wMainReqLen; wire wTxnErr; wire wChnlRx; wire wChnlRxRecvd; wire wChnlRxAckRecvd; wire wChnlRxLast; wire [31:0] wChnlRxLen; wire [30:0] wChnlRxOff; wire [31:0] wChnlRxConsumed; reg [4:0] rWideRst=0; reg rRst=0; // Generate a wide reset from the input reset. always @ (posedge CLK) begin rRst <= #1 rWideRst[4]; if (RST) rWideRst <= #1 5'b11111; else rWideRst <= (rWideRst<<1); end // Pack received data tightly into our FIFOs fifo_packer_32 mainFifoPacker ( .CLK(CLK), .RST(rRst), .DATA_IN(MAIN_DATA), .DATA_IN_EN(MAIN_DATA_EN), .DATA_IN_DONE(MAIN_DONE), .DATA_IN_ERR(MAIN_ERR), .DATA_IN_FLUSH(wMainFlush), .PACKED_DATA(wPackedMainData), .PACKED_WEN(wPackedMainWen), .PACKED_DATA_DONE(wPackedMainDone), .PACKED_DATA_ERR(wPackedMainErr), .PACKED_DATA_FLUSHED(wMainFlushed) ); fifo_packer_32 sgRxFifoPacker ( .CLK(CLK), .RST(rRst), .DATA_IN(SG_RX_DATA), .DATA_IN_EN(SG_RX_DATA_EN), .DATA_IN_DONE(SG_RX_DONE), .DATA_IN_ERR(SG_RX_ERR), .DATA_IN_FLUSH(wSgRxFlush), .PACKED_DATA(wPackedSgRxData), .PACKED_WEN(wPackedSgRxWen), .PACKED_DATA_DONE(wPackedSgRxDone), .PACKED_DATA_ERR(wPackedSgRxErr), .PACKED_DATA_FLUSHED(wSgRxFlushed) ); fifo_packer_32 sgTxFifoPacker ( .CLK(CLK), .RST(rRst), .DATA_IN(SG_TX_DATA), .DATA_IN_EN(SG_TX_DATA_EN), .DATA_IN_DONE(SG_TX_DONE), .DATA_IN_ERR(SG_TX_ERR), .DATA_IN_FLUSH(wSgTxFlush), .PACKED_DATA(wPackedSgTxData), .PACKED_WEN(wPackedSgTxWen), .PACKED_DATA_DONE(wPackedSgTxDone), .PACKED_DATA_ERR(wPackedSgTxErr), .PACKED_DATA_FLUSHED(wSgTxFlushed) ); // FIFOs for storing received data for the channel. (* RAM_STYLE="BLOCK" *) async_fifo_fwft #(.C_WIDTH(C_DATA_WIDTH), .C_DEPTH(C_MAIN_FIFO_DEPTH)) mainFifo ( .WR_CLK(CLK), .WR_RST(rRst | (wTxnErr & TXN_DONE) | wSgRst), .WR_EN(wPackedMainWen), .WR_DATA(wPackedMainData), .WR_FULL(), .RD_CLK(CHNL_CLK), .RD_RST(rRst | (wTxnErr & TXN_DONE) | wSgRst), .RD_EN(wMainDataRen), .RD_DATA(wMainData), .RD_EMPTY(wMainDataEmpty) ); (* RAM_STYLE="BLOCK" *) sync_fifo #(.C_WIDTH(C_DATA_WIDTH), .C_DEPTH(C_SG_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) sgRxFifo ( .RST(rRst | wSgRxRst), .CLK(CLK), .WR_EN(wPackedSgRxWen), .WR_DATA(wPackedSgRxData), .FULL(), .RD_EN(wSgRxDataRen), .RD_DATA(wSgRxData), .EMPTY(wSgRxDataEmpty), .COUNT(wSgRxFifoCount) ); (* RAM_STYLE="BLOCK" *) sync_fifo #(.C_WIDTH(C_DATA_WIDTH), .C_DEPTH(C_SG_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) sgTxFifo ( .RST(rRst | wSgTxRst), .CLK(CLK), .WR_EN(wPackedSgTxWen), .WR_DATA(wPackedSgTxData), .FULL(), .RD_EN(SG_DATA_REN), .RD_DATA(SG_DATA), .EMPTY(SG_DATA_EMPTY), .COUNT(wSgTxFifoCount) ); // Manage requesting and acknowledging scatter gather data. Note that // these modules will share the main requestor's RX channel. They will // take priority over the main logic's use of the RX channel. sg_list_requester #(.C_FIFO_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_SG_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ)) sgRxReq ( .CLK(CLK), .RST(rRst), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE), .USER_RST(wSgRst), .BUF_RECVD(SG_RX_BUF_RECVD), .BUF_DATA(SG_RX_BUF_DATA), .BUF_LEN_VALID(SG_RX_BUF_LEN_VALID), .BUF_ADDR_HI_VALID(SG_RX_BUF_ADDR_HI_VALID), .BUF_ADDR_LO_VALID(SG_RX_BUF_ADDR_LO_VALID), .FIFO_COUNT(wSgRxFifoCount), .FIFO_FLUSH(wSgRxFlush), .FIFO_FLUSHED(wSgRxFlushed), .FIFO_RST(wSgRxRst), .RX_REQ(wSgRxReq), .RX_ADDR(wSgRxReqAddr), .RX_LEN(wSgRxReqLen), .RX_REQ_ACK(wReqAck & wSgRxReqProc), .RX_DONE(wPackedSgRxDone) ); sg_list_requester #(.C_FIFO_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_SG_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ)) sgTxReq ( .CLK(CLK), .RST(rRst), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE), .USER_RST(SG_RST), .BUF_RECVD(SG_TX_BUF_RECVD), .BUF_DATA(SG_TX_BUF_DATA), .BUF_LEN_VALID(SG_TX_BUF_LEN_VALID), .BUF_ADDR_HI_VALID(SG_TX_BUF_ADDR_HI_VALID), .BUF_ADDR_LO_VALID(SG_TX_BUF_ADDR_LO_VALID), .FIFO_COUNT(wSgTxFifoCount), .FIFO_FLUSH(wSgTxFlush), .FIFO_FLUSHED(wSgTxFlushed), .FIFO_RST(wSgTxRst), .RX_REQ(wSgTxReq), .RX_ADDR(wSgTxReqAddr), .RX_LEN(wSgTxReqLen), .RX_REQ_ACK(wReqAck & wSgTxReqProc), .RX_DONE(wPackedSgTxDone) ); // A read requester for the channel and scatter gather requesters. rx_port_requester_mux requesterMux ( .RST(rRst), .CLK(CLK), .SG_RX_REQ(wSgRxReq), .SG_RX_LEN(wSgRxReqLen), .SG_RX_ADDR(wSgRxReqAddr), .SG_RX_REQ_PROC(wSgRxReqProc), .SG_TX_REQ(wSgTxReq), .SG_TX_LEN(wSgTxReqLen), .SG_TX_ADDR(wSgTxReqAddr), .SG_TX_REQ_PROC(wSgTxReqProc), .MAIN_REQ(wMainReq), .MAIN_LEN(wMainReqLen), .MAIN_ADDR(wMainReqAddr), .MAIN_REQ_PROC(wMainReqProc), .RX_REQ(RX_REQ), .RX_REQ_ACK(RX_REQ_ACK), .RX_REQ_TAG(RX_REQ_TAG), .RX_REQ_ADDR(RX_REQ_ADDR), .RX_REQ_LEN(RX_REQ_LEN), .REQ_ACK(wReqAck) ); // Read the scatter gather buffer address and length, continuously so that // we have it ready whenever the next buffer is needed. sg_list_reader_32 #(.C_DATA_WIDTH(C_DATA_WIDTH)) sgListReader ( .CLK(CLK), .RST(rRst | wSgRst), .BUF_DATA(wSgRxData), .BUF_DATA_EMPTY(wSgRxDataEmpty), .BUF_DATA_REN(wSgRxDataRen), .VALID(wSgElemRdy), .EMPTY(), .REN(wSgElemRen), .ADDR(wSgElemAddr), .LEN(wSgElemLen) ); // Main port reader logic rx_port_reader #(.C_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_MAIN_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ)) reader ( .CLK(CLK), .RST(rRst), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE), .TXN_DATA(TXN_DATA), .TXN_LEN_VALID(TXN_LEN_VALID), .TXN_OFF_LAST_VALID(TXN_OFF_LAST_VALID), .TXN_DONE_LEN(TXN_DONE_LEN), .TXN_DONE(TXN_DONE), .TXN_ERR(wTxnErr), .TXN_DONE_ACK(TXN_DONE_ACK), .TXN_DATA_FLUSH(wMainFlush), .TXN_DATA_FLUSHED(wMainFlushed), .RX_REQ(wMainReq), .RX_ADDR(wMainReqAddr), .RX_LEN(wMainReqLen), .RX_REQ_ACK(wReqAck & wMainReqProc), .RX_DATA_EN(MAIN_DATA_EN), .RX_DONE(wPackedMainDone), .RX_ERR(wPackedMainErr), .SG_DONE(wPackedSgRxDone), .SG_ERR(wPackedSgRxErr), .SG_ELEM_ADDR(wSgElemAddr), .SG_ELEM_LEN(wSgElemLen), .SG_ELEM_RDY(wSgElemRdy), .SG_ELEM_REN(wSgElemRen), .SG_RST(wSgRst), .CHNL_RX(wChnlRx), .CHNL_RX_LEN(wChnlRxLen), .CHNL_RX_LAST(wChnlRxLast), .CHNL_RX_OFF(wChnlRxOff), .CHNL_RX_RECVD(wChnlRxRecvd), .CHNL_RX_ACK_RECVD(wChnlRxAckRecvd), .CHNL_RX_CONSUMED(wChnlRxConsumed) ); // Manage the CHNL_RX* signals in the CHNL_CLK domain. rx_port_channel_gate #(.C_DATA_WIDTH(C_DATA_WIDTH)) gate ( .RST(rRst), .CLK(CLK), .RX(wChnlRx), .RX_RECVD(wChnlRxRecvd), .RX_ACK_RECVD(wChnlRxAckRecvd), .RX_LAST(wChnlRxLast), .RX_LEN(wChnlRxLen), .RX_OFF(wChnlRxOff), .RX_CONSUMED(wChnlRxConsumed), .RD_DATA(wMainData), .RD_EMPTY(wMainDataEmpty), .RD_EN(wMainDataRen), .CHNL_CLK(CHNL_CLK), .CHNL_RX(CHNL_RX), .CHNL_RX_ACK(CHNL_RX_ACK), .CHNL_RX_LAST(CHNL_RX_LAST), .CHNL_RX_LEN(CHNL_RX_LEN), .CHNL_RX_OFF(CHNL_RX_OFF), .CHNL_RX_DATA(CHNL_RX_DATA), .CHNL_RX_DATA_VALID(CHNL_RX_DATA_VALID), .CHNL_RX_DATA_REN(CHNL_RX_DATA_REN) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/rx_port_64.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: rx_port_64.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Receives data from the rx_engine and buffers the output // for the RIFFA channel. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module rx_port_64 #( parameter C_DATA_WIDTH = 9'd64, parameter C_MAIN_FIFO_DEPTH = 1024, parameter C_SG_FIFO_DEPTH = 512, parameter C_MAX_READ_REQ = 2, // Max read: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B // Local parameters parameter C_DATA_WORD_WIDTH = clog2((C_DATA_WIDTH/32)+1), parameter C_MAIN_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_MAIN_FIFO_DEPTH))+1), parameter C_SG_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_SG_FIFO_DEPTH))+1) ) ( input CLK, input RST, input [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // Maximum read payload: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B output SG_RX_BUF_RECVD, // Scatter gather RX buffer completely read (ready for next if applicable) input [31:0] SG_RX_BUF_DATA, // Scatter gather RX buffer data input SG_RX_BUF_LEN_VALID, // Scatter gather RX buffer length valid input SG_RX_BUF_ADDR_HI_VALID, // Scatter gather RX buffer high address valid input SG_RX_BUF_ADDR_LO_VALID, // Scatter gather RX buffer low address valid output SG_TX_BUF_RECVD, // Scatter gather TX buffer completely read (ready for next if applicable) input [31:0] SG_TX_BUF_DATA, // Scatter gather TX buffer data input SG_TX_BUF_LEN_VALID, // Scatter gather TX buffer length valid input SG_TX_BUF_ADDR_HI_VALID, // Scatter gather TX buffer high address valid input SG_TX_BUF_ADDR_LO_VALID, // Scatter gather TX buffer low address valid output [C_DATA_WIDTH-1:0] SG_DATA, // Scatter gather TX buffer data output SG_DATA_EMPTY, // Scatter gather TX buffer data empty input SG_DATA_REN, // Scatter gather TX buffer data read enable input SG_RST, // Scatter gather TX buffer data reset output SG_ERR, // Scatter gather TX encountered an error input [31:0] TXN_DATA, // Read transaction data input TXN_LEN_VALID, // Read transaction length valid input TXN_OFF_LAST_VALID, // Read transaction offset/last valid output [31:0] TXN_DONE_LEN, // Read transaction actual transfer length output TXN_DONE, // Read transaction done input TXN_DONE_ACK, // Read transaction actual transfer length read output RX_REQ, // Read request input RX_REQ_ACK, // Read request accepted output [1:0] RX_REQ_TAG, // Read request data tag output [63:0] RX_REQ_ADDR, // Read request address output [9:0] RX_REQ_LEN, // Read request length input [C_DATA_WIDTH-1:0] MAIN_DATA, // Main incoming data input [C_DATA_WORD_WIDTH-1:0] MAIN_DATA_EN, // Main incoming data enable input MAIN_DONE, // Main incoming data complete input MAIN_ERR, // Main incoming data completed with error input [C_DATA_WIDTH-1:0] SG_RX_DATA, // Scatter gather for RX incoming data input [C_DATA_WORD_WIDTH-1:0] SG_RX_DATA_EN, // Scatter gather for RX incoming data enable input SG_RX_DONE, // Scatter gather for RX incoming data complete input SG_RX_ERR, // Scatter gather for RX incoming data completed with error input [C_DATA_WIDTH-1:0] SG_TX_DATA, // Scatter gather for TX incoming data input [C_DATA_WORD_WIDTH-1:0] SG_TX_DATA_EN, // Scatter gather for TX incoming data enable input SG_TX_DONE, // Scatter gather for TX incoming data complete input SG_TX_ERR, // Scatter gather for TX incoming data completed with error input CHNL_CLK, // Channel read clock output CHNL_RX, // Channel read receive signal input CHNL_RX_ACK, // Channle read received signal output CHNL_RX_LAST, // Channel last read output [31:0] CHNL_RX_LEN, // Channel read length output [30:0] CHNL_RX_OFF, // Channel read offset output [C_DATA_WIDTH-1:0] CHNL_RX_DATA, // Channel read data output CHNL_RX_DATA_VALID, // Channel read data valid input CHNL_RX_DATA_REN // Channel read data has been recieved ); `include "common_functions.v" assign SG_ERR = (wPackedSgTxDone & wPackedSgTxErr); wire [C_DATA_WIDTH-1:0] wPackedMainData; wire wPackedMainWen; wire wPackedMainDone; wire wPackedMainErr; wire wMainFlush; wire wMainFlushed; wire [C_DATA_WIDTH-1:0] wPackedSgRxData; wire wPackedSgRxWen; wire wPackedSgRxDone; wire wPackedSgRxErr; wire wSgRxFlush; wire wSgRxFlushed; wire [C_DATA_WIDTH-1:0] wPackedSgTxData; wire wPackedSgTxWen; wire wPackedSgTxDone; wire wPackedSgTxErr; wire wSgTxFlush; wire wSgTxFlushed; wire wMainDataRen; wire wMainDataEmpty; wire [C_DATA_WIDTH-1:0] wMainData; wire wSgRxRst; wire wSgRxDataRen; wire wSgRxDataEmpty; wire [C_DATA_WIDTH-1:0] wSgRxData; wire [C_SG_FIFO_DEPTH_WIDTH-1:0] wSgRxFifoCount; wire wSgTxRst; wire [C_SG_FIFO_DEPTH_WIDTH-1:0] wSgTxFifoCount; wire wSgRxReq; wire [63:0] wSgRxReqAddr; wire [9:0] wSgRxReqLen; wire wSgTxReq; wire [63:0] wSgTxReqAddr; wire [9:0] wSgTxReqLen; wire wSgRxReqProc; wire wSgTxReqProc; wire wMainReqProc; wire wReqAck; wire wSgElemRdy; wire wSgElemRen; wire [63:0] wSgElemAddr; wire [31:0] wSgElemLen; wire wSgRst; wire wMainReq; wire [63:0] wMainReqAddr; wire [9:0] wMainReqLen; wire wTxnErr; wire wChnlRx; wire wChnlRxRecvd; wire wChnlRxAckRecvd; wire wChnlRxLast; wire [31:0] wChnlRxLen; wire [30:0] wChnlRxOff; wire [31:0] wChnlRxConsumed; reg [4:0] rWideRst=0; reg rRst=0; // Generate a wide reset from the input reset. always @ (posedge CLK) begin rRst <= #1 rWideRst[4]; if (RST) rWideRst <= #1 5'b11111; else rWideRst <= (rWideRst<<1); end // Pack received data tightly into our FIFOs fifo_packer_64 mainFifoPacker ( .CLK(CLK), .RST(rRst), .DATA_IN(MAIN_DATA), .DATA_IN_EN(MAIN_DATA_EN), .DATA_IN_DONE(MAIN_DONE), .DATA_IN_ERR(MAIN_ERR), .DATA_IN_FLUSH(wMainFlush), .PACKED_DATA(wPackedMainData), .PACKED_WEN(wPackedMainWen), .PACKED_DATA_DONE(wPackedMainDone), .PACKED_DATA_ERR(wPackedMainErr), .PACKED_DATA_FLUSHED(wMainFlushed) ); fifo_packer_64 sgRxFifoPacker ( .CLK(CLK), .RST(rRst), .DATA_IN(SG_RX_DATA), .DATA_IN_EN(SG_RX_DATA_EN), .DATA_IN_DONE(SG_RX_DONE), .DATA_IN_ERR(SG_RX_ERR), .DATA_IN_FLUSH(wSgRxFlush), .PACKED_DATA(wPackedSgRxData), .PACKED_WEN(wPackedSgRxWen), .PACKED_DATA_DONE(wPackedSgRxDone), .PACKED_DATA_ERR(wPackedSgRxErr), .PACKED_DATA_FLUSHED(wSgRxFlushed) ); fifo_packer_64 sgTxFifoPacker ( .CLK(CLK), .RST(rRst), .DATA_IN(SG_TX_DATA), .DATA_IN_EN(SG_TX_DATA_EN), .DATA_IN_DONE(SG_TX_DONE), .DATA_IN_ERR(SG_TX_ERR), .DATA_IN_FLUSH(wSgTxFlush), .PACKED_DATA(wPackedSgTxData), .PACKED_WEN(wPackedSgTxWen), .PACKED_DATA_DONE(wPackedSgTxDone), .PACKED_DATA_ERR(wPackedSgTxErr), .PACKED_DATA_FLUSHED(wSgTxFlushed) ); // FIFOs for storing received data for the channel. (* RAM_STYLE="BLOCK" *) async_fifo_fwft #(.C_WIDTH(C_DATA_WIDTH), .C_DEPTH(C_MAIN_FIFO_DEPTH)) mainFifo ( .WR_CLK(CLK), .WR_RST(rRst | (wTxnErr & TXN_DONE) | wSgRst), .WR_EN(wPackedMainWen), .WR_DATA(wPackedMainData), .WR_FULL(), .RD_CLK(CHNL_CLK), .RD_RST(rRst | (wTxnErr & TXN_DONE) | wSgRst), .RD_EN(wMainDataRen), .RD_DATA(wMainData), .RD_EMPTY(wMainDataEmpty) ); (* RAM_STYLE="BLOCK" *) sync_fifo #(.C_WIDTH(C_DATA_WIDTH), .C_DEPTH(C_SG_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) sgRxFifo ( .RST(rRst | wSgRxRst), .CLK(CLK), .WR_EN(wPackedSgRxWen), .WR_DATA(wPackedSgRxData), .FULL(), .RD_EN(wSgRxDataRen), .RD_DATA(wSgRxData), .EMPTY(wSgRxDataEmpty), .COUNT(wSgRxFifoCount) ); (* RAM_STYLE="BLOCK" *) sync_fifo #(.C_WIDTH(C_DATA_WIDTH), .C_DEPTH(C_SG_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) sgTxFifo ( .RST(rRst | wSgTxRst), .CLK(CLK), .WR_EN(wPackedSgTxWen), .WR_DATA(wPackedSgTxData), .FULL(), .RD_EN(SG_DATA_REN), .RD_DATA(SG_DATA), .EMPTY(SG_DATA_EMPTY), .COUNT(wSgTxFifoCount) ); // Manage requesting and acknowledging scatter gather data. Note that // these modules will share the main requestor's RX channel. They will // take priority over the main logic's use of the RX channel. sg_list_requester #(.C_FIFO_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_SG_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ)) sgRxReq ( .CLK(CLK), .RST(rRst), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE), .USER_RST(wSgRst), .BUF_RECVD(SG_RX_BUF_RECVD), .BUF_DATA(SG_RX_BUF_DATA), .BUF_LEN_VALID(SG_RX_BUF_LEN_VALID), .BUF_ADDR_HI_VALID(SG_RX_BUF_ADDR_HI_VALID), .BUF_ADDR_LO_VALID(SG_RX_BUF_ADDR_LO_VALID), .FIFO_COUNT(wSgRxFifoCount), .FIFO_FLUSH(wSgRxFlush), .FIFO_FLUSHED(wSgRxFlushed), .FIFO_RST(wSgRxRst), .RX_REQ(wSgRxReq), .RX_ADDR(wSgRxReqAddr), .RX_LEN(wSgRxReqLen), .RX_REQ_ACK(wReqAck & wSgRxReqProc), .RX_DONE(wPackedSgRxDone) ); sg_list_requester #(.C_FIFO_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_SG_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ)) sgTxReq ( .CLK(CLK), .RST(rRst), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE), .USER_RST(SG_RST), .BUF_RECVD(SG_TX_BUF_RECVD), .BUF_DATA(SG_TX_BUF_DATA), .BUF_LEN_VALID(SG_TX_BUF_LEN_VALID), .BUF_ADDR_HI_VALID(SG_TX_BUF_ADDR_HI_VALID), .BUF_ADDR_LO_VALID(SG_TX_BUF_ADDR_LO_VALID), .FIFO_COUNT(wSgTxFifoCount), .FIFO_FLUSH(wSgTxFlush), .FIFO_FLUSHED(wSgTxFlushed), .FIFO_RST(wSgTxRst), .RX_REQ(wSgTxReq), .RX_ADDR(wSgTxReqAddr), .RX_LEN(wSgTxReqLen), .RX_REQ_ACK(wReqAck & wSgTxReqProc), .RX_DONE(wPackedSgTxDone) ); // A read requester for the channel and scatter gather requesters. rx_port_requester_mux requesterMux ( .RST(rRst), .CLK(CLK), .SG_RX_REQ(wSgRxReq), .SG_RX_LEN(wSgRxReqLen), .SG_RX_ADDR(wSgRxReqAddr), .SG_RX_REQ_PROC(wSgRxReqProc), .SG_TX_REQ(wSgTxReq), .SG_TX_LEN(wSgTxReqLen), .SG_TX_ADDR(wSgTxReqAddr), .SG_TX_REQ_PROC(wSgTxReqProc), .MAIN_REQ(wMainReq), .MAIN_LEN(wMainReqLen), .MAIN_ADDR(wMainReqAddr), .MAIN_REQ_PROC(wMainReqProc), .RX_REQ(RX_REQ), .RX_REQ_ACK(RX_REQ_ACK), .RX_REQ_TAG(RX_REQ_TAG), .RX_REQ_ADDR(RX_REQ_ADDR), .RX_REQ_LEN(RX_REQ_LEN), .REQ_ACK(wReqAck) ); // Read the scatter gather buffer address and length, continuously so that // we have it ready whenever the next buffer is needed. sg_list_reader_64 #(.C_DATA_WIDTH(C_DATA_WIDTH)) sgListReader ( .CLK(CLK), .RST(rRst | wSgRst), .BUF_DATA(wSgRxData), .BUF_DATA_EMPTY(wSgRxDataEmpty), .BUF_DATA_REN(wSgRxDataRen), .VALID(wSgElemRdy), .EMPTY(), .REN(wSgElemRen), .ADDR(wSgElemAddr), .LEN(wSgElemLen) ); // Main port reader logic rx_port_reader #(.C_DATA_WIDTH(C_DATA_WIDTH), .C_FIFO_DEPTH(C_MAIN_FIFO_DEPTH), .C_MAX_READ_REQ(C_MAX_READ_REQ)) reader ( .CLK(CLK), .RST(rRst), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE), .TXN_DATA(TXN_DATA), .TXN_LEN_VALID(TXN_LEN_VALID), .TXN_OFF_LAST_VALID(TXN_OFF_LAST_VALID), .TXN_DONE_LEN(TXN_DONE_LEN), .TXN_DONE(TXN_DONE), .TXN_ERR(wTxnErr), .TXN_DONE_ACK(TXN_DONE_ACK), .TXN_DATA_FLUSH(wMainFlush), .TXN_DATA_FLUSHED(wMainFlushed), .RX_REQ(wMainReq), .RX_ADDR(wMainReqAddr), .RX_LEN(wMainReqLen), .RX_REQ_ACK(wReqAck & wMainReqProc), .RX_DATA_EN(MAIN_DATA_EN), .RX_DONE(wPackedMainDone), .RX_ERR(wPackedMainErr), .SG_DONE(wPackedSgRxDone), .SG_ERR(wPackedSgRxErr), .SG_ELEM_ADDR(wSgElemAddr), .SG_ELEM_LEN(wSgElemLen), .SG_ELEM_RDY(wSgElemRdy), .SG_ELEM_REN(wSgElemRen), .SG_RST(wSgRst), .CHNL_RX(wChnlRx), .CHNL_RX_LEN(wChnlRxLen), .CHNL_RX_LAST(wChnlRxLast), .CHNL_RX_OFF(wChnlRxOff), .CHNL_RX_RECVD(wChnlRxRecvd), .CHNL_RX_ACK_RECVD(wChnlRxAckRecvd), .CHNL_RX_CONSUMED(wChnlRxConsumed) ); // Manage the CHNL_RX* signals in the CHNL_CLK domain. rx_port_channel_gate #(.C_DATA_WIDTH(C_DATA_WIDTH)) gate ( .RST(rRst), .CLK(CLK), .RX(wChnlRx), .RX_RECVD(wChnlRxRecvd), .RX_ACK_RECVD(wChnlRxAckRecvd), .RX_LAST(wChnlRxLast), .RX_LEN(wChnlRxLen), .RX_OFF(wChnlRxOff), .RX_CONSUMED(wChnlRxConsumed), .RD_DATA(wMainData), .RD_EMPTY(wMainDataEmpty), .RD_EN(wMainDataRen), .CHNL_CLK(CHNL_CLK), .CHNL_RX(CHNL_RX), .CHNL_RX_ACK(CHNL_RX_ACK), .CHNL_RX_LAST(CHNL_RX_LAST), .CHNL_RX_LEN(CHNL_RX_LEN), .CHNL_RX_OFF(CHNL_RX_OFF), .CHNL_RX_DATA(CHNL_RX_DATA), .CHNL_RX_DATA_VALID(CHNL_RX_DATA_VALID), .CHNL_RX_DATA_REN(CHNL_RX_DATA_REN) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/rx_port_channel_gate.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: rx_port_channel_gate.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Provides cross domain synchronization for the CHNL_RX* // signals between the CHNL_CLK and CLK domains. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module rx_port_channel_gate #( parameter C_DATA_WIDTH = 9'd64 ) ( input RST, input CLK, input RX, // Channel read signal (CLK) output RX_RECVD, // Channel read received signal (CLK) output RX_ACK_RECVD, // Channel read acknowledgment received signal (CLK) input RX_LAST, // Channel last read (CLK) input [31:0] RX_LEN, // Channel read length (CLK) input [30:0] RX_OFF, // Channel read offset (CLK) output [31:0] RX_CONSUMED, // Channel words consumed (CLK) input [C_DATA_WIDTH-1:0] RD_DATA, // FIFO read data (CHNL_CLK) input RD_EMPTY, // FIFO is empty (CHNL_CLK) output RD_EN, // FIFO read enable (CHNL_CLK) input CHNL_CLK, // Channel read clock output CHNL_RX, // Channel read receive signal (CHNL_CLK) input CHNL_RX_ACK, // Channle read received signal (CHNL_CLK) output CHNL_RX_LAST, // Channel last read (CHNL_CLK) output [31:0] CHNL_RX_LEN, // Channel read length (CHNL_CLK) output [30:0] CHNL_RX_OFF, // Channel read offset (CHNL_CLK) output [C_DATA_WIDTH-1:0] CHNL_RX_DATA, // Channel read data (CHNL_CLK) output CHNL_RX_DATA_VALID, // Channel read data valid (CHNL_CLK) input CHNL_RX_DATA_REN // Channel read data has been recieved (CHNL_CLK) ); reg rAckd=0, _rAckd=0; reg rChnlRxAck=0, _rChnlRxAck=0; reg [31:0] rConsumed=0, _rConsumed=0; reg [31:0] rConsumedStable=0, _rConsumedStable=0; reg [31:0] rConsumedSample=0, _rConsumedSample=0; reg rCountRead=0, _rCountRead=0; wire wCountRead; wire wCountStable; wire wDataRead = (CHNL_RX_DATA_REN & CHNL_RX_DATA_VALID); assign RX_CONSUMED = rConsumedSample; assign RD_EN = CHNL_RX_DATA_REN; assign CHNL_RX_LAST = RX_LAST; assign CHNL_RX_LEN = RX_LEN; assign CHNL_RX_OFF = RX_OFF; assign CHNL_RX_DATA = RD_DATA; assign CHNL_RX_DATA_VALID = !RD_EMPTY; // Buffer the input signals that come from outside the rx_port. always @ (posedge CHNL_CLK) begin rChnlRxAck <= #1 (RST ? 1'd0 : _rChnlRxAck); end always @ (*) begin _rChnlRxAck = CHNL_RX_ACK; end // Signal receive into the channel domain. cross_domain_signal rxSig ( .CLK_A(CLK), .CLK_A_SEND(RX), .CLK_A_RECV(RX_RECVD), .CLK_B(CHNL_CLK), .CLK_B_RECV(CHNL_RX), .CLK_B_SEND(CHNL_RX) ); // Signal acknowledgment of receive into the CLK domain. syncff rxAckSig (.CLK(CLK), .IN_ASYNC(rAckd), .OUT_SYNC(RX_ACK_RECVD)); // Capture CHNL_RX_ACK and reset only after the CHNL_RX drops. always @ (posedge CHNL_CLK) begin rAckd <= #1 (RST ? 1'd0 : _rAckd); end always @ (*) begin _rAckd = (CHNL_RX & (rAckd | rChnlRxAck)); end // Count the words consumed by the channel and pass it into the CLK domain. always @ (posedge CHNL_CLK) begin rConsumed <= #1 _rConsumed; rConsumedStable <= #1 _rConsumedStable; rCountRead <= #1 (RST ? 1'd0 : _rCountRead); end always @ (*) begin _rConsumed = (!CHNL_RX ? 0 : rConsumed + (wDataRead*(C_DATA_WIDTH/32))); _rConsumedStable = (wCountRead | rCountRead ? rConsumedStable : rConsumed); _rCountRead = !wCountRead; end always @ (posedge CLK) begin rConsumedSample <= #1 _rConsumedSample; end always @ (*) begin _rConsumedSample = (wCountStable ? rConsumedStable : rConsumedSample); end // Determine when it's safe to update the count in the CLK domain. cross_domain_signal countSync ( .CLK_A(CHNL_CLK), .CLK_A_SEND(rCountRead), .CLK_A_RECV(wCountRead), .CLK_B(CLK), .CLK_B_RECV(wCountStable), .CLK_B_SEND(wCountStable) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/rx_port_reader.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: rx_port_reader.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Handles the RX lifecycle and issuing requests for receiving // data input. // for the RIFFA channel. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_RXPORTRD_MAIN_IDLE 6'b00_0001 `define S_RXPORTRD_MAIN_CHECK 6'b00_0010 `define S_RXPORTRD_MAIN_READ 6'b00_0100 `define S_RXPORTRD_MAIN_FLUSH 6'b00_1000 `define S_RXPORTRD_MAIN_DONE 6'b01_0000 `define S_RXPORTRD_MAIN_RESET 6'b10_0000 `define S_RXPORTRD_RX_IDLE 8'b0000_0001 `define S_RXPORTRD_RX_BUF 8'b0000_0010 `define S_RXPORTRD_RX_ADJ_0 8'b0000_0100 `define S_RXPORTRD_RX_ADJ_1 8'b0000_1000 `define S_RXPORTRD_RX_ISSUE 8'b0001_0000 `define S_RXPORTRD_RX_WAIT_0 8'b0010_0000 `define S_RXPORTRD_RX_WAIT_1 8'b0100_0000 `define S_RXPORTRD_RX_DONE 8'b1000_0000 module rx_port_reader #( parameter C_DATA_WIDTH = 9'd64, parameter C_FIFO_DEPTH = 1024, parameter C_MAX_READ_REQ = 2, // Max read: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B // Local parameters parameter C_DATA_WORD_WIDTH = clog2((C_DATA_WIDTH/32)+1), parameter C_FIFO_WORDS = (C_DATA_WIDTH/32)*C_FIFO_DEPTH ) ( input CLK, input RST, input [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // Maximum read payload: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B input [31:0] TXN_DATA, // Read transaction data input TXN_LEN_VALID, // Read transaction length valid input TXN_OFF_LAST_VALID, // Read transaction offset/last valid output [31:0] TXN_DONE_LEN, // Read transaction actual transfer length output TXN_DONE, // Read transaction done output TXN_ERR, // Read transaction completed with error input TXN_DONE_ACK, // Read transaction actual transfer length read output TXN_DATA_FLUSH, // Request that all data in the packer be flushed input TXN_DATA_FLUSHED, // All data in the packer has been flushed output RX_REQ, // Issue a read request output [63:0] RX_ADDR, // Request address output [9:0] RX_LEN, // Request length input RX_REQ_ACK, // Request has been accepted input [C_DATA_WORD_WIDTH-1:0] RX_DATA_EN, // Incoming read data enable input RX_DONE, // Incoming read completed input RX_ERR, // Incoming read completed with error input SG_DONE, // Incoming scatter gather read completed input SG_ERR, // Incoming scatter gather read completed with error input [63:0] SG_ELEM_ADDR, // Scatter gather element address input [31:0] SG_ELEM_LEN, // Scatter gather element length (in words) input SG_ELEM_RDY, // Scatter gather element ready output SG_ELEM_REN, // Scatter gather element read enable output SG_RST, // Scatter gather reset output CHNL_RX, // Signal channel RX output [31:0] CHNL_RX_LEN, // Channel RX length output CHNL_RX_LAST, // Channel RX last output [30:0] CHNL_RX_OFF, // Channel RX offset input CHNL_RX_RECVD, // Channel RX received input CHNL_RX_ACK_RECVD, // Channel RX acknowledgment received input [31:0] CHNL_RX_CONSUMED // Channel words consumed in current RX ); `include "common_functions.v" reg [31:0] rTxnData=0, _rTxnData=0; reg rTxnOffLastValid=0, _rTxnOffLastValid=0; reg rTxnLenValid=0, _rTxnLenValid=0; reg [C_DATA_WORD_WIDTH-1:0] rRxDataEn=0, _rRxDataEn=0; (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [5:0] rMainState=`S_RXPORTRD_MAIN_IDLE, _rMainState=`S_RXPORTRD_MAIN_IDLE; reg [31:0] rOffLast=0, _rOffLast=0; reg [31:0] rReadWords=0, _rReadWords=0; reg rReadWordsZero=0, _rReadWordsZero=0; reg [0:0] rStart=0, _rStart=0; reg [3:0] rFlushed=0, _rFlushed=0; reg [31:0] rDoneLen=0, _rDoneLen=0; reg rTxnDone=0, _rTxnDone=0; (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [7:0] rRxState=`S_RXPORTRD_RX_IDLE, _rRxState=`S_RXPORTRD_RX_IDLE; reg rSgRen=0, _rSgRen=0; reg [31:0] rWords=0, _rWords=0; reg [31:0] rBufWords=0, _rBufWords=0; reg [31:0] rBufWordsInit=0, _rBufWordsInit=0; reg rLargeBuf=0, _rLargeBuf=0; reg [63:0] rAddr=64'd0, _rAddr=64'd0; reg [3:0] rValsProp=0, _rValsProp=0; reg [2:0] rCarry=0, _rCarry=0; reg rCopyBufWords=0, _rCopyBufWords=0; reg rUseInit=0, _rUseInit=0; reg [10:0] rPageRem=0, _rPageRem=0; reg rPageSpill=0, _rPageSpill=0; reg rPageSpillInit=0, _rPageSpillInit=0; reg [10:0] rPreLen=0, _rPreLen=0; reg [2:0] rMaxPayloadTrain=0, _rMaxPayloadTrain=0; reg [2:0] rMaxPayloadShift=0, _rMaxPayloadShift=0; reg [9:0] rMaxPayload=0, _rMaxPayload=0; reg rPayloadSpill=0, _rPayloadSpill=0; reg rMaxLen=0, _rMaxLen=0; reg [9:0] rLen=0, _rLen=0; reg rLenEQWordsHi=0, _rLenEQWordsHi=0; reg rLenEQWordsLo=0, _rLenEQWordsLo=0; reg rLenEQBufWordsHi=0, _rLenEQBufWordsHi=0; reg rLenEQBufWordsLo=0, _rLenEQBufWordsLo=0; reg [31:0] rRecvdWords=0, _rRecvdWords=0; reg [31:0] rReqdWords=0, _rReqdWords=0; reg [31:0] rRequestingWords=0, _rRequestingWords=0; reg [31:0] rAvailWords=0, _rAvailWords=0; reg [31:0] rPartWords=0, _rPartWords=0; reg [10:0] rAckCount=0, _rAckCount=0; reg rAckCountEQ0=0, _rAckCountEQ0=0; reg rLastDoneRead=1, _rLastDoneRead=1; reg rTxnDoneAck=0, _rTxnDoneAck=0; reg rPartWordsRecvd=0, _rPartWordsRecvd=0; reg rCarryInv=0, _rCarryInv=0; reg rSpaceAvail=0, _rSpaceAvail=0; reg rPartialDone=0, _rPartialDone=0; reg rReqPartialDone=0, _rReqPartialDone=0; reg rErr=0, _rErr=0; assign TXN_DONE_LEN = rDoneLen; assign TXN_DONE = (rTxnDone | rPartialDone); assign TXN_ERR = rErr; assign TXN_DATA_FLUSH = rMainState[3]; // S_RXPORTRD_MAIN_FLUSH assign RX_REQ = (rRxState[4] & rSpaceAvail); // S_RXPORTRD_RX_ISSUE assign RX_ADDR = rAddr; assign RX_LEN = rLen; assign SG_ELEM_REN = rSgRen; assign SG_RST = rMainState[1]; // S_RXPORTRD_MAIN_CHECK assign CHNL_RX = (rMainState[2] | rMainState[3] | rMainState[4]); // S_RXPORTRD_MAIN_READ | S_RXPORTRD_MAIN_FLUSH | S_RXPORTRD_MAIN_DONE assign CHNL_RX_LEN = rReadWords; assign CHNL_RX_LAST = rOffLast[0]; assign CHNL_RX_OFF = rOffLast[31:1]; // Buffer signals that come from outside the rx_port. always @ (posedge CLK) begin rTxnData <= #1 _rTxnData; rTxnOffLastValid <= #1 _rTxnOffLastValid; rTxnLenValid <= #1 _rTxnLenValid; rTxnDoneAck <= #1 (RST ? 1'd0 : _rTxnDoneAck); rRxDataEn <= #1 _rRxDataEn; end always @ (*) begin _rTxnData = TXN_DATA; _rTxnOffLastValid = TXN_OFF_LAST_VALID; _rTxnLenValid = TXN_LEN_VALID; _rTxnDoneAck = TXN_DONE_ACK; _rRxDataEn = RX_DATA_EN; end // Handle RX lifecycle. always @ (posedge CLK) begin rMainState <= #1 (RST ? `S_RXPORTRD_MAIN_IDLE : _rMainState); rOffLast <= #1 _rOffLast; rReadWords <= #1 _rReadWords; rReadWordsZero <= #1 _rReadWordsZero; rStart <= #1 _rStart; rFlushed <= #1 _rFlushed; rDoneLen <= #1 (RST ? 0 : _rDoneLen); rTxnDone <= #1 _rTxnDone; end always @ (*) begin _rMainState = rMainState; _rDoneLen = rDoneLen; _rTxnDone = rTxnDone; _rOffLast = (rTxnOffLastValid ? rTxnData : rOffLast); _rReadWords = (rMainState[0] & rTxnLenValid ? rTxnData : rReadWords); _rReadWordsZero = (rReadWords == 0); _rStart = ((rStart<<1) | rTxnLenValid); _rFlushed = ((rFlushed<<1) | TXN_DATA_FLUSHED); case (rMainState) `S_RXPORTRD_MAIN_IDLE: begin // Wait for new read transaction offset/last & length _rTxnDone = 0; if (rStart[0]) _rMainState = `S_RXPORTRD_MAIN_CHECK; end `S_RXPORTRD_MAIN_CHECK: begin // See if we should start a transaction if (!rReadWordsZero) _rMainState = `S_RXPORTRD_MAIN_READ; else if (rOffLast[0]) _rMainState = `S_RXPORTRD_MAIN_FLUSH; else _rMainState = `S_RXPORTRD_MAIN_IDLE; end `S_RXPORTRD_MAIN_READ: begin // Issue read transfers, wait for data to arrive if (rRxState[7] & rLastDoneRead) begin // S_RXPORTRD_RX_DONE _rDoneLen = rRecvdWords; _rMainState = `S_RXPORTRD_MAIN_FLUSH; end end `S_RXPORTRD_MAIN_FLUSH: begin // Wait for data to be flushed if (rFlushed[3]) _rMainState = `S_RXPORTRD_MAIN_DONE; end `S_RXPORTRD_MAIN_DONE: begin // Wait for RX to be received and ackd in the channel if (CHNL_RX_RECVD & CHNL_RX_ACK_RECVD) _rMainState = `S_RXPORTRD_MAIN_RESET; end `S_RXPORTRD_MAIN_RESET: begin // Wait until RX has dropped in the channel if (!CHNL_RX_RECVD) begin _rTxnDone = 1; _rMainState = `S_RXPORTRD_MAIN_IDLE; end end default: begin _rMainState = `S_RXPORTRD_MAIN_IDLE; end endcase end // Issue the read requests at the buffer level. Decrement the amount requested // after every request. Continue until all words have been requested. wire [9:0] wAddrLoInv = ~rAddr[11:2]; always @ (posedge CLK) begin rRxState <= #1 (RST ? `S_RXPORTRD_RX_IDLE : _rRxState); rSgRen <= #1 (RST ? 1'd0: _rSgRen); rWords <= #1 _rWords; rBufWords <= #1 _rBufWords; rBufWordsInit <= #1 _rBufWordsInit; rLargeBuf <= #1 _rLargeBuf; rAddr <= #1 _rAddr; rCarry <= #1 _rCarry; rValsProp <= #1 _rValsProp; rPageRem <= #1 _rPageRem; rPageSpill <= #1 _rPageSpill; rPageSpillInit <= #1 _rPageSpillInit; rCopyBufWords <= #1 _rCopyBufWords; rUseInit <= #1 _rUseInit; rPreLen <= #1 _rPreLen; rMaxPayloadTrain <= #1 _rMaxPayloadTrain; rMaxPayloadShift <= #1 _rMaxPayloadShift; rMaxPayload <= #1 _rMaxPayload; rPayloadSpill <= #1 _rPayloadSpill; rMaxLen <= #1 _rMaxLen; rLen <= #1 _rLen; rLenEQWordsHi <= #1 _rLenEQWordsHi; rLenEQWordsLo <= #1 _rLenEQWordsLo; rLenEQBufWordsHi <= #1 _rLenEQBufWordsHi; rLenEQBufWordsLo <= #1 _rLenEQBufWordsLo; end always @ (*) begin _rRxState = rRxState; _rCopyBufWords = rCopyBufWords; _rUseInit = rUseInit; _rSgRen = rSgRen; _rValsProp = ((rValsProp<<1) | rRxState[2]); // S_RXPORTRD_RX_ADJ_0 _rLargeBuf = (SG_ELEM_LEN > rWords); {_rCarry[0], _rAddr[15:0]} = (rRxState[1] ? SG_ELEM_ADDR[15:0] : (rAddr[15:0] + ({12{RX_REQ_ACK}} & {rLen,2'd0}))); {_rCarry[1], _rAddr[31:16]} = (rRxState[1] ? SG_ELEM_ADDR[31:16] : (rAddr[31:16] + rCarry[0])); {_rCarry[2], _rAddr[47:32]} = (rRxState[1] ? SG_ELEM_ADDR[47:32] : (rAddr[47:32] + rCarry[1])); _rAddr[63:48] = (rRxState[1] ? SG_ELEM_ADDR[63:48] : (rAddr[63:48] + rCarry[2])); _rWords = (rRxState[0] ? rReadWords : (rWords - ({10{RX_REQ_ACK}} & rLen))); _rBufWordsInit = (rLargeBuf ? rWords : SG_ELEM_LEN); _rBufWords = (rCopyBufWords ? rBufWordsInit : rBufWords) - ({10{RX_REQ_ACK}} & rLen); _rPageRem = (wAddrLoInv + 1'd1); _rPageSpillInit = (rBufWordsInit > rPageRem); _rPageSpill = (rBufWords > rPageRem); _rPreLen = ((rPageSpillInit & rUseInit) | (rPageSpill & !rUseInit) ? rPageRem : rBufWords[10:0]); _rMaxPayloadTrain = (CONFIG_MAX_READ_REQUEST_SIZE > 3'd4 ? 3'd4 : CONFIG_MAX_READ_REQUEST_SIZE); _rMaxPayloadShift = (C_MAX_READ_REQ[2:0] < rMaxPayloadTrain ? C_MAX_READ_REQ[2:0] : rMaxPayloadTrain); _rMaxPayload = (6'd32< rMaxPayload); _rMaxLen = ((rMaxLen & !rValsProp[2]) | RX_REQ_ACK); _rLen = (rPayloadSpill | rMaxLen ? rMaxPayload : rPreLen[9:0]); _rLenEQWordsHi = (16'd0 == rWords[31:16]); _rLenEQWordsLo = ({6'd0, rLen} == rWords[15:0]); _rLenEQBufWordsHi = (16'd0 == rBufWords[31:16]); _rLenEQBufWordsLo = ({6'd0, rLen} == rBufWords[15:0]); case (rRxState) `S_RXPORTRD_RX_IDLE: begin // Wait for a new read transaction if (rMainState[2]) // S_RXPORTRD_MAIN_READ _rRxState = `S_RXPORTRD_RX_BUF; end `S_RXPORTRD_RX_BUF: begin // Wait for buffer length and address if (SG_ELEM_RDY) begin _rSgRen = 1; _rRxState = `S_RXPORTRD_RX_ADJ_0; end else if (rErr) begin _rRxState = `S_RXPORTRD_RX_WAIT_0; end end `S_RXPORTRD_RX_ADJ_0: begin // Fix for large buffer _rSgRen = 0; _rCopyBufWords = rSgRen; _rRxState = `S_RXPORTRD_RX_ADJ_1; end // (bufwords and pagerem valid here) `S_RXPORTRD_RX_ADJ_1: begin // Wait for the value to propagate // Check for page boundary crossing // Fix for page boundary crossing // Check for max read payload // Fix for max read payload _rCopyBufWords = 0; _rUseInit = rCopyBufWords; if (rValsProp[3]) _rRxState = `S_RXPORTRD_RX_ISSUE; end `S_RXPORTRD_RX_ISSUE: begin // Wait for the request to be accepted if (RX_REQ_ACK) begin if (rErr | (rLenEQWordsHi & rLenEQWordsLo)) _rRxState = `S_RXPORTRD_RX_WAIT_0; else if (rLenEQBufWordsHi & rLenEQBufWordsLo) _rRxState = `S_RXPORTRD_RX_BUF; else _rRxState = `S_RXPORTRD_RX_ADJ_0; end end `S_RXPORTRD_RX_WAIT_0: begin // Wait for rAckCount to update _rRxState = `S_RXPORTRD_RX_WAIT_1; end `S_RXPORTRD_RX_WAIT_1: begin // Wait for requested data to arrive if (rAckCountEQ0) _rRxState = `S_RXPORTRD_RX_DONE; end `S_RXPORTRD_RX_DONE: begin // Signal done if (rMainState[3]) // S_RXPORTRD_MAIN_FLUSH _rRxState = `S_RXPORTRD_RX_IDLE; end default: begin _rRxState = `S_RXPORTRD_RX_IDLE; end endcase end // Count the data. always @ (posedge CLK) begin rRecvdWords <= #1 _rRecvdWords; rReqdWords <= #1 _rReqdWords; rPartWords <= #1 _rPartWords; rAckCount <= #1 _rAckCount; rAckCountEQ0 <= #1 _rAckCountEQ0; rPartWordsRecvd <= #1 _rPartWordsRecvd; rRequestingWords <= #1 _rRequestingWords; rAvailWords <= #1 _rAvailWords; rCarryInv <= #1 _rCarryInv; rSpaceAvail <= #1 _rSpaceAvail; rLastDoneRead <= #1 (RST ? 1'd1 : _rLastDoneRead); end always @ (*) begin // Count words as they arrive (words from the rx_engine directly). if (rMainState[0]) // S_RXPORTRD_MAIN_IDLE _rRecvdWords = #1 0; else _rRecvdWords = #1 rRecvdWords + rRxDataEn; // Count words as they are requested. if (rMainState[0]) // S_RXPORTRD_MAIN_IDLE _rReqdWords = #1 0; else _rReqdWords = #1 rReqdWords + ({10{RX_REQ_ACK}} & rLen); // Track outstanding requests if (rMainState[0]) // S_RXPORTRD_MAIN_IDLE _rAckCount = 0; else _rAckCount = rAckCount + RX_REQ_ACK - RX_DONE; _rAckCountEQ0 = (rAckCount == 11'd0); // Track when the user reads the actual transfer amount. _rLastDoneRead = (rTxnDone ? 1'd0 : (rLastDoneRead | rTxnDoneAck)); // Track the amount of words that are expected to arrive. _rPartWords = #1 (rTxnLenValid ? rTxnData : rPartWords); // Compare counts. _rPartWordsRecvd = (rRecvdWords >= rPartWords); _rRequestingWords = rReqdWords + rLen; {_rCarryInv, _rAvailWords[15:0]} = {1'd1, rRequestingWords[15:0]} - CHNL_RX_CONSUMED[15:0]; _rAvailWords[31:16] = rRequestingWords[31:16] - CHNL_RX_CONSUMED[31:16] - !rCarryInv; _rSpaceAvail = (rAvailWords <= C_FIFO_WORDS); end // Facilitate sending a TXN_DONE when we receive a TXN_ACK after the transaction // has begun sending. This will happen when the workstation detects that it has // sent/used all its currently mapped scatter gather elements, but it's not enough // to complete the transaction. The TXN_DONE will let the workstation know it can // release the current scatter gather mappings and allocate new ones. always @ (posedge CLK) begin rPartialDone <= #1 _rPartialDone; rReqPartialDone <= #1 (RST ? 1'd0 : _rReqPartialDone); end always @ (*) begin // Signal TXN_DONE after we've recieved the (seemingly superfluous) TXN_ACK // and received the corresponding amount of words. _rPartialDone = (rReqPartialDone & rPartWordsRecvd); // Keep track of (seemingly superfluous) TXN_ACK requests. if ((rReqPartialDone & rPartWordsRecvd) | rMainState[0]) // S_RXPORTRD_MAIN_IDLE _rReqPartialDone = 0; else _rReqPartialDone = (rReqPartialDone | rTxnLenValid); end // Handle errors in the main data or scatter gather data. always @ (posedge CLK) begin rErr <= #1 (RST ? 1'd0 : _rErr); end always @ (*) begin // Keep track of errors if we encounter them. if (rMainState[0]) // S_RXPORTRD_MAIN_IDLE _rErr = 0; else _rErr = (rErr | (RX_DONE & RX_ERR) | (SG_DONE & SG_ERR)); end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/rx_port_requester_mux.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: rx_port_requester.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Issues read requests to the tx_engine for the rx_port // and sg_list_requester modules in the rx_port. Expects those modules to update // their address and length values after every request issued. Also expects them // to update their space available values within 6 cycles of a change to the // RX_LEN. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_RXPORTREQ_RX_TX 2'b00 `define S_RXPORTREQ_TX_RX 2'b01 `define S_RXPORTREQ_ISSUE 2'b10 module rx_port_requester_mux ( input RST, input CLK, input SG_RX_REQ, // Scatter gather RX read request input [9:0] SG_RX_LEN, // Scatter gather RX read request length input [63:0] SG_RX_ADDR, // Scatter gather RX read request address output SG_RX_REQ_PROC, // Scatter gather RX read request processing input SG_TX_REQ, // Scatter gather TX read request input [9:0] SG_TX_LEN, // Scatter gather TX read request length input [63:0] SG_TX_ADDR, // Scatter gather TX read request address output SG_TX_REQ_PROC, // Scatter gather TX read request processing input MAIN_REQ, // Main read request input [9:0] MAIN_LEN, // Main read request length input [63:0] MAIN_ADDR, // Main read request address output MAIN_REQ_PROC, // Main read request processing output RX_REQ, // Read request input RX_REQ_ACK, // Read request accepted output [1:0] RX_REQ_TAG, // Read request data tag output [63:0] RX_REQ_ADDR, // Read request address output [9:0] RX_REQ_LEN, // Read request length output REQ_ACK // Request accepted ); reg rRxReqAck=0, _rRxReqAck=0; (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [1:0] rState=`S_RXPORTREQ_RX_TX, _rState=`S_RXPORTREQ_RX_TX; reg [9:0] rLen=0, _rLen=0; reg [63:0] rAddr=64'd0, _rAddr=64'd0; reg rSgRxAck=0, _rSgRxAck=0; reg rSgTxAck=0, _rSgTxAck=0; reg rMainAck=0, _rMainAck=0; reg rAck=0, _rAck=0; assign SG_RX_REQ_PROC = rSgRxAck; assign SG_TX_REQ_PROC = rSgTxAck; assign MAIN_REQ_PROC = rMainAck; assign RX_REQ = rState[1]; // S_RXPORTREQ_ISSUE assign RX_REQ_TAG = {rSgTxAck, rSgRxAck}; assign RX_REQ_ADDR = rAddr; assign RX_REQ_LEN = rLen; assign REQ_ACK = rAck; // Buffer signals that come from outside the rx_port. always @ (posedge CLK) begin rRxReqAck <= #1 (RST ? 1'd0 : _rRxReqAck); end always @ (*) begin _rRxReqAck = RX_REQ_ACK; end // Handle issuing read requests. Scatter gather requests are processed // with higher priority than the main channel. always @ (posedge CLK) begin rState <= #1 (RST ? `S_RXPORTREQ_RX_TX : _rState); rLen <= #1 _rLen; rAddr <= #1 _rAddr; rSgRxAck <= #1 _rSgRxAck; rSgTxAck <= #1 _rSgTxAck; rMainAck <= #1 _rMainAck; rAck <= #1 _rAck; end always @ (*) begin _rState = rState; _rLen = rLen; _rAddr = rAddr; _rSgRxAck = rSgRxAck; _rSgTxAck = rSgTxAck; _rMainAck = rMainAck; _rAck = rAck; case (rState) `S_RXPORTREQ_RX_TX: begin // Wait for a new read request if (SG_RX_REQ) begin _rLen = SG_RX_LEN; _rAddr = SG_RX_ADDR; _rSgRxAck = 1; _rAck = 1; _rState = `S_RXPORTREQ_ISSUE; end else if (SG_TX_REQ) begin _rLen = SG_TX_LEN; _rAddr = SG_TX_ADDR; _rSgTxAck = 1; _rAck = 1; _rState = `S_RXPORTREQ_ISSUE; end else if (MAIN_REQ) begin _rLen = MAIN_LEN; _rAddr = MAIN_ADDR; _rMainAck = 1; _rAck = 1; _rState = `S_RXPORTREQ_ISSUE; end else begin _rState = `S_RXPORTREQ_TX_RX; end end `S_RXPORTREQ_TX_RX: begin // Wait for a new read request if (SG_TX_REQ) begin _rLen = SG_TX_LEN; _rAddr = SG_TX_ADDR; _rSgTxAck = 1; _rAck = 1; _rState = `S_RXPORTREQ_ISSUE; end else if (SG_RX_REQ) begin _rLen = SG_RX_LEN; _rAddr = SG_RX_ADDR; _rSgRxAck = 1; _rAck = 1; _rState = `S_RXPORTREQ_ISSUE; end else if (MAIN_REQ) begin _rLen = MAIN_LEN; _rAddr = MAIN_ADDR; _rMainAck = 1; _rAck = 1; _rState = `S_RXPORTREQ_ISSUE; end else begin _rState = `S_RXPORTREQ_RX_TX; end end `S_RXPORTREQ_ISSUE: begin // Issue the request _rAck = 0; if (rRxReqAck) begin _rSgRxAck = 0; _rSgTxAck = 0; _rMainAck = 0; if (rSgRxAck) _rState = `S_RXPORTREQ_TX_RX; else _rState = `S_RXPORTREQ_RX_TX; end end default: begin _rState = `S_RXPORTREQ_RX_TX; end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/sg_list_reader_128.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: sg_list_reader_128.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Reads data from the scatter gather list buffer. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_SGR128_RD_0 1'b1 `define S_SGR128_RD_WAIT 1'b0 `define S_SGR128_CAP_0 1'b0 `define S_SGR128_CAP_RDY 1'b1 module sg_list_reader_128 #( parameter C_DATA_WIDTH = 9'd128 ) ( input CLK, input RST, input [C_DATA_WIDTH-1:0] BUF_DATA, // Scatter gather buffer data input BUF_DATA_EMPTY, // Scatter gather buffer data empty output BUF_DATA_REN, // Scatter gather buffer data read enable output VALID, // Scatter gather element data is valid output EMPTY, // Scatter gather elements empty input REN, // Scatter gather element data read enable output [63:0] ADDR, // Scatter gather element address output [31:0] LEN // Scatter gather element length (in words) ); (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg rRdState=`S_SGR128_RD_0, _rRdState=`S_SGR128_RD_0; (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg rCapState=`S_SGR128_CAP_0, _rCapState=`S_SGR128_CAP_0; reg [C_DATA_WIDTH-1:0] rData={C_DATA_WIDTH{1'd0}}, _rData={C_DATA_WIDTH{1'd0}}; reg [63:0] rAddr=64'd0, _rAddr=64'd0; reg [31:0] rLen=0, _rLen=0; reg rFifoValid=0, _rFifoValid=0; reg rDataValid=0, _rDataValid=0; assign BUF_DATA_REN = rRdState; // Not S_SGR128_RD_WAIT assign VALID = rCapState; // S_SGR128_CAP_RDY assign EMPTY = (BUF_DATA_EMPTY & rRdState); // Not S_SGR128_RD_WAIT assign ADDR = rAddr; assign LEN = rLen; // Capture address and length as it comes out of the FIFO always @ (posedge CLK) begin rRdState <= #1 (RST ? `S_SGR128_RD_0 : _rRdState); rCapState <= #1 (RST ? `S_SGR128_CAP_0 : _rCapState); rData <= #1 _rData; rFifoValid <= #1 (RST ? 1'd0 : _rFifoValid); rDataValid <= #1 (RST ? 1'd0 : _rDataValid); rAddr <= #1 _rAddr; rLen <= #1 _rLen; end always @ (*) begin _rRdState = rRdState; _rCapState = rCapState; _rAddr = rAddr; _rLen = rLen; _rData = BUF_DATA; _rFifoValid = (BUF_DATA_REN & !BUF_DATA_EMPTY); _rDataValid = rFifoValid; case (rCapState) `S_SGR128_CAP_0: begin if (rDataValid) begin _rAddr = rData[63:0]; _rLen = rData[95:64]; _rCapState = `S_SGR128_CAP_RDY; end end `S_SGR128_CAP_RDY: begin if (REN) _rCapState = `S_SGR128_CAP_0; end endcase case (rRdState) `S_SGR128_RD_0: begin // Read from the sg data FIFO if (!BUF_DATA_EMPTY) _rRdState = `S_SGR128_RD_WAIT; end `S_SGR128_RD_WAIT: begin // Wait for the data to be consumed if (REN) _rRdState = `S_SGR128_RD_0; end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/sg_list_reader_32.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: sg_list_reader_32.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Reads data from the scatter gather list buffer. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_SGR32_RD_0 3'b000 `define S_SGR32_RD_1 3'b001 `define S_SGR32_RD_2 3'b010 `define S_SGR32_RD_3 3'b011 `define S_SGR32_RD_WAIT 3'b100 `define S_SGR32_CAP_0 3'b000 `define S_SGR32_CAP_1 3'b001 `define S_SGR32_CAP_2 3'b010 `define S_SGR32_CAP_3 3'b011 `define S_SGR32_CAP_RDY 3'b100 module sg_list_reader_32 #( parameter C_DATA_WIDTH = 9'd32 ) ( input CLK, input RST, input [C_DATA_WIDTH-1:0] BUF_DATA, // Scatter gather buffer data input BUF_DATA_EMPTY, // Scatter gather buffer data empty output BUF_DATA_REN, // Scatter gather buffer data read enable output VALID, // Scatter gather element data is valid output EMPTY, // Scatter gather elements empty input REN, // Scatter gather element data read enable output [63:0] ADDR, // Scatter gather element address output [31:0] LEN // Scatter gather element length (in words) ); (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [2:0] rRdState=`S_SGR32_RD_0, _rRdState=`S_SGR32_RD_0; (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [2:0] rCapState=`S_SGR32_CAP_0, _rCapState=`S_SGR32_CAP_0; reg [C_DATA_WIDTH-1:0] rData={C_DATA_WIDTH{1'd0}}, _rData={C_DATA_WIDTH{1'd0}}; reg [63:0] rAddr=64'd0, _rAddr=64'd0; reg [31:0] rLen=0, _rLen=0; reg rFifoValid=0, _rFifoValid=0; reg rDataValid=0, _rDataValid=0; assign BUF_DATA_REN = !rRdState[2]; // Not S_SGR32_RD_0 assign VALID = rCapState[2]; // S_SGR32_CAP_RDY assign EMPTY = (BUF_DATA_EMPTY & !rRdState[2]); // Not S_SGR32_RD_0 assign ADDR = rAddr; assign LEN = rLen; // Capture address and length as it comes out of the FIFO always @ (posedge CLK) begin rRdState <= #1 (RST ? `S_SGR32_RD_0 : _rRdState); rCapState <= #1 (RST ? `S_SGR32_CAP_0 : _rCapState); rData <= #1 _rData; rFifoValid <= #1 (RST ? 1'd0 : _rFifoValid); rDataValid <= #1 (RST ? 1'd0 : _rDataValid); rAddr <= #1 _rAddr; rLen <= #1 _rLen; end always @ (*) begin _rRdState = rRdState; _rCapState = rCapState; _rAddr = rAddr; _rLen = rLen; _rData = BUF_DATA; _rFifoValid = (BUF_DATA_REN & !BUF_DATA_EMPTY); _rDataValid = rFifoValid; case (rCapState) `S_SGR32_CAP_0: begin if (rDataValid) begin _rAddr[31:0] = rData; _rCapState = `S_SGR32_CAP_1; end end `S_SGR32_CAP_1: begin if (rDataValid) begin _rAddr[63:32] = rData; _rCapState = `S_SGR32_CAP_2; end end `S_SGR32_CAP_2: begin if (rDataValid) begin _rLen = rData; _rCapState = `S_SGR32_CAP_3; end end `S_SGR32_CAP_3: begin if (rDataValid) _rCapState = `S_SGR32_CAP_RDY; end `S_SGR32_CAP_RDY: begin if (REN) _rCapState = `S_SGR32_CAP_0; end default: begin _rCapState = `S_SGR32_CAP_0; end endcase case (rRdState) `S_SGR32_RD_0: begin // Read from the sg data FIFO if (!BUF_DATA_EMPTY) _rRdState = `S_SGR32_RD_1; end `S_SGR32_RD_1: begin // Read from the sg data FIFO if (!BUF_DATA_EMPTY) _rRdState = `S_SGR32_RD_2; end `S_SGR32_RD_2: begin // Read from the sg data FIFO if (!BUF_DATA_EMPTY) _rRdState = `S_SGR32_RD_3; end `S_SGR32_RD_3: begin // Read from the sg data FIFO if (!BUF_DATA_EMPTY) _rRdState = `S_SGR32_RD_WAIT; end `S_SGR32_RD_WAIT: begin // Wait for the data to be consumed if (REN) _rRdState = `S_SGR32_RD_0; end default: begin _rRdState = `S_SGR32_RD_0; end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/sg_list_reader_64.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: sg_list_reader_64.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Reads data from the scatter gather list buffer. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_SGR64_RD_0 2'b01 `define S_SGR64_RD_1 2'b11 `define S_SGR64_RD_WAIT 2'b10 `define S_SGR64_CAP_0 2'b00 `define S_SGR64_CAP_1 2'b01 `define S_SGR64_CAP_RDY 2'b10 module sg_list_reader_64 #( parameter C_DATA_WIDTH = 9'd64 ) ( input CLK, input RST, input [C_DATA_WIDTH-1:0] BUF_DATA, // Scatter gather buffer data input BUF_DATA_EMPTY, // Scatter gather buffer data empty output BUF_DATA_REN, // Scatter gather buffer data read enable output VALID, // Scatter gather element data is valid output EMPTY, // Scatter gather elements empty input REN, // Scatter gather element data read enable output [63:0] ADDR, // Scatter gather element address output [31:0] LEN // Scatter gather element length (in words) ); (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [1:0] rRdState=`S_SGR64_RD_0, _rRdState=`S_SGR64_RD_0; (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [1:0] rCapState=`S_SGR64_CAP_0, _rCapState=`S_SGR64_CAP_0; reg [C_DATA_WIDTH-1:0] rData={C_DATA_WIDTH{1'd0}}, _rData={C_DATA_WIDTH{1'd0}}; reg [63:0] rAddr=64'd0, _rAddr=64'd0; reg [31:0] rLen=0, _rLen=0; reg rFifoValid=0, _rFifoValid=0; reg rDataValid=0, _rDataValid=0; assign BUF_DATA_REN = rRdState[0]; // Not S_SGR64_RD_WAIT assign VALID = rCapState[1]; // S_SGR64_CAP_RDY assign EMPTY = (BUF_DATA_EMPTY & rRdState[0]); // Not S_SGR64_RD_WAIT assign ADDR = rAddr; assign LEN = rLen; // Capture address and length as it comes out of the FIFO always @ (posedge CLK) begin rRdState <= #1 (RST ? `S_SGR64_RD_0 : _rRdState); rCapState <= #1 (RST ? `S_SGR64_CAP_0 : _rCapState); rData <= #1 _rData; rFifoValid <= #1 (RST ? 1'd0 : _rFifoValid); rDataValid <= #1 (RST ? 1'd0 : _rDataValid); rAddr <= #1 _rAddr; rLen <= #1 _rLen; end always @ (*) begin _rRdState = rRdState; _rCapState = rCapState; _rAddr = rAddr; _rLen = rLen; _rData = BUF_DATA; _rFifoValid = (BUF_DATA_REN & !BUF_DATA_EMPTY); _rDataValid = rFifoValid; case (rCapState) `S_SGR64_CAP_0: begin if (rDataValid) begin _rAddr = rData; _rCapState = `S_SGR64_CAP_1; end end `S_SGR64_CAP_1: begin if (rDataValid) begin _rLen = rData[31:0]; _rCapState = `S_SGR64_CAP_RDY; end end `S_SGR64_CAP_RDY: begin if (REN) _rCapState = `S_SGR64_CAP_0; end default: begin _rCapState = `S_SGR64_CAP_0; end endcase case (rRdState) `S_SGR64_RD_0: begin // Read from the sg data FIFO if (!BUF_DATA_EMPTY) _rRdState = `S_SGR64_RD_1; end `S_SGR64_RD_1: begin // Read from the sg data FIFO if (!BUF_DATA_EMPTY) _rRdState = `S_SGR64_RD_WAIT; end `S_SGR64_RD_WAIT: begin // Wait for the data to be consumed if (REN) _rRdState = `S_SGR64_RD_0; end default: begin _rRdState = `S_SGR64_RD_0; end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/sg_list_requester.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: sg_list_requester.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Receives scatter gather address/length info and requests // the scatter gather data from the RX engine. Monitors the state of the scatter // gather FIFO to make sure it can accommodate the requested data. Also signals // when the entire scatter gather data has been received so the buffer can be // overwritten with new data. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_SGREQ_IDLE 8'b0000_0001 `define S_SGREQ_WAIT_0 8'b0000_0010 `define S_SGREQ_WAIT_1 8'b0000_0100 `define S_SGREQ_CHECK 8'b0000_1000 `define S_SGREQ_ISSUE 8'b0001_0000 `define S_SGREQ_UPDATE 8'b0010_0000 `define S_SGREQ_COUNT 8'b0100_0000 `define S_SGREQ_FLUSH 8'b1000_0000 module sg_list_requester #( parameter C_FIFO_DATA_WIDTH = 9'd64, parameter C_FIFO_DEPTH = 1024, parameter C_MAX_READ_REQ = 2, // Max read: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B // Local parameters parameter C_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_FIFO_DEPTH))+1), parameter C_WORDS_PER_ELEM = 4, parameter C_MAX_ELEMS = 200, parameter C_MAX_ENTRIES = (C_MAX_ELEMS*C_WORDS_PER_ELEM), parameter C_FIFO_COUNT_THRESH = C_FIFO_DEPTH - C_MAX_ENTRIES ) ( input CLK, input RST, input [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // Maximum read payload: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B input USER_RST, // User reset, should clear FIFO data too output BUF_RECVD, // Signals when scatter gather buffer received input [31:0] BUF_DATA, // Buffer data input BUF_LEN_VALID, // Buffer length valid input BUF_ADDR_HI_VALID, // Buffer high address valid input BUF_ADDR_LO_VALID, // Buffer low address valid input [C_FIFO_DEPTH_WIDTH-1:0] FIFO_COUNT, // Scatter gather FIFO count output FIFO_FLUSH, // Scatter gather FIFO flush request input FIFO_FLUSHED, // Scatter gather FIFO flushed output FIFO_RST, // Scatter gather FIFO data reset request output RX_REQ, // Issue a read request output [63:0] RX_ADDR, // Request address output [9:0] RX_LEN, // Request length input RX_REQ_ACK, // Request has been issued input RX_DONE // Request has completed (data received) ); `include "common_functions.v" reg [31:0] rData=0, _rData=0; reg rAddrHiValid=0, _rAddrHiValid=0; reg rAddrLoValid=0, _rAddrLoValid=0; reg rLenValid=0, _rLenValid=0; (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [7:0] rState=`S_SGREQ_IDLE, _rState=`S_SGREQ_IDLE; reg rDone=0, _rDone=0; reg rDelay=0, _rDelay=0; reg [2:0] rCarry=0, _rCarry=0; reg [3:0] rValsProp=0, _rValsProp=0; reg [63:0] rAddr=64'd0, _rAddr=64'd0; reg [31:0] rBufWords=0, _rBufWords=0; reg [10:0] rPageRem=0, _rPageRem=0; reg rPageSpill=0, _rPageSpill=0; reg [10:0] rPreLen=0, _rPreLen=0; reg [2:0] rMaxPayloadTrain=0, _rMaxPayloadTrain=0; reg [2:0] rMaxPayloadShift=0, _rMaxPayloadShift=0; reg [9:0] rMaxPayload=0, _rMaxPayload=0; reg rPayloadSpill=0, _rPayloadSpill=0; reg [9:0] rLen=0, _rLen=0; reg rBufWordsEQ0Hi=0, _rBufWordsEQ0Hi=0; reg rBufWordsEQ0Lo=0, _rBufWordsEQ0Lo=0; reg rUserRst=0, _rUserRst=0; reg rRecvdAll=0, _rRecvdAll=0; reg [10:0] rAckCount=0, _rAckCount=0; assign BUF_RECVD = rDone; assign FIFO_FLUSH = rState[7]; // S_SGREQ_FLUSH assign FIFO_RST = (rUserRst & rState[0]); // S_SGREQ_IDLE assign RX_ADDR = rAddr; assign RX_LEN = rLen; assign RX_REQ = rState[4]; // S_SGREQ_ISSUE // Buffer signals coming from outside the rx_port. always @ (posedge CLK) begin rData <= #1 _rData; rAddrHiValid <= #1 _rAddrHiValid; rAddrLoValid <= #1 _rAddrLoValid; rLenValid <= #1 _rLenValid; end always @ (*) begin _rData = BUF_DATA; _rAddrHiValid = BUF_ADDR_HI_VALID; _rAddrLoValid = BUF_ADDR_LO_VALID; _rLenValid = BUF_LEN_VALID; end // Handle requesting the next scatter gather buffer data. wire [9:0] wAddrLoInv = ~rAddr[11:2]; always @ (posedge CLK) begin rState <= #1 (RST ? `S_SGREQ_IDLE : _rState); rDone <= #1 (RST ? 1'd0 : _rDone); rDelay <= #1 _rDelay; rAddr <= #1 _rAddr; rCarry <= #1 _rCarry; rBufWords <= #1 _rBufWords; rValsProp <= #1 _rValsProp; rPageRem <= #1 _rPageRem; rPageSpill <= #1 _rPageSpill; rPreLen <= #1 _rPreLen; rMaxPayloadTrain <= #1 _rMaxPayloadTrain; rMaxPayloadShift <= #1 _rMaxPayloadShift; rMaxPayload <= #1 _rMaxPayload; rPayloadSpill <= #1 _rPayloadSpill; rLen <= #1 _rLen; rBufWordsEQ0Hi <= #1 _rBufWordsEQ0Hi; rBufWordsEQ0Lo <= #1 _rBufWordsEQ0Lo; rUserRst <= #1 (RST ? 1'd0 : _rUserRst); end always @ (*) begin _rState = rState; _rDone = rDone; _rDelay = rDelay; _rUserRst = ((rUserRst & !rState[0]) | USER_RST); _rValsProp = ((rValsProp<<1) | RX_REQ_ACK); {_rCarry[0], _rAddr[15:0]} = (rAddrLoValid ? rData[15:0] : (rAddr[15:0] + ({12{RX_REQ_ACK}} & {2'b0,rLen}<<2))); {_rCarry[1], _rAddr[31:16]} = (rAddrLoValid ? rData[31:16] : (rAddr[31:16] + rCarry[0])); {_rCarry[2], _rAddr[47:32]} = (rAddrHiValid ? rData[15:0] : (rAddr[47:32] + rCarry[1])); _rAddr[63:48] = (rAddrHiValid ? rData[31:16] : (rAddr[63:48] + rCarry[2])); _rBufWords = (rLenValid ? rData : rBufWords) - ({10{RX_REQ_ACK}} & rLen); _rPageRem = (wAddrLoInv + 1'd1); _rPageSpill = (rBufWords > rPageRem); _rPreLen = (rPageSpill ? rPageRem : rBufWords[10:0]); _rMaxPayloadTrain = (CONFIG_MAX_READ_REQUEST_SIZE > 3'd4 ? 3'd4 : CONFIG_MAX_READ_REQUEST_SIZE); _rMaxPayloadShift = (C_MAX_READ_REQ[2:0] < rMaxPayloadTrain ? C_MAX_READ_REQ[2:0] : rMaxPayloadTrain); _rMaxPayload = (6'd32< rMaxPayload); _rLen = (rPayloadSpill ? rMaxPayload : rPreLen[9:0]); _rBufWordsEQ0Hi = (16'd0 == rBufWords[31:16]); _rBufWordsEQ0Lo = (16'd0 == rBufWords[15:0]); case (rState) `S_SGREQ_IDLE: begin // Wait for addr & length _rDone = 0; if (rLenValid) _rState = `S_SGREQ_WAIT_0; end `S_SGREQ_WAIT_0: begin // Wait 1 cycle for values to propagate _rDelay = 0; _rState = `S_SGREQ_WAIT_1; end `S_SGREQ_WAIT_1: begin // Wait 2 cycles for values to propagate _rDelay = 1; if (rDelay) _rState = `S_SGREQ_CHECK; end `S_SGREQ_CHECK: begin // Wait for space to be made available if (FIFO_COUNT < C_FIFO_COUNT_THRESH) _rState = `S_SGREQ_ISSUE; else if (rUserRst) _rState = `S_SGREQ_COUNT; end `S_SGREQ_ISSUE: begin // Wait for read request to be serviced if (RX_REQ_ACK) _rState = `S_SGREQ_UPDATE; end `S_SGREQ_UPDATE: begin // Update the address and length if (rUserRst | (rBufWordsEQ0Hi & rBufWordsEQ0Lo)) _rState = `S_SGREQ_COUNT; else if (rValsProp[3]) _rState = `S_SGREQ_ISSUE; end `S_SGREQ_COUNT: begin // Wait for read data to arrive if (rRecvdAll) _rState = `S_SGREQ_FLUSH; end `S_SGREQ_FLUSH: begin // Wait for read data to arrive if (FIFO_FLUSHED) begin _rDone = !rUserRst; _rState = `S_SGREQ_IDLE; end end default: begin _rState = `S_SGREQ_IDLE; end endcase end // Keep track of requests made and requests completed so we know when all // the outstanding data has been received. always @ (posedge CLK) begin rAckCount <= #1 (RST ? 10'd0 : _rAckCount); rRecvdAll <= #1 _rRecvdAll; end always @ (*) begin // Track REQ_DONE and SG_DONE to maintain an outstanding request count. _rRecvdAll = (rAckCount == 10'd0); if (rState[0]) // S_SGREQ_IDLE _rAckCount = 0; else _rAckCount = rAckCount + RX_REQ_ACK - RX_DONE; end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/sync_fifo.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: sync_fifo.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: A synchronous capable parameterized FIFO. As with all // traditional FIFOs, the RD_DATA will be valid one cycle following a RD_EN // assertion. EMPTY will remain low until the cycle following the last RD_EN // assertion. Note, that EMPTY may actually be high on the same cycle that // RD_DATA contains valid data. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module sync_fifo #( parameter C_WIDTH = 32, // Data bus width parameter C_DEPTH = 1024, // Depth of the FIFO parameter C_PROVIDE_COUNT = 0, // Include code for counts // Local parameters parameter C_REAL_DEPTH = 2**clog2(C_DEPTH), parameter C_DEPTH_BITS = clog2s(C_REAL_DEPTH), parameter C_DEPTH_P1_BITS = clog2s(C_REAL_DEPTH+1) ) ( input CLK, // Clock input RST, // Sync reset, active high input [C_WIDTH-1:0] WR_DATA, // Write data input input WR_EN, // Write enable, high active output [C_WIDTH-1:0] RD_DATA, // Read data output input RD_EN, // Read enable, high active output FULL, // Full condition output EMPTY, // Empty condition output [C_DEPTH_P1_BITS-1:0] COUNT // Data count ); `include "common_functions.v" reg [C_DEPTH_BITS:0] rWrPtr=0, _rWrPtr=0; reg [C_DEPTH_BITS:0] rWrPtrPlus1=1, _rWrPtrPlus1=1; reg [C_DEPTH_BITS:0] rRdPtr=0, _rRdPtr=0; reg [C_DEPTH_BITS:0] rRdPtrPlus1=1, _rRdPtrPlus1=1; reg rFull=0, _rFull=0; reg rEmpty=1, _rEmpty=1; // Memory block (synthesis attributes applied to this module will // determine the memory option). ram_1clk_1w_1r #(.C_RAM_WIDTH(C_WIDTH), .C_RAM_DEPTH(C_REAL_DEPTH)) mem ( .CLK(CLK), .ADDRA(rWrPtr[C_DEPTH_BITS-1:0]), .WEA(WR_EN & !rFull), .DINA(WR_DATA), .ADDRB(rRdPtr[C_DEPTH_BITS-1:0]), .DOUTB(RD_DATA) ); // Write pointer logic. always @ (posedge CLK) begin if (RST) begin rWrPtr <= #1 0; rWrPtrPlus1 <= #1 1; end else begin rWrPtr <= #1 _rWrPtr; rWrPtrPlus1 <= #1 _rWrPtrPlus1; end end always @ (*) begin if (WR_EN & !rFull) begin _rWrPtr = rWrPtrPlus1; _rWrPtrPlus1 = rWrPtrPlus1 + 1'd1; end else begin _rWrPtr = rWrPtr; _rWrPtrPlus1 = rWrPtrPlus1; end end // Read pointer logic. always @ (posedge CLK) begin if (RST) begin rRdPtr <= #1 0; rRdPtrPlus1 <= #1 1; end else begin rRdPtr <= #1 _rRdPtr; rRdPtrPlus1 <= #1 _rRdPtrPlus1; end end always @ (*) begin if (RD_EN & !rEmpty) begin _rRdPtr = rRdPtrPlus1; _rRdPtrPlus1 = rRdPtrPlus1 + 1'd1; end else begin _rRdPtr = rRdPtr; _rRdPtrPlus1 = rRdPtrPlus1; end end // Calculate empty assign EMPTY = rEmpty; always @ (posedge CLK) begin rEmpty <= #1 (RST ? 1'd1 : _rEmpty); end always @ (*) begin _rEmpty = (rWrPtr == rRdPtr) || (RD_EN && !rEmpty && (rWrPtr == rRdPtrPlus1)); end // Calculate full assign FULL = rFull; always @ (posedge CLK) begin rFull <= #1 (RST ? 1'd0 : _rFull); end always @ (*) begin _rFull = ((rWrPtr[C_DEPTH_BITS-1:0] == rRdPtr[C_DEPTH_BITS-1:0]) && (rWrPtr[C_DEPTH_BITS] != rRdPtr[C_DEPTH_BITS])) || (WR_EN && (rWrPtrPlus1[C_DEPTH_BITS-1:0] == rRdPtr[C_DEPTH_BITS-1:0]) && (rWrPtrPlus1[C_DEPTH_BITS] != rRdPtr[C_DEPTH_BITS])); end generate if (C_PROVIDE_COUNT) begin: provide_count reg [C_DEPTH_BITS:0] rCount=0, _rCount=0; assign COUNT = (rFull ? C_REAL_DEPTH[C_DEPTH_P1_BITS-1:0] : rCount); // Calculate read count always @ (posedge CLK) begin if (RST) rCount <= #1 0; else rCount <= #1 _rCount; end always @ (*) begin _rCount = (rWrPtr - rRdPtr); end end else begin: provide_no_count assign COUNT = 0; end endgenerate endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/syncff.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: syncff.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: A back to back FF design to mitigate metastable issues // when crossing clock domains. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module syncff( CLK, IN_ASYNC, OUT_SYNC ); input CLK; input IN_ASYNC; output OUT_SYNC; wire wSyncFFQ; ff syncFF ( .CLK(CLK), .D(IN_ASYNC), .Q(wSyncFFQ) ); ff metaFF ( .CLK(CLK), .D(wSyncFFQ), .Q(OUT_SYNC) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/translation_layer.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 19:27:32 05/15/2014 // Design Name: // Module Name: translation_layer // Project Name: // Target Devices: // Tool versions: // Description: // Translates AXI (Xilinx) or Avalon (Altera) signals into Unified (architecture // independent) streaming signals for riffa. The altera RX interface has a 1 cycle // latency because it needs to produce several metadata signals that are not // provided by the altera PCIe Core. // // Dependencies: None // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module translation_layer #(parameter C_ALTERA = 1'b1, parameter C_PCI_DATA_WIDTH = 9'd128, parameter C_TX_READY_LATENCY = 3'd1) ( input CLK, input RST_IN, // Xilinx Signals input [C_PCI_DATA_WIDTH-1:0] M_AXIS_RX_TDATA, input [(C_PCI_DATA_WIDTH/8)-1:0] M_AXIS_RX_TKEEP, input M_AXIS_RX_TLAST, // Not used in the 128 bit interface input M_AXIS_RX_TVALID, output M_AXIS_RX_TREADY, input [4:0] IS_SOF, input [4:0] IS_EOF, input RERR_FWD, output [C_PCI_DATA_WIDTH-1:0] S_AXIS_TX_TDATA, output [(C_PCI_DATA_WIDTH/8)-1:0] S_AXIS_TX_TKEEP, output S_AXIS_TX_TLAST, output S_AXIS_TX_TVALID, output S_AXIS_SRC_DSC, input S_AXIS_TX_TREADY, input [15:0] COMPLETER_ID, input CFG_BUS_MSTR_ENABLE, input [5:0] CFG_LINK_WIDTH, // cfg_lstatus[9:4] (from Link Status Register): 000001=x1, 000010=x2, 000100=x4, 001000=x8, 001100=x12, 010000=x16, 100000=x32, others=? input [1:0] CFG_LINK_RATE, // cfg_lstatus[1:0] (from Link Status Register): 01=2.5GT/s, 10=5.0GT/s, others=? input [2:0] CFG_MAX_READ_REQUEST_SIZE, // cfg_dcommand[14:12] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B input [2:0] CFG_MAX_PAYLOAD_SIZE, // cfg_dcommand[7:5] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B input CFG_INTERRUPT_MSIEN, // 1 if MSI interrupts are enable, 0 if only legacy are supported input CFG_INTERRUPT_RDY, // High when interrupt is able to be sent output CFG_INTERRUPT, // High to request interrupt, when both CFG_INTERRUPT_RDY and CFG_INTERRUPT are high, interrupt is sent); input RCB, input [11:0] MAX_RC_CPLD, // Receive credit limit for data (be sure fc_sel == 001) input [7:0] MAX_RC_CPLH, // Receive credit limit for headers (be sure fc_sel == 001) // Altera Signals input [C_PCI_DATA_WIDTH-1:0] RX_ST_DATA, input [0:0] RX_ST_EOP, input [0:0] RX_ST_SOP, input [0:0] RX_ST_VALID, output RX_ST_READY, input [0:0] RX_ST_EMPTY, output [C_PCI_DATA_WIDTH-1:0] TX_ST_DATA, output [0:0] TX_ST_VALID, input TX_ST_READY, output [0:0] TX_ST_EOP, output [0:0] TX_ST_SOP, output [0:0] TX_ST_EMPTY, input [31:0] TL_CFG_CTL, input [3:0] TL_CFG_ADD, input [52:0] TL_CFG_STS, input [7:0] KO_CPL_SPC_HEADER, input [11:0] KO_CPL_SPC_DATA, input APP_MSI_ACK, output APP_MSI_REQ, // Unified Signals output [C_PCI_DATA_WIDTH-1:0] RX_DATA, output RX_DATA_VALID, input RX_DATA_READY, output [(C_PCI_DATA_WIDTH/8)-1:0] RX_DATA_BYTE_ENABLE, output RX_TLP_END_FLAG, output [3:0] RX_TLP_END_OFFSET, output RX_TLP_START_FLAG, output [3:0] RX_TLP_START_OFFSET, output RX_TLP_ERROR_POISON, input [C_PCI_DATA_WIDTH-1:0] TX_DATA, input [(C_PCI_DATA_WIDTH/8)-1:0] TX_DATA_BYTE_ENABLE, input TX_TLP_END_FLAG, input TX_TLP_START_FLAG, input TX_DATA_VALID, input TX_TLP_ERROR_POISON, output TX_DATA_READY, output [15:0] CONFIG_COMPLETER_ID, output CONFIG_BUS_MASTER_ENABLE, output [5:0] CONFIG_LINK_WIDTH, // cfg_lstatus[9:4] (from Link Status Register): 000001=x1, 000010=x2, 000100=x4, 001000=x8, 001100=x12, 010000=x16, 100000=x32, others=? output [1:0] CONFIG_LINK_RATE, // cfg_lstatus[1:0] (from Link Status Register): 01=2.5GT/s, 10=5.0GT/s, others=? output [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // cfg_dcommand[14:12] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B output [2:0] CONFIG_MAX_PAYLOAD_SIZE, // cfg_dcommand[7:5] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B output CONFIG_INTERRUPT_MSIENABLE, // 1 if MSI interrupts are enable, 0 if only legacy are supported output [11:0] CONFIG_MAX_CPL_DATA, // Receive credit limit for data output [7:0] CONFIG_MAX_CPL_HDR, // Receive credit limit for headers output CONFIG_CPL_BOUNDARY_SEL, // Read completion boundary (0=64 bytes, 1=128 bytes)w output INTR_MSI_RDY, // High when interrupt is able to be sent input INTR_MSI_REQUEST // High to request interrupt, when both CFG_INTERRUPT_RDY and CFG_INTERRUPT are hi ); generate if (C_PCI_DATA_WIDTH == 9'd32) begin : endpoint32 translation_layer_32 #(.C_ALTERA(1'b0), .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH)) tl32_inst (/*AUTOINST*/ // Outputs .M_AXIS_RX_TREADY (M_AXIS_RX_TREADY), .S_AXIS_TX_TDATA (S_AXIS_TX_TDATA[C_PCI_DATA_WIDTH-1:0]), .S_AXIS_TX_TKEEP (S_AXIS_TX_TKEEP[(C_PCI_DATA_WIDTH/8)-1:0]), .S_AXIS_TX_TLAST (S_AXIS_TX_TLAST), .S_AXIS_TX_TVALID (S_AXIS_TX_TVALID), .S_AXIS_SRC_DSC (S_AXIS_SRC_DSC), .CFG_INTERRUPT (CFG_INTERRUPT), .RX_ST_READY (RX_ST_READY), .TX_ST_DATA (TX_ST_DATA[C_PCI_DATA_WIDTH-1:0]), .TX_ST_VALID (TX_ST_VALID[0:0]), .TX_ST_EOP (TX_ST_EOP[0:0]), .TX_ST_SOP (TX_ST_SOP[0:0]), .TX_ST_EMPTY (TX_ST_EMPTY[0:0]), .APP_MSI_REQ (APP_MSI_REQ), .RX_DATA (RX_DATA[C_PCI_DATA_WIDTH-1:0]), .RX_DATA_VALID (RX_DATA_VALID), .RX_DATA_BYTE_ENABLE (RX_DATA_BYTE_ENABLE[(C_PCI_DATA_WIDTH/8)-1:0]), .RX_TLP_END_FLAG (RX_TLP_END_FLAG), .RX_TLP_END_OFFSET (RX_TLP_END_OFFSET[3:0]), .RX_TLP_START_FLAG (RX_TLP_START_FLAG), .RX_TLP_START_OFFSET (RX_TLP_START_OFFSET[3:0]), .RX_TLP_ERROR_POISON (RX_TLP_ERROR_POISON), .TX_DATA_READY (TX_DATA_READY), .CONFIG_COMPLETER_ID (CONFIG_COMPLETER_ID[15:0]), .CONFIG_BUS_MASTER_ENABLE(CONFIG_BUS_MASTER_ENABLE), .CONFIG_LINK_WIDTH (CONFIG_LINK_WIDTH[5:0]), .CONFIG_LINK_RATE (CONFIG_LINK_RATE[1:0]), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE[2:0]), .CONFIG_MAX_PAYLOAD_SIZE(CONFIG_MAX_PAYLOAD_SIZE[2:0]), .CONFIG_INTERRUPT_MSIENABLE(CONFIG_INTERRUPT_MSIENABLE), .CONFIG_MAX_CPL_DATA (CONFIG_MAX_CPL_DATA[11:0]), .CONFIG_MAX_CPL_HDR (CONFIG_MAX_CPL_HDR[7:0]), .CONFIG_CPL_BOUNDARY_SEL(CONFIG_CPL_BOUNDARY_SEL), .INTR_MSI_RDY (INTR_MSI_RDY), // Inputs .CLK (CLK), .RST_IN (RST_IN), .M_AXIS_RX_TDATA (M_AXIS_RX_TDATA[C_PCI_DATA_WIDTH-1:0]), .M_AXIS_RX_TKEEP (M_AXIS_RX_TKEEP[(C_PCI_DATA_WIDTH/8)-1:0]), .M_AXIS_RX_TLAST (M_AXIS_RX_TLAST), .M_AXIS_RX_TVALID (M_AXIS_RX_TVALID), .IS_SOF (IS_SOF[(C_PCI_DATA_WIDTH/32):0]), .IS_EOF (IS_EOF[(C_PCI_DATA_WIDTH/32):0]), .RERR_FWD (RERR_FWD), .S_AXIS_TX_TREADY (S_AXIS_TX_TREADY), .COMPLETER_ID (COMPLETER_ID[15:0]), .CFG_BUS_MSTR_ENABLE (CFG_BUS_MSTR_ENABLE), .CFG_LINK_WIDTH (CFG_LINK_WIDTH[5:0]), .CFG_LINK_RATE (CFG_LINK_RATE[1:0]), .CFG_MAX_READ_REQUEST_SIZE(CFG_MAX_READ_REQUEST_SIZE[2:0]), .CFG_MAX_PAYLOAD_SIZE (CFG_MAX_PAYLOAD_SIZE[2:0]), .CFG_INTERRUPT_MSIEN (CFG_INTERRUPT_MSIEN), .CFG_INTERRUPT_RDY (CFG_INTERRUPT_RDY), .RCB (RCB), .MAX_RC_CPLD (MAX_RC_CPLD[11:0]), .MAX_RC_CPLH (MAX_RC_CPLH[7:0]), .RX_ST_DATA (RX_ST_DATA[C_PCI_DATA_WIDTH-1:0]), .RX_ST_EOP (RX_ST_EOP[0:0]), .RX_ST_VALID (RX_ST_VALID[0:0]), .RX_ST_SOP (RX_ST_SOP[0:0]), .RX_ST_EMPTY (RX_ST_EMPTY[0:0]), .TX_ST_READY (TX_ST_READY), .TL_CFG_CTL (TL_CFG_CTL[31:0]), .TL_CFG_ADD (TL_CFG_ADD[3:0]), .TL_CFG_STS (TL_CFG_STS[52:0]), .KO_CPL_SPC_HEADER (KO_CPL_SPC_HEADER[7:0]), .KO_CPL_SPC_DATA (KO_CPL_SPC_DATA[11:0]), .APP_MSI_ACK (APP_MSI_ACK), .RX_DATA_READY (RX_DATA_READY), .TX_DATA (TX_DATA[C_PCI_DATA_WIDTH-1:0]), .TX_DATA_BYTE_ENABLE (TX_DATA_BYTE_ENABLE[(C_PCI_DATA_WIDTH/8)-1:0]), .TX_TLP_END_FLAG (TX_TLP_END_FLAG), .TX_DATA_VALID (TX_DATA_VALID), .TX_TLP_ERROR_POISON (TX_TLP_ERROR_POISON), .INTR_MSI_REQUEST (INTR_MSI_REQUEST)); end else if (C_PCI_DATA_WIDTH == 9'd64) begin : endpoint64 translation_layer_64 #(.C_ALTERA(C_ALTERA), .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH), .C_TX_READY_LATENCY(C_TX_READY_LATENCY)) tl64_inst (/*AUTOINST*/ // Outputs .M_AXIS_RX_TREADY (M_AXIS_RX_TREADY), .S_AXIS_TX_TDATA (S_AXIS_TX_TDATA[C_PCI_DATA_WIDTH-1:0]), .S_AXIS_TX_TKEEP (S_AXIS_TX_TKEEP[(C_PCI_DATA_WIDTH/8)-1:0]), .S_AXIS_TX_TLAST (S_AXIS_TX_TLAST), .S_AXIS_TX_TVALID (S_AXIS_TX_TVALID), .S_AXIS_SRC_DSC (S_AXIS_SRC_DSC), .CFG_INTERRUPT (CFG_INTERRUPT), .RX_ST_READY (RX_ST_READY), .TX_ST_DATA (TX_ST_DATA[C_PCI_DATA_WIDTH-1:0]), .TX_ST_VALID (TX_ST_VALID[0:0]), .TX_ST_EOP (TX_ST_EOP[0:0]), .TX_ST_SOP (TX_ST_SOP[0:0]), .TX_ST_EMPTY (TX_ST_EMPTY[0:0]), .APP_MSI_REQ (APP_MSI_REQ), .RX_DATA (RX_DATA[C_PCI_DATA_WIDTH-1:0]), .RX_DATA_VALID (RX_DATA_VALID), .RX_DATA_BYTE_ENABLE (RX_DATA_BYTE_ENABLE[(C_PCI_DATA_WIDTH/8)-1:0]), .RX_TLP_END_FLAG (RX_TLP_END_FLAG), .RX_TLP_END_OFFSET (RX_TLP_END_OFFSET[3:0]), .RX_TLP_START_FLAG (RX_TLP_START_FLAG), .RX_TLP_START_OFFSET (RX_TLP_START_OFFSET[3:0]), .RX_TLP_ERROR_POISON (RX_TLP_ERROR_POISON), .TX_DATA_READY (TX_DATA_READY), .CONFIG_COMPLETER_ID (CONFIG_COMPLETER_ID[15:0]), .CONFIG_BUS_MASTER_ENABLE(CONFIG_BUS_MASTER_ENABLE), .CONFIG_LINK_WIDTH (CONFIG_LINK_WIDTH[5:0]), .CONFIG_LINK_RATE (CONFIG_LINK_RATE[1:0]), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE[2:0]), .CONFIG_MAX_PAYLOAD_SIZE(CONFIG_MAX_PAYLOAD_SIZE[2:0]), .CONFIG_INTERRUPT_MSIENABLE(CONFIG_INTERRUPT_MSIENABLE), .CONFIG_MAX_CPL_DATA (CONFIG_MAX_CPL_DATA[11:0]), .CONFIG_MAX_CPL_HDR (CONFIG_MAX_CPL_HDR[7:0]), .CONFIG_CPL_BOUNDARY_SEL(CONFIG_CPL_BOUNDARY_SEL), .INTR_MSI_RDY (INTR_MSI_RDY), // Inputs .CLK (CLK), .RST_IN (RST_IN), .M_AXIS_RX_TDATA (M_AXIS_RX_TDATA[C_PCI_DATA_WIDTH-1:0]), .M_AXIS_RX_TKEEP (M_AXIS_RX_TKEEP[(C_PCI_DATA_WIDTH/8)-1:0]), .M_AXIS_RX_TLAST (M_AXIS_RX_TLAST), .M_AXIS_RX_TVALID (M_AXIS_RX_TVALID), .IS_SOF (IS_SOF[(C_PCI_DATA_WIDTH/32):0]), .IS_EOF (IS_EOF[(C_PCI_DATA_WIDTH/32):0]), .RERR_FWD (RERR_FWD), .S_AXIS_TX_TREADY (S_AXIS_TX_TREADY), .COMPLETER_ID (COMPLETER_ID[15:0]), .CFG_BUS_MSTR_ENABLE (CFG_BUS_MSTR_ENABLE), .CFG_LINK_WIDTH (CFG_LINK_WIDTH[5:0]), .CFG_LINK_RATE (CFG_LINK_RATE[1:0]), .CFG_MAX_READ_REQUEST_SIZE(CFG_MAX_READ_REQUEST_SIZE[2:0]), .CFG_MAX_PAYLOAD_SIZE (CFG_MAX_PAYLOAD_SIZE[2:0]), .CFG_INTERRUPT_MSIEN (CFG_INTERRUPT_MSIEN), .CFG_INTERRUPT_RDY (CFG_INTERRUPT_RDY), .RCB (RCB), .MAX_RC_CPLD (MAX_RC_CPLD[11:0]), .MAX_RC_CPLH (MAX_RC_CPLH[7:0]), .RX_ST_DATA (RX_ST_DATA[C_PCI_DATA_WIDTH-1:0]), .RX_ST_EOP (RX_ST_EOP[0:0]), .RX_ST_VALID (RX_ST_VALID[0:0]), .RX_ST_SOP (RX_ST_SOP[0:0]), .RX_ST_EMPTY (RX_ST_EMPTY[0:0]), .TX_ST_READY (TX_ST_READY), .TL_CFG_CTL (TL_CFG_CTL[31:0]), .TL_CFG_ADD (TL_CFG_ADD[3:0]), .TL_CFG_STS (TL_CFG_STS[52:0]), .KO_CPL_SPC_HEADER (KO_CPL_SPC_HEADER[7:0]), .KO_CPL_SPC_DATA (KO_CPL_SPC_DATA[11:0]), .APP_MSI_ACK (APP_MSI_ACK), .RX_DATA_READY (RX_DATA_READY), .TX_DATA (TX_DATA[C_PCI_DATA_WIDTH-1:0]), .TX_DATA_BYTE_ENABLE (TX_DATA_BYTE_ENABLE[(C_PCI_DATA_WIDTH/8)-1:0]), .TX_TLP_END_FLAG (TX_TLP_END_FLAG), .TX_TLP_START_FLAG (TX_TLP_START_FLAG), .TX_DATA_VALID (TX_DATA_VALID), .TX_TLP_ERROR_POISON (TX_TLP_ERROR_POISON), .INTR_MSI_REQUEST (INTR_MSI_REQUEST)); end else if (C_PCI_DATA_WIDTH == 9'd128) begin : endpoint128 translation_layer_128 #(.C_ALTERA(C_ALTERA), .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH), .C_TX_READY_LATENCY(C_TX_READY_LATENCY)) tl128_inst (/*AUTOINST*/ // Outputs .M_AXIS_RX_TREADY (M_AXIS_RX_TREADY), .S_AXIS_TX_TDATA (S_AXIS_TX_TDATA[C_PCI_DATA_WIDTH-1:0]), .S_AXIS_TX_TKEEP (S_AXIS_TX_TKEEP[(C_PCI_DATA_WIDTH/8)-1:0]), .S_AXIS_TX_TLAST (S_AXIS_TX_TLAST), .S_AXIS_TX_TVALID (S_AXIS_TX_TVALID), .S_AXIS_SRC_DSC (S_AXIS_SRC_DSC), .CFG_INTERRUPT (CFG_INTERRUPT), .RX_ST_READY (RX_ST_READY), .TX_ST_DATA (TX_ST_DATA[C_PCI_DATA_WIDTH-1:0]), .TX_ST_VALID (TX_ST_VALID[0:0]), .TX_ST_EOP (TX_ST_EOP[0:0]), .TX_ST_SOP (TX_ST_SOP[0:0]), .TX_ST_EMPTY (TX_ST_EMPTY[0:0]), .APP_MSI_REQ (APP_MSI_REQ), .RX_DATA (RX_DATA[C_PCI_DATA_WIDTH-1:0]), .RX_DATA_VALID (RX_DATA_VALID), .RX_TLP_END_FLAG (RX_TLP_END_FLAG), .RX_TLP_END_OFFSET (RX_TLP_END_OFFSET[3:0]), .RX_TLP_START_FLAG (RX_TLP_START_FLAG), .RX_TLP_START_OFFSET (RX_TLP_START_OFFSET[3:0]), .RX_TLP_ERROR_POISON (RX_TLP_ERROR_POISON), .TX_DATA_READY (TX_DATA_READY), .CONFIG_COMPLETER_ID (CONFIG_COMPLETER_ID[15:0]), .CONFIG_BUS_MASTER_ENABLE(CONFIG_BUS_MASTER_ENABLE), .CONFIG_LINK_WIDTH (CONFIG_LINK_WIDTH[5:0]), .CONFIG_LINK_RATE (CONFIG_LINK_RATE[1:0]), .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE[2:0]), .CONFIG_MAX_PAYLOAD_SIZE(CONFIG_MAX_PAYLOAD_SIZE[2:0]), .CONFIG_INTERRUPT_MSIENABLE(CONFIG_INTERRUPT_MSIENABLE), .CONFIG_MAX_CPL_DATA (CONFIG_MAX_CPL_DATA[11:0]), .CONFIG_MAX_CPL_HDR (CONFIG_MAX_CPL_HDR[7:0]), .CONFIG_CPL_BOUNDARY_SEL(CONFIG_CPL_BOUNDARY_SEL), .INTR_MSI_RDY (INTR_MSI_RDY), // Inputs .CLK (CLK), .RST_IN (RST_IN), .M_AXIS_RX_TDATA (M_AXIS_RX_TDATA[C_PCI_DATA_WIDTH-1:0]), .M_AXIS_RX_TKEEP (M_AXIS_RX_TKEEP[(C_PCI_DATA_WIDTH/8)-1:0]), .M_AXIS_RX_TLAST (M_AXIS_RX_TLAST), .M_AXIS_RX_TVALID (M_AXIS_RX_TVALID), .IS_SOF (IS_SOF[(C_PCI_DATA_WIDTH/32):0]), .IS_EOF (IS_EOF[(C_PCI_DATA_WIDTH/32):0]), .RERR_FWD (RERR_FWD), .S_AXIS_TX_TREADY (S_AXIS_TX_TREADY), .COMPLETER_ID (COMPLETER_ID[15:0]), .CFG_BUS_MSTR_ENABLE (CFG_BUS_MSTR_ENABLE), .CFG_LINK_WIDTH (CFG_LINK_WIDTH[5:0]), .CFG_LINK_RATE (CFG_LINK_RATE[1:0]), .CFG_MAX_READ_REQUEST_SIZE(CFG_MAX_READ_REQUEST_SIZE[2:0]), .CFG_MAX_PAYLOAD_SIZE (CFG_MAX_PAYLOAD_SIZE[2:0]), .CFG_INTERRUPT_MSIEN (CFG_INTERRUPT_MSIEN), .CFG_INTERRUPT_RDY (CFG_INTERRUPT_RDY), .RCB (RCB), .MAX_RC_CPLD (MAX_RC_CPLD[11:0]), .MAX_RC_CPLH (MAX_RC_CPLH[7:0]), .RX_ST_DATA (RX_ST_DATA[C_PCI_DATA_WIDTH-1:0]), .RX_ST_EOP (RX_ST_EOP[0:0]), .RX_ST_VALID (RX_ST_VALID[0:0]), .RX_ST_SOP (RX_ST_SOP[0:0]), .RX_ST_EMPTY (RX_ST_EMPTY[0:0]), .TX_ST_READY (TX_ST_READY), .TL_CFG_CTL (TL_CFG_CTL[31:0]), .TL_CFG_ADD (TL_CFG_ADD[3:0]), .TL_CFG_STS (TL_CFG_STS[52:0]), .KO_CPL_SPC_HEADER (KO_CPL_SPC_HEADER[7:0]), .KO_CPL_SPC_DATA (KO_CPL_SPC_DATA[11:0]), .APP_MSI_ACK (APP_MSI_ACK), .RX_DATA_READY (RX_DATA_READY), .TX_DATA (TX_DATA[C_PCI_DATA_WIDTH-1:0]), .TX_DATA_BYTE_ENABLE (TX_DATA_BYTE_ENABLE[(C_PCI_DATA_WIDTH/8)-1:0]), .TX_TLP_END_FLAG (TX_TLP_END_FLAG), .TX_TLP_START_FLAG (TX_TLP_START_FLAG), .TX_DATA_VALID (TX_DATA_VALID), .TX_TLP_ERROR_POISON (TX_TLP_ERROR_POISON), .INTR_MSI_REQUEST (INTR_MSI_REQUEST)); end endgenerate endmodule // translation_layer ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/translation_layer_128.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- // ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 19:27:32 05/15/2014 // Design Name: // Module Name: translation_layer_128 // Project Name: // Target Devices: // Tool versions: // Description: // Translates AXI (Xilinx) or Avalon (Altera) signals into Unified (architecture // independent) streaming signals for riffa. The altera RX interface has a 1 cycle // latency because it needs to produce several metadata signals that are not // provided by the altera PCIe Core. // // Dependencies: None // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module translation_layer_128 #( parameter C_ALTERA = 1'b1, parameter C_PCI_DATA_WIDTH = 10'd128, parameter C_RX_READY_LATENCY = 3'd2, parameter C_TX_READY_LATENCY = 3'd2 ) ( input CLK, input RST_IN, // Xilinx Signals input [C_PCI_DATA_WIDTH-1:0] M_AXIS_RX_TDATA, input [(C_PCI_DATA_WIDTH/8)-1:0] M_AXIS_RX_TKEEP, input M_AXIS_RX_TLAST, // Not used in the 128 bit interface input M_AXIS_RX_TVALID, output M_AXIS_RX_TREADY, input [(C_PCI_DATA_WIDTH/32):0] IS_SOF, input [(C_PCI_DATA_WIDTH/32):0] IS_EOF, input RERR_FWD, output [C_PCI_DATA_WIDTH-1:0] S_AXIS_TX_TDATA, output [(C_PCI_DATA_WIDTH/8)-1:0] S_AXIS_TX_TKEEP, output S_AXIS_TX_TLAST, output S_AXIS_TX_TVALID, output S_AXIS_SRC_DSC, input S_AXIS_TX_TREADY, input [15:0] COMPLETER_ID, input CFG_BUS_MSTR_ENABLE, input [5:0] CFG_LINK_WIDTH, // cfg_lstatus[9:4] (from Link Status Register): 000001=x1, 000010=x2, 000100=x4, 001000=x8, 001100=x12, 010000=x16, 100000=x32, others=? input [1:0] CFG_LINK_RATE, // cfg_lstatus[1:0] (from Link Status Register): 01=2.5GT/s, 10=5.0GT/s, others=? input [2:0] CFG_MAX_READ_REQUEST_SIZE, // cfg_dcommand[14:12] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B input [2:0] CFG_MAX_PAYLOAD_SIZE, // cfg_dcommand[7:5] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B input CFG_INTERRUPT_MSIEN, // 1 if MSI interrupts are enable, 0 if only legacy are supported input CFG_INTERRUPT_RDY, // High when interrupt is able to be sent output CFG_INTERRUPT, // High to request interrupt, when both CFG_INTERRUPT_RDY and CFG_INTERRUPT are high, interrupt is sent) input RCB, input [11:0] MAX_RC_CPLD, // Receive credit limit for data (be sure fc_sel == 001) input [7:0] MAX_RC_CPLH, // Receive credit limit for headers (be sure fc_sel == 001) // Altera Signals input [C_PCI_DATA_WIDTH-1:0] RX_ST_DATA, input [0:0] RX_ST_EOP, input [0:0] RX_ST_VALID, output RX_ST_READY, input [0:0] RX_ST_SOP, input [0:0] RX_ST_EMPTY, output [C_PCI_DATA_WIDTH-1:0] TX_ST_DATA, output [0:0] TX_ST_VALID, input TX_ST_READY, output [0:0] TX_ST_EOP, output [0:0] TX_ST_SOP, output [0:0] TX_ST_EMPTY, input [31:0] TL_CFG_CTL, input [3:0] TL_CFG_ADD, input [52:0] TL_CFG_STS, input [7:0] KO_CPL_SPC_HEADER, input [11:0] KO_CPL_SPC_DATA, input APP_MSI_ACK, output APP_MSI_REQ, // Unified Signals output [C_PCI_DATA_WIDTH-1:0] RX_DATA, output RX_DATA_VALID, input RX_DATA_READY, output RX_TLP_END_FLAG, output [3:0] RX_TLP_END_OFFSET, output RX_TLP_START_FLAG, output [3:0] RX_TLP_START_OFFSET, output RX_TLP_ERROR_POISON, input [C_PCI_DATA_WIDTH-1:0] TX_DATA, input [(C_PCI_DATA_WIDTH/8)-1:0] TX_DATA_BYTE_ENABLE, input TX_TLP_END_FLAG, input TX_TLP_START_FLAG, input TX_DATA_VALID, input TX_TLP_ERROR_POISON, output TX_DATA_READY, output [15:0] CONFIG_COMPLETER_ID, output CONFIG_BUS_MASTER_ENABLE, output [5:0] CONFIG_LINK_WIDTH, // cfg_lstatus[9:4] (from Link Status Register): 000001=x1, 000010=x2, 000100=x4, 001000=x8, 001100=x12, 010000=x16, 100000=x32, others=? output [1:0] CONFIG_LINK_RATE, // cfg_lstatus[1:0] (from Link Status Register): 01=2.5GT/s, 10=5.0GT/s, others=? output [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // cfg_dcommand[14:12] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B output [2:0] CONFIG_MAX_PAYLOAD_SIZE, // cfg_dcommand[7:5] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B output CONFIG_INTERRUPT_MSIENABLE, // 1 if MSI interrupts are enable, 0 if only legacy are supported output [11:0] CONFIG_MAX_CPL_DATA, // Receive credit limit for data output [7:0] CONFIG_MAX_CPL_HDR, // Receive credit limit for headers output CONFIG_CPL_BOUNDARY_SEL, // Read completion boundary (0=64 bytes, 1=128 byt output INTR_MSI_RDY, input INTR_MSI_REQUEST ); generate if(C_ALTERA == 1'b1) begin : altera_translator_128 wire [2:0] wFMT; // Format field of the TLP Header wire [4:0] wType; // Type field of the TLP header wire [9:0] wLength; // Length field of the TLP Header wire wLenEven; // 1 if even number of TLP data words, else 0 wire wQWA4DWH, wQWA3DWH; wire wMsgType; wire wEP; wire w3DWH; wire w4DWH; reg _r1CyTLP,r1CyTLP; reg _rEven4DWH, rEven4DWH; reg _rEven3DWH, rEven3DWH; reg _rEvenMsg, rEvenMsg; reg _rEP, rEP; reg _rMSG, rMSG/* synthesis noprune */; reg [3:0] rTlCfgAdd,_rTlCfgAdd; reg [31:0] rTlCfgCtl,_rTlCfgCtl; reg [52:0] rTlCfgSts,_rTlCfgSts; reg [15:0] rCfgCompleterId; reg rCfgBusMstrEnable; reg [2:0] rCfgMaxReadRequestSize; reg [2:0] rCfgMaxPayloadSize; reg rCfgInterruptMsienable; reg rReadCompletionBoundarySel; reg [1:0] _rTlpEndOffset_I, rTlpEndOffset_I; reg [1:0] _rTlpEndOffset_D, rTlpEndOffset_D; reg [127:0] rRxStData; reg rRxStValid; reg rRxStEop; reg rRxStSop; assign wEP = RX_ST_DATA[14]; assign wLength = RX_ST_DATA[9:0]; assign wType = RX_ST_DATA[28:24]; assign wFMT = RX_ST_DATA[31:29]; assign wQWA3DWH = ~RX_ST_DATA[66]; assign wQWA4DWH = ~RX_ST_DATA[98]; assign w4DWH = wFMT[0]; assign w3DWH = ~wFMT[0]; assign wLenEven = ~wLength[0]; assign wMsgType = wType[4]; // Pre-calculating TLP End offset always @(*) begin // We expect to recieve three different types of packets // 3 DWH Packets, 4 DWH Packets, and Messages (No address) _rEven4DWH = w4DWH & ((wQWA4DWH & wLenEven) | (~wQWA4DWH & ~wLenEven)); _rEven3DWH = w3DWH & ((wQWA3DWH & wLenEven) | (~wQWA3DWH & ~wLenEven)); _rEvenMsg = wMsgType & wLenEven; _rMSG = (RX_ST_SOP & RX_ST_DATA[28]) | (rMSG & ~RX_ST_EOP); _rEP = (wEP & RX_ST_SOP) | (rEP & ~RX_TLP_END_FLAG); _rTlpEndOffset_I = {1'b1, ((~wLenEven & w3DWH)| w4DWH)}; _rTlpEndOffset_D = {~RX_ST_EMPTY,rEven4DWH|rEven3DWH|rEvenMsg}; _r1CyTLP = RX_ST_SOP & RX_ST_EOP; _rTlCfgCtl = TL_CFG_CTL; _rTlCfgAdd = TL_CFG_ADD; _rTlCfgSts = TL_CFG_STS; end always @(posedge CLK) begin // Should be the same clock as pld_clk rTlCfgAdd <= _rTlCfgAdd; rTlCfgCtl <= _rTlCfgCtl; rTlCfgSts <= _rTlCfgSts; rEP <= _rEP; rTlpEndOffset_I <= _rTlpEndOffset_I; rTlpEndOffset_D <= _rTlpEndOffset_D; r1CyTLP <= _r1CyTLP; rRxStData <= RX_ST_DATA; rRxStValid <= RX_ST_VALID; rRxStEop <= RX_ST_EOP; rRxStSop <= RX_ST_SOP; rMSG <= _rMSG; if(RX_ST_SOP) begin rEven4DWH <= _rEven4DWH; rEven3DWH <= _rEven3DWH; rEvenMsg <= _rEvenMsg; end if(rTlCfgAdd == 4'h0) begin rCfgMaxReadRequestSize <= rTlCfgCtl[30:28]; rCfgMaxPayloadSize <= rTlCfgCtl[23:21]; end if(rTlCfgAdd == 4'h2) begin rReadCompletionBoundarySel <= rTlCfgCtl[19]; end if(rTlCfgAdd == 4'h3) begin rCfgBusMstrEnable <= rTlCfgCtl[10]; end if(rTlCfgAdd == 4'hD) begin rCfgInterruptMsienable <= rTlCfgCtl[0]; end if(rTlCfgAdd == 4'hF) begin rCfgCompleterId <= {rTlCfgCtl[12:0],3'b0}; end end // always @ (posedge CLK) // Rx Interface (To PCIe Core) assign RX_ST_READY = RX_DATA_READY; // Rx Interface (From PCIe Core) assign RX_DATA = rRxStData; assign RX_DATA_VALID = rRxStValid; assign RX_TLP_END_FLAG = rRxStEop; assign RX_TLP_END_OFFSET = {r1CyTLP?rTlpEndOffset_I:rTlpEndOffset_D,2'b11}; assign RX_TLP_START_FLAG = rRxStSop; assign RX_TLP_START_OFFSET = 4'h0000; assign RX_TLP_ERROR_POISON = rEP; // Configuration Interface assign CONFIG_COMPLETER_ID = rCfgCompleterId; assign CONFIG_BUS_MASTER_ENABLE = rCfgBusMstrEnable; assign CONFIG_LINK_WIDTH = rTlCfgSts[40:35]; assign CONFIG_LINK_RATE = rTlCfgSts[32:31]; assign CONFIG_MAX_READ_REQUEST_SIZE = rCfgMaxReadRequestSize; assign CONFIG_MAX_PAYLOAD_SIZE = rCfgMaxPayloadSize; assign CONFIG_INTERRUPT_MSIENABLE = rCfgInterruptMsienable; assign CONFIG_CPL_BOUNDARY_SEL = rReadCompletionBoundarySel; assign CONFIG_MAX_CPL_HDR = KO_CPL_SPC_HEADER; assign CONFIG_MAX_CPL_DATA = KO_CPL_SPC_DATA; // Interrupt interface assign APP_MSI_REQ = INTR_MSI_REQUEST; assign INTR_MSI_RDY = APP_MSI_ACK; tx_qword_aligner_128 #( .C_ALTERA(C_ALTERA), .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH), .C_TX_READY_LATENCY(C_TX_READY_LATENCY) ) aligner_inst ( // Outputs .TX_DATA_READY (TX_DATA_READY), .TX_ST_DATA (TX_ST_DATA[C_PCI_DATA_WIDTH-1:0]), .TX_ST_VALID (TX_ST_VALID[0:0]), .TX_ST_EOP (TX_ST_EOP[0:0]), .TX_ST_SOP (TX_ST_SOP[0:0]), .TX_ST_EMPTY (TX_ST_EMPTY), // Inputs .CLK (CLK), .RST_IN (RST_IN), .TX_DATA (TX_DATA[C_PCI_DATA_WIDTH-1:0]), .TX_DATA_VALID (TX_DATA_VALID), .TX_TLP_END_FLAG (TX_TLP_END_FLAG), .TX_TLP_START_FLAG (TX_TLP_START_FLAG), .TX_ST_READY (TX_ST_READY)); end else begin : xilinx_translator_128 // Rx Interface (From PCIe Core) assign RX_DATA = M_AXIS_RX_TDATA; assign RX_DATA_VALID = M_AXIS_RX_TVALID; assign RX_TLP_END_FLAG = IS_EOF[4]; // Also, M_AXIS_RX_TLAST assign RX_TLP_END_OFFSET = IS_EOF[3:0]; assign RX_TLP_START_FLAG = IS_SOF[4]; // Also, posedge M_AXIS_RX_TVALID or negedge M_AXIS_RX_TLAST and M_AXIS_RX_TVALID = 1 assign RX_TLP_START_OFFSET = IS_SOF[3:0]; assign RX_TLP_ERROR_POISON = RERR_FWD; // Rx Interface (To PCIe Core) assign M_AXIS_RX_TREADY = RX_DATA_READY; // TX Interface (From PCIe Core) assign TX_DATA_READY = S_AXIS_TX_TREADY; // TX Interface (TO PCIe Core) assign S_AXIS_TX_TDATA = TX_DATA; assign S_AXIS_TX_TVALID = TX_DATA_VALID; assign S_AXIS_TX_TKEEP = TX_DATA_BYTE_ENABLE; assign S_AXIS_TX_TLAST = TX_TLP_END_FLAG; assign S_AXIS_SRC_DSC = TX_TLP_ERROR_POISON; // Configuration Interface assign CONFIG_COMPLETER_ID = COMPLETER_ID; assign CONFIG_BUS_MASTER_ENABLE = CFG_BUS_MSTR_ENABLE; assign CONFIG_LINK_WIDTH = CFG_LINK_WIDTH; assign CONFIG_LINK_RATE = CFG_LINK_RATE; assign CONFIG_MAX_READ_REQUEST_SIZE = CFG_MAX_READ_REQUEST_SIZE; assign CONFIG_MAX_PAYLOAD_SIZE = CFG_MAX_PAYLOAD_SIZE; assign CONFIG_INTERRUPT_MSIENABLE = CFG_INTERRUPT_MSIEN; assign CONFIG_CPL_BOUNDARY_SEL = RCB; assign CONFIG_MAX_CPL_DATA = MAX_RC_CPLD; assign CONFIG_MAX_CPL_HDR = MAX_RC_CPLH; // Interrupt interface assign CFG_INTERRUPT = INTR_MSI_REQUEST; assign INTR_MSI_RDY = CFG_INTERRUPT_RDY; end endgenerate endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/translation_layer_32.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 19:27:32 05/15/2014 // Design Name: // Module Name: translation_layer_32 // Project Name: // Target Devices: // Tool versions: // Description: // Translates AXI (Xilinx) signals into Unified (architecture // independent) streaming signals for riffa. // // Dependencies: None // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module translation_layer_32 #(parameter C_ALTERA = 1'b1, parameter C_PCI_DATA_WIDTH = 10'd32) ( input CLK, input RST_IN, // Xilinx Signals input [C_PCI_DATA_WIDTH-1:0] M_AXIS_RX_TDATA, input [(C_PCI_DATA_WIDTH/8)-1:0] M_AXIS_RX_TKEEP, input M_AXIS_RX_TLAST, // Not used in the 128 bit interface input M_AXIS_RX_TVALID, output M_AXIS_RX_TREADY, input [(C_PCI_DATA_WIDTH/32):0] IS_SOF, input [(C_PCI_DATA_WIDTH/32):0] IS_EOF, input RERR_FWD, output [C_PCI_DATA_WIDTH-1:0] S_AXIS_TX_TDATA, output [(C_PCI_DATA_WIDTH/8)-1:0] S_AXIS_TX_TKEEP, output S_AXIS_TX_TLAST, output S_AXIS_TX_TVALID, output S_AXIS_SRC_DSC, input S_AXIS_TX_TREADY, input [15:0] COMPLETER_ID, input CFG_BUS_MSTR_ENABLE, input [5:0] CFG_LINK_WIDTH, // cfg_lstatus[9:4] (from Link Status Register): 000001=x1, 000010=x2, 000100=x4, 001000=x8, 001100=x12, 010000=x16, 100000=x32, others=? input [1:0] CFG_LINK_RATE, // cfg_lstatus[1:0] (from Link Status Register): 01=2.5GT/s, 10=5.0GT/s, others=? input [2:0] CFG_MAX_READ_REQUEST_SIZE, // cfg_dcommand[14:12] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B input [2:0] CFG_MAX_PAYLOAD_SIZE, // cfg_dcommand[7:5] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B input CFG_INTERRUPT_MSIEN, // 1 if MSI interrupts are enable, 0 if only legacy are supported input CFG_INTERRUPT_RDY, // High when interrupt is able to be sent output CFG_INTERRUPT, // High to request interrupt, when both CFG_INTERRUPT_RDY and CFG_INTERRUPT are high, interrupt is sent) input RCB, input [11:0] MAX_RC_CPLD, // Receive credit limit for data (be sure fc_sel == 001) input [7:0] MAX_RC_CPLH, // Receive credit limit for headers (be sure fc_sel == 001) // Altera Signals input [C_PCI_DATA_WIDTH-1:0] RX_ST_DATA, input [0:0] RX_ST_EOP, input [0:0] RX_ST_VALID, output RX_ST_READY, input [0:0] RX_ST_SOP, input [0:0] RX_ST_EMPTY, output [C_PCI_DATA_WIDTH-1:0] TX_ST_DATA, output [0:0] TX_ST_VALID, input TX_ST_READY, output [0:0] TX_ST_EOP, output [0:0] TX_ST_SOP, output [0:0] TX_ST_EMPTY, input [31:0] TL_CFG_CTL, input [3:0] TL_CFG_ADD, input [52:0] TL_CFG_STS, input [7:0] KO_CPL_SPC_HEADER, input [11:0] KO_CPL_SPC_DATA, input APP_MSI_ACK, output APP_MSI_REQ, // Unified Signals output [C_PCI_DATA_WIDTH-1:0] RX_DATA, output RX_DATA_VALID, input RX_DATA_READY, output [(C_PCI_DATA_WIDTH/8)-1:0] RX_DATA_BYTE_ENABLE, output RX_TLP_END_FLAG, output [3:0] RX_TLP_END_OFFSET, output RX_TLP_START_FLAG, output [3:0] RX_TLP_START_OFFSET, output RX_TLP_ERROR_POISON, input [C_PCI_DATA_WIDTH-1:0] TX_DATA, input [(C_PCI_DATA_WIDTH/8)-1:0] TX_DATA_BYTE_ENABLE, input TX_TLP_END_FLAG, input TX_DATA_VALID, input TX_TLP_ERROR_POISON, output TX_DATA_READY, output [15:0] CONFIG_COMPLETER_ID, output CONFIG_BUS_MASTER_ENABLE, output [5:0] CONFIG_LINK_WIDTH, // cfg_lstatus[9:4] (from Link Status Register): 000001=x1, 000010=x2, 000100=x4, 001000=x8, 001100=x12, 010000=x16, 100000=x32, others=? output [1:0] CONFIG_LINK_RATE, // cfg_lstatus[1:0] (from Link Status Register): 01=2.5GT/s, 10=5.0GT/s, others=? output [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // cfg_dcommand[14:12] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B output [2:0] CONFIG_MAX_PAYLOAD_SIZE, // cfg_dcommand[7:5] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B output CONFIG_INTERRUPT_MSIENABLE, // 1 if MSI interrupts are enable, 0 if only legacy are supported output [11:0] CONFIG_MAX_CPL_DATA, // Receive credit limit for data output [7:0] CONFIG_MAX_CPL_HDR, // Receive credit limit for headers output CONFIG_CPL_BOUNDARY_SEL, // Read completion boundary (0=64 bytes, 1=128 byte output INTR_MSI_RDY, // High when interrupt is able to be sent input INTR_MSI_REQUEST // High to request interrupt, when both CFG_INTERRUPT_RDY and CFG_INTERRUPT are high ); generate if(C_ALTERA == 1'b1) begin : altera_translator_32 // If you have reached here, something has gone // horrendously wrong. Altera does not have a 32-bit PCIE // interface. Please adapt your application and try again. end else begin : xilinx_translator_32 // Rx Interface (From PCIe Core) assign RX_DATA = M_AXIS_RX_TDATA; assign RX_DATA_VALID = M_AXIS_RX_TVALID; assign RX_DATA_BYTE_ENABLE = M_AXIS_RX_TKEEP; assign RX_TLP_END_FLAG = M_AXIS_RX_TLAST; assign RX_TLP_END_OFFSET = M_AXIS_RX_TKEEP[3]; assign RX_TLP_START_FLAG = 1'd0; assign RX_TLP_START_OFFSET = 4'h0; assign RX_TLP_ERROR_POISON = RERR_FWD; // Rx Interface (To PCIe Core) assign M_AXIS_RX_TREADY = RX_DATA_READY; // TX Interface (From PCIe Core) assign TX_DATA_READY = S_AXIS_TX_TREADY; // TX Interface (TO PCIe Core) assign S_AXIS_TX_TDATA = TX_DATA; assign S_AXIS_TX_TVALID = TX_DATA_VALID; assign S_AXIS_TX_TKEEP = TX_DATA_BYTE_ENABLE; assign S_AXIS_TX_TLAST = TX_TLP_END_FLAG; assign S_AXIS_SRC_DSC = TX_TLP_ERROR_POISON; // Configuration Interface assign CONFIG_COMPLETER_ID = COMPLETER_ID; assign CONFIG_BUS_MASTER_ENABLE = CFG_BUS_MSTR_ENABLE; assign CONFIG_LINK_WIDTH = CFG_LINK_WIDTH; assign CONFIG_LINK_RATE = CFG_LINK_RATE; assign CONFIG_MAX_READ_REQUEST_SIZE = CFG_MAX_READ_REQUEST_SIZE; assign CONFIG_MAX_PAYLOAD_SIZE = CFG_MAX_PAYLOAD_SIZE; assign CONFIG_INTERRUPT_MSIENABLE = CFG_INTERRUPT_MSIEN; assign CONFIG_CPL_BOUNDARY_SEL = RCB; assign CONFIG_MAX_CPL_DATA = MAX_RC_CPLD; assign CONFIG_MAX_CPL_HDR = MAX_RC_CPLH; // Interrupt interface assign CFG_INTERRUPT = INTR_MSI_REQUEST; assign INTR_MSI_RDY = CFG_INTERRUPT_RDY; end endgenerate endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/translation_layer_64.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 19:27:32 05/15/2014 // Design Name: // Module Name: translation_layer_64 // Project Name: // Target Devices: // Tool versions: // Description: // Translates AXI (Xilinx) or Avalon (Altera) signals into Unified (architecture // independent) streaming signals for riffa. The altera RX interface has a 1 cycle // latency because it needs to produce several metadata signals that are not // provided by the altera PCIe Core. // // Dependencies: None // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module translation_layer_64 #(parameter C_ALTERA = 1'b1, parameter C_PCI_DATA_WIDTH = 10'd64, parameter C_RX_READY_LATENCY = 3'd2, parameter C_TX_READY_LATENCY = 3'd2) ( input CLK, input RST_IN, // Xilinx Signals input [C_PCI_DATA_WIDTH-1:0] M_AXIS_RX_TDATA, input [(C_PCI_DATA_WIDTH/8)-1:0] M_AXIS_RX_TKEEP, input M_AXIS_RX_TLAST, // Not used in the 128 bit interface input M_AXIS_RX_TVALID, output M_AXIS_RX_TREADY, input [(C_PCI_DATA_WIDTH/32):0] IS_SOF, input [(C_PCI_DATA_WIDTH/32):0] IS_EOF, input RERR_FWD, output [C_PCI_DATA_WIDTH-1:0] S_AXIS_TX_TDATA, output [(C_PCI_DATA_WIDTH/8)-1:0] S_AXIS_TX_TKEEP, output S_AXIS_TX_TLAST, output S_AXIS_TX_TVALID, output S_AXIS_SRC_DSC, input S_AXIS_TX_TREADY, input [15:0] COMPLETER_ID, input CFG_BUS_MSTR_ENABLE, input [5:0] CFG_LINK_WIDTH, // cfg_lstatus[9:4] (from Link Status Register): 000001=x1, 000010=x2, 000100=x4, 001000=x8, 001100=x12, 010000=x16, 100000=x32, others=? input [1:0] CFG_LINK_RATE, // cfg_lstatus[1:0] (from Link Status Register): 01=2.5GT/s, 10=5.0GT/s, others=? input [2:0] CFG_MAX_READ_REQUEST_SIZE, // cfg_dcommand[14:12] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B input [2:0] CFG_MAX_PAYLOAD_SIZE, // cfg_dcommand[7:5] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B input CFG_INTERRUPT_MSIEN, // 1 if MSI interrupts are enable, 0 if only legacy are supported input CFG_INTERRUPT_RDY, // High when interrupt is able to be sent output CFG_INTERRUPT, // High to request interrupt, when both CFG_INTERRUPT_RDY and CFG_INTERRUPT are high, interrupt is sent) input RCB, input [11:0] MAX_RC_CPLD, // Receive credit limit for data (be sure fc_sel == 001) input [7:0] MAX_RC_CPLH, // Receive credit limit for headers (be sure fc_sel == 001) // Altera Signals input [C_PCI_DATA_WIDTH-1:0] RX_ST_DATA, input [0:0] RX_ST_EOP, input [0:0] RX_ST_VALID, output RX_ST_READY, input [0:0] RX_ST_SOP, input [0:0] RX_ST_EMPTY, output [C_PCI_DATA_WIDTH-1:0] TX_ST_DATA, output [0:0] TX_ST_VALID, input TX_ST_READY, output [0:0] TX_ST_EOP, output [0:0] TX_ST_SOP, output [0:0] TX_ST_EMPTY, // NC input [31:0] TL_CFG_CTL, input [3:0] TL_CFG_ADD, input [52:0] TL_CFG_STS, input [7:0] KO_CPL_SPC_HEADER, input [11:0] KO_CPL_SPC_DATA, input APP_MSI_ACK, output APP_MSI_REQ, // Unified Signals output [C_PCI_DATA_WIDTH-1:0] RX_DATA, output RX_DATA_VALID, input RX_DATA_READY, output [(C_PCI_DATA_WIDTH/8)-1:0] RX_DATA_BYTE_ENABLE, output RX_TLP_END_FLAG, output [3:0] RX_TLP_END_OFFSET, output RX_TLP_START_FLAG, output [3:0] RX_TLP_START_OFFSET, output RX_TLP_ERROR_POISON, input [C_PCI_DATA_WIDTH-1:0] TX_DATA, input [(C_PCI_DATA_WIDTH/8)-1:0] TX_DATA_BYTE_ENABLE, input TX_TLP_END_FLAG, input TX_TLP_START_FLAG, input TX_DATA_VALID, input TX_TLP_ERROR_POISON, output TX_DATA_READY, output [15:0] CONFIG_COMPLETER_ID, output CONFIG_BUS_MASTER_ENABLE, output [5:0] CONFIG_LINK_WIDTH, // cfg_lstatus[9:4] (from Link Status Register): 000001=x1, 000010=x2, 000100=x4, 001000=x8, 001100=x12, 010000=x16, 100000=x32, others=? output [1:0] CONFIG_LINK_RATE, // cfg_lstatus[1:0] (from Link Status Register): 01=2.5GT/s, 10=5.0GT/s, others=? output [2:0] CONFIG_MAX_READ_REQUEST_SIZE, // cfg_dcommand[14:12] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B output [2:0] CONFIG_MAX_PAYLOAD_SIZE, // cfg_dcommand[7:5] (from Device Control Register): 000=128B, 001=256B, 010=512B, 011=1024B output CONFIG_INTERRUPT_MSIENABLE, // 1 if MSI interrupts are enable, 0 if only legacy are supported output [11:0] CONFIG_MAX_CPL_DATA, // Receive credit limit for data output [7:0] CONFIG_MAX_CPL_HDR, // Receive credit limit for headers output CONFIG_CPL_BOUNDARY_SEL, // Read completion boundary (0=64 bytes, 1=128 byt output INTR_MSI_RDY, // High when interrupt is able to be sent input INTR_MSI_REQUEST // High to request interrupt, when both CFG_INTERRUPT_RDY and CFG_INTERRUPT are high ); generate if(C_ALTERA == 1'b1) begin : altera_translator_64 wire wEP; wire [9:0] wLength; // Length field of the TLP Header wire [4:0] wType; // Type field of the TLP header wire [3:0] wFMT; // Format field of the TLP Header wire w4DWH; wire w3DWH; wire wLenEven; // 1 if even number of TLP data words, else 0 wire wMsg; wire [64:0] wAddr3DWH; wire [64:0] wAddr4DWH; wire wQWA4DWH; wire wQWA3DWH; /// Configuration signals reg [15:0] rCfgCompleterId; reg rCfgBusMstrEnable; reg [2:0] rCfgMaxReadRequestSize; reg [2:0] rCfgMaxPayloadSize; reg rCfgInterruptMsienable; reg rReadCompletionBoundarySel; reg [3:0] rTlCfgAdd,_rTlCfgAdd; reg [31:0] rTlCfgCtl,_rTlCfgCtl; reg [52:0] rTlCfgSts,_rTlCfgSts; reg [63:0] rRxStData; reg rRxStValid; reg rRxStEop; reg rRxStSop; reg rEP, _rEP; reg rLenEven,_rLenEven; reg rMsg,_rMsg; reg r3DWH,_r3DWH; reg r4DWH,_r4DWH; reg rTlpEndOffset, _rTlpEndOffset; // Valid when RX_ST_SOP & RX_ST_VALID assign wEP = RX_ST_DATA[14]; assign wLength = RX_ST_DATA[9:0]; assign wType = RX_ST_DATA[28:24]; assign wFMT = RX_ST_DATA[31:29]; assign w4DWH = wFMT[0]; assign w3DWH = ~wFMT[0]; assign wLenEven = ~wLength[0]; assign wMsg = wType[4]; // Valid when rRxStSop & RX_ST_VALID assign wAddr3DWH = {32'd0,RX_ST_DATA[31:0]}; assign wAddr4DWH = {RX_ST_DATA[31:0],RX_ST_DATA[63:32]}; assign wQWA3DWH = ~wAddr3DWH[2]; assign wQWA4DWH = ~wAddr4DWH[2]; always @(*) begin // We expect to recieve three different types of packets // 3 DWH Packets, 4 DWH Packets, and Messages (No address) _rEP = wEP; _rLenEven = wLenEven; _rMsg = wMsg; _r3DWH = w3DWH; _r4DWH = w4DWH; // If the whole TLP is of even length, then the end will be at // offset byte 7, otherwise the end will be at byte offset 3 _rTlpEndOffset = ( rMsg & rLenEven) | (~rMsg & (( rLenEven & r3DWH & wQWA3DWH)| (~rLenEven & r3DWH & ~wQWA3DWH)| ( rLenEven & r4DWH & wQWA4DWH)| (~rLenEven & r4DWH & ~wQWA4DWH))); _rTlCfgCtl = TL_CFG_CTL; _rTlCfgAdd = TL_CFG_ADD; _rTlCfgSts = TL_CFG_STS; end always @(posedge CLK) begin // Should be the same clock as pld_clk rTlCfgAdd <= _rTlCfgAdd; rTlCfgCtl <= _rTlCfgCtl; rTlCfgSts <= _rTlCfgSts; rRxStData <= RX_ST_DATA; rRxStValid <= RX_ST_VALID; if(RX_ST_VALID) begin rRxStEop <= RX_ST_EOP; rRxStSop <= RX_ST_SOP; end if(rRxStSop) begin rTlpEndOffset <= _rTlpEndOffset; end if(RX_ST_SOP & RX_ST_VALID) begin rEP <= _rEP; rLenEven <= _rLenEven; rMsg <= _rMsg; r3DWH <= _r3DWH; r4DWH <= _r4DWH; end if(rTlCfgAdd == 4'h0) begin rCfgMaxReadRequestSize <= rTlCfgCtl[30:28]; rCfgMaxPayloadSize <= rTlCfgCtl[23:21]; end if(rTlCfgAdd == 4'h2) begin rReadCompletionBoundarySel <= rTlCfgCtl[19]; end if(rTlCfgAdd == 4'h3) begin rCfgBusMstrEnable <= rTlCfgCtl[10]; end if(rTlCfgAdd == 4'hD) begin rCfgInterruptMsienable <= rTlCfgCtl[0]; end if(rTlCfgAdd == 4'hF) begin rCfgCompleterId <= {rTlCfgCtl[12:0],3'b0}; end end // always @ (posedge CLK) // Rx Interface (To PCIe Core) assign RX_ST_READY = RX_DATA_READY; // Rx Interface (From PCIe Core) assign RX_DATA = rRxStData; assign RX_DATA_VALID = rRxStValid; assign RX_DATA_BYTE_ENABLE = {{4{rTlpEndOffset}},4'hF}; assign RX_TLP_END_FLAG = rRxStEop; assign RX_TLP_END_OFFSET = {rTlpEndOffset,2'b11}; assign RX_TLP_START_FLAG = rRxStSop; assign RX_TLP_START_OFFSET = 4'h0; assign RX_TLP_ERROR_POISON = rEP; // Configuration Interface assign CONFIG_COMPLETER_ID = rCfgCompleterId; assign CONFIG_BUS_MASTER_ENABLE = rCfgBusMstrEnable; assign CONFIG_LINK_WIDTH = rTlCfgSts[40:35]; assign CONFIG_LINK_RATE = rTlCfgSts[32:31]; assign CONFIG_MAX_READ_REQUEST_SIZE = rCfgMaxReadRequestSize; assign CONFIG_MAX_PAYLOAD_SIZE = rCfgMaxPayloadSize; assign CONFIG_INTERRUPT_MSIENABLE = rCfgInterruptMsienable; assign CONFIG_CPL_BOUNDARY_SEL = rReadCompletionBoundarySel; assign CONFIG_MAX_CPL_HDR = KO_CPL_SPC_HEADER; assign CONFIG_MAX_CPL_DATA = KO_CPL_SPC_DATA; // Interrupt interface assign APP_MSI_REQ = INTR_MSI_REQUEST; assign INTR_MSI_RDY = APP_MSI_ACK; tx_qword_aligner_64 #( .C_ALTERA(C_ALTERA), .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH), .C_TX_READY_LATENCY(C_TX_READY_LATENCY) ) aligner_inst ( // Outputs .TX_DATA_READY (TX_DATA_READY), .TX_ST_DATA (TX_ST_DATA[C_PCI_DATA_WIDTH-1:0]), .TX_ST_VALID (TX_ST_VALID[0:0]), .TX_ST_EOP (TX_ST_EOP[0:0]), .TX_ST_SOP (TX_ST_SOP[0:0]), .TX_ST_EMPTY (TX_ST_EMPTY), // Inputs .CLK (CLK), .RST_IN (RST_IN), .TX_DATA (TX_DATA[C_PCI_DATA_WIDTH-1:0]), .TX_DATA_VALID (TX_DATA_VALID), .TX_TLP_END_FLAG (TX_TLP_END_FLAG), .TX_TLP_START_FLAG (TX_TLP_START_FLAG), .TX_ST_READY (TX_ST_READY)); end else begin : xilinx_translator_64 // Rx Interface (From PCIe Core) assign RX_DATA = M_AXIS_RX_TDATA; assign RX_DATA_VALID = M_AXIS_RX_TVALID; assign RX_DATA_BYTE_ENABLE = M_AXIS_RX_TKEEP; assign RX_TLP_END_FLAG = M_AXIS_RX_TLAST; assign RX_TLP_END_OFFSET = {3'b000,M_AXIS_RX_TKEEP[4]}; assign RX_TLP_START_FLAG = 1'd0; assign RX_TLP_START_OFFSET = 4'h0; assign RX_TLP_ERROR_POISON = RERR_FWD; // Rx Interface (To PCIe Core) assign M_AXIS_RX_TREADY = RX_DATA_READY; // TX Interface (From PCIe Core) assign TX_DATA_READY = S_AXIS_TX_TREADY; // TX Interface (TO PCIe Core) assign S_AXIS_TX_TDATA = TX_DATA; assign S_AXIS_TX_TVALID = TX_DATA_VALID; assign S_AXIS_TX_TKEEP = TX_DATA_BYTE_ENABLE; assign S_AXIS_TX_TLAST = TX_TLP_END_FLAG; assign S_AXIS_SRC_DSC = TX_TLP_ERROR_POISON; // Configuration Interface assign CONFIG_COMPLETER_ID = COMPLETER_ID; assign CONFIG_BUS_MASTER_ENABLE = CFG_BUS_MSTR_ENABLE; assign CONFIG_LINK_WIDTH = CFG_LINK_WIDTH; assign CONFIG_LINK_RATE = CFG_LINK_RATE; assign CONFIG_MAX_READ_REQUEST_SIZE = CFG_MAX_READ_REQUEST_SIZE; assign CONFIG_MAX_PAYLOAD_SIZE = CFG_MAX_PAYLOAD_SIZE; assign CONFIG_INTERRUPT_MSIENABLE = CFG_INTERRUPT_MSIEN; assign CONFIG_CPL_BOUNDARY_SEL = RCB; assign CONFIG_MAX_CPL_DATA = MAX_RC_CPLD; assign CONFIG_MAX_CPL_HDR = MAX_RC_CPLH; // Interrupt interface assign CFG_INTERRUPT = INTR_MSI_REQUEST; assign INTR_MSI_RDY = CFG_INTERRUPT_RDY; end endgenerate endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_engine_128.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_engine_128.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Transmit engine for PCIe using AXI interface from Xilinx // PCIe Endpoint core. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: Very good PCIe header reference: // http://www.pzk-agro.com/0321156307_ch04lev1sec5.html#ch04lev4sec14 //----------------------------------------------------------------------------- module tx_engine_128 #( parameter C_PCI_DATA_WIDTH = 9'd128, parameter C_NUM_CHNL = 4'd12, parameter C_TAG_WIDTH = 5, // Number of outstanding requests parameter C_ALTERA = 1'b1, // 1 if Altera, 0 if Xilinx // Local parameters parameter C_FIFO_DEPTH = 512, parameter C_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_FIFO_DEPTH))+1) ) ( input CLK, input RST, input [15:0] CONFIG_COMPLETER_ID, input [2:0] CONFIG_MAX_PAYLOAD_SIZE, // Maximum write payload: 000=128B, 001=256B, 010=512B, 011=1024B output [C_PCI_DATA_WIDTH-1:0] TX_DATA, // AXI data output output [(C_PCI_DATA_WIDTH/8)-1:0] TX_DATA_BYTE_ENABLE, // AXI data keep output TX_TLP_END_FLAG, // AXI data last output TX_TLP_START_FLAG, // AXI data start output TX_DATA_VALID, // AXI data valid output S_AXIS_SRC_DSC, // AXI data discontinue input TX_DATA_READY, // AXI ready for data input [C_NUM_CHNL-1:0] WR_REQ, // Write request input [(C_NUM_CHNL*64)-1:0] WR_ADDR, // Write address input [(C_NUM_CHNL*10)-1:0] WR_LEN, // Write data length input [(C_NUM_CHNL*C_PCI_DATA_WIDTH)-1:0] WR_DATA, // Write data output [C_NUM_CHNL-1:0] WR_DATA_REN, // Write data read enable output [C_NUM_CHNL-1:0] WR_ACK, // Write request has been accepted output [C_NUM_CHNL-1:0] WR_SENT, // Pulsed at channel pos when write request sent input [C_NUM_CHNL-1:0] RD_REQ, // Read request input [(C_NUM_CHNL*2)-1:0] RD_SG_CHNL, // Read request channel for scatter gather lists input [(C_NUM_CHNL*64)-1:0] RD_ADDR, // Read request address input [(C_NUM_CHNL*10)-1:0] RD_LEN, // Read request length output [C_NUM_CHNL-1:0] RD_ACK, // Read request has been accepted output [5:0] INT_TAG, // Internal tag to exchange with external output INT_TAG_VALID, // High to signal tag exchange input [C_TAG_WIDTH-1:0] EXT_TAG, // External tag to provide in exchange for internal tag input EXT_TAG_VALID, // High to signal external tag is valid output TX_ENG_RD_REQ_SENT, // Read completion request issued input RXBUF_SPACE_AVAIL, input COMPL_REQ, // RX Engine request for completion output COMPL_DONE, // Completion done input [2:0] REQ_TC, input REQ_TD, input REQ_EP, input [1:0] REQ_ATTR, input [9:0] REQ_LEN, input [15:0] REQ_ID, input [7:0] REQ_TAG, input [3:0] REQ_BE, input [29:0] REQ_ADDR, input [31:0] REQ_DATA, output [31:0] REQ_DATA_SENT // Actual completion data sent ); `include "common_functions.v" wire [C_PCI_DATA_WIDTH-1:0] wFifoWrData; wire [C_PCI_DATA_WIDTH-1:0] wFifoRdData; wire [C_FIFO_DEPTH_WIDTH-1:0] wFifoCount; wire wFifoEmpty; wire wFifoRen; wire wFifoWen; wire wAltera = C_ALTERA; // Convert the read and write requests into PCI packet format and mux // them together into a FIFO. tx_engine_upper_128 #( .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH), .C_NUM_CHNL(C_NUM_CHNL), .C_FIFO_DEPTH(C_FIFO_DEPTH), .C_TAG_WIDTH(C_TAG_WIDTH), .C_ALTERA(C_ALTERA) ) upper ( .RST(RST), .CLK(CLK), .CONFIG_COMPLETER_ID(CONFIG_COMPLETER_ID), .CONFIG_MAX_PAYLOAD_SIZE(CONFIG_MAX_PAYLOAD_SIZE), .WR_REQ(WR_REQ), .WR_ADDR(WR_ADDR), .WR_LEN(WR_LEN), .WR_DATA(WR_DATA), .WR_DATA_REN(WR_DATA_REN), .WR_ACK(WR_ACK), .RD_REQ(RD_REQ), .RD_SG_CHNL(RD_SG_CHNL), .RD_ADDR(RD_ADDR), .RD_LEN(RD_LEN), .RD_ACK(RD_ACK), .TX_ENG_RD_REQ_SENT(TX_ENG_RD_REQ_SENT), .RXBUF_SPACE_AVAIL(RXBUF_SPACE_AVAIL | !wAltera), .INT_TAG(INT_TAG), .INT_TAG_VALID(INT_TAG_VALID), .EXT_TAG(EXT_TAG), .EXT_TAG_VALID(EXT_TAG_VALID), .FIFO_DATA(wFifoWrData), .FIFO_COUNT(wFifoCount), .FIFO_WEN(wFifoWen) ); // FIFO for storing outbound read/write requests. (* RAM_STYLE="BLOCK" *) sync_fifo #(.C_WIDTH(C_PCI_DATA_WIDTH), .C_DEPTH(C_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) fifo ( .RST(RST), .CLK(CLK), .WR_EN(wFifoWen), .WR_DATA(wFifoWrData), .FULL(), .COUNT(wFifoCount), .RD_EN(wFifoRen), .RD_DATA(wFifoRdData), .EMPTY(wFifoEmpty) ); // Process the formatted PCI packets in the FIFO and completions. // Completions take top priority. Mux the data into the AXI interface // for the PCIe Endpoint. tx_engine_lower_128 #( .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH), .C_NUM_CHNL(C_NUM_CHNL), .C_ALTERA(C_ALTERA) ) lower ( .RST(RST), .CLK(CLK), .CONFIG_COMPLETER_ID(CONFIG_COMPLETER_ID), .TX_DATA(TX_DATA), .TX_DATA_BYTE_ENABLE(TX_DATA_BYTE_ENABLE), .TX_TLP_END_FLAG(TX_TLP_END_FLAG), .TX_TLP_START_FLAG(TX_TLP_START_FLAG), .TX_DATA_VALID(TX_DATA_VALID), .S_AXIS_SRC_DSC(S_AXIS_SRC_DSC), .TX_DATA_READY(TX_DATA_READY), .COMPL_REQ(COMPL_REQ), .COMPL_DONE(COMPL_DONE), .REQ_TC(REQ_TC), .REQ_TD(REQ_TD), .REQ_EP(REQ_EP), .REQ_ATTR(REQ_ATTR), .REQ_LEN(REQ_LEN), .REQ_ID(REQ_ID), .REQ_TAG(REQ_TAG), .REQ_BE(REQ_BE), .REQ_ADDR(REQ_ADDR), .REQ_DATA(REQ_DATA), .REQ_DATA_SENT(REQ_DATA_SENT), .FIFO_DATA(wFifoRdData), .FIFO_EMPTY(wFifoEmpty), .FIFO_REN(wFifoRen), .WR_SENT(WR_SENT) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_engine_32.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_engine_32.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Transmit engine for PCIe using AXI interface from Xilinx // PCIe Endpoint core. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: Very good PCIe header reference: // http://www.pzk-agro.com/0321156307_ch04lev1sec5.html#ch04lev4sec14 //----------------------------------------------------------------------------- module tx_engine_32 #( parameter C_PCI_DATA_WIDTH = 9'd32, parameter C_NUM_CHNL = 4'd12, parameter C_TAG_WIDTH = 5, // Number of outstanding requests parameter C_ALTERA = 1'b1, // 1 if Altera, 0 if Xilinx // Local parameters parameter C_FIFO_DEPTH = 512, parameter C_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_FIFO_DEPTH))+1) ) ( input CLK, input RST, input [15:0] CONFIG_COMPLETER_ID, input [2:0] CONFIG_MAX_PAYLOAD_SIZE, // Maximum write payload: 000=128B, 001=256B, 010=512B, 011=1024B output [C_PCI_DATA_WIDTH-1:0] TX_DATA, // AXI data output output [(C_PCI_DATA_WIDTH/8)-1:0] TX_DATA_BYTE_ENABLE, // AXI data keep output TX_TLP_END_FLAG, // AXI data last output TX_TLP_START_FLAG, // AXI data first output TX_DATA_VALID, // AXI data valid output S_AXIS_SRC_DSC, // AXI data discontinue input TX_DATA_READY, // AXI ready for data input [C_NUM_CHNL-1:0] WR_REQ, // Write request input [(C_NUM_CHNL*64)-1:0] WR_ADDR, // Write address input [(C_NUM_CHNL*10)-1:0] WR_LEN, // Write data length input [(C_NUM_CHNL*C_PCI_DATA_WIDTH)-1:0] WR_DATA, // Write data output [C_NUM_CHNL-1:0] WR_DATA_REN, // Write data read enable output [C_NUM_CHNL-1:0] WR_ACK, // Write request has been accepted output [C_NUM_CHNL-1:0] WR_SENT, // Pulsed at channel pos when write request sent input [C_NUM_CHNL-1:0] RD_REQ, // Read request input [(C_NUM_CHNL*2)-1:0] RD_SG_CHNL, // Read request channel for scatter gather lists input [(C_NUM_CHNL*64)-1:0] RD_ADDR, // Read request address input [(C_NUM_CHNL*10)-1:0] RD_LEN, // Read request length output [C_NUM_CHNL-1:0] RD_ACK, // Read request has been accepted output [5:0] INT_TAG, // Internal tag to exchange with external output INT_TAG_VALID, // High to signal tag exchange input [C_TAG_WIDTH-1:0] EXT_TAG, // External tag to provide in exchange for internal tag input EXT_TAG_VALID, // High to signal external tag is valid output TX_ENG_RD_REQ_SENT, // Read completion request issued input RXBUF_SPACE_AVAIL, input COMPL_REQ, // RX Engine request for completion output COMPL_DONE, // Completion done input [2:0] REQ_TC, input REQ_TD, input REQ_EP, input [1:0] REQ_ATTR, input [9:0] REQ_LEN, input [15:0] REQ_ID, input [7:0] REQ_TAG, input [3:0] REQ_BE, input [29:0] REQ_ADDR, input [31:0] REQ_DATA, output [31:0] REQ_DATA_SENT // Actual completion data sent ); `include "common_functions.v" wire [C_PCI_DATA_WIDTH-1:0] wFifoWrData; wire [C_PCI_DATA_WIDTH-1:0] wFifoRdData; wire [C_FIFO_DEPTH_WIDTH-1:0] wFifoCount; wire wFifoEmpty; wire wFifoRen; wire wFifoWen; wire wAltera = C_ALTERA; // Convert the read and write requests into PCI packet format and mux // them together into a FIFO. tx_engine_upper_32 #(.C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH), .C_NUM_CHNL(C_NUM_CHNL), .C_FIFO_DEPTH(C_FIFO_DEPTH), .C_TAG_WIDTH(C_TAG_WIDTH)) upper ( .RST(RST), .CLK(CLK), .CONFIG_COMPLETER_ID(CONFIG_COMPLETER_ID), .CONFIG_MAX_PAYLOAD_SIZE(CONFIG_MAX_PAYLOAD_SIZE), .WR_REQ(WR_REQ), .WR_ADDR(WR_ADDR), .WR_LEN(WR_LEN), .WR_DATA(WR_DATA), .WR_DATA_REN(WR_DATA_REN), .WR_ACK(WR_ACK), .RD_REQ(RD_REQ), .RD_SG_CHNL(RD_SG_CHNL), .RD_ADDR(RD_ADDR), .RD_LEN(RD_LEN), .RD_ACK(RD_ACK), .TX_ENG_RD_REQ_SENT(TX_ENG_RD_REQ_SENT), .RXBUF_SPACE_AVAIL(RXBUF_SPACE_AVAIL | !wAltera), .INT_TAG(INT_TAG), .INT_TAG_VALID(INT_TAG_VALID), .EXT_TAG(EXT_TAG), .EXT_TAG_VALID(EXT_TAG_VALID), .FIFO_DATA(wFifoWrData), .FIFO_COUNT(wFifoCount), .FIFO_WEN(wFifoWen) ); // FIFO for storing outbound read/write requests. (* RAM_STYLE="BLOCK" *) sync_fifo #(.C_WIDTH(C_PCI_DATA_WIDTH), .C_DEPTH(C_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) fifo ( .RST(RST), .CLK(CLK), .WR_EN(wFifoWen), .WR_DATA(wFifoWrData), .FULL(), .COUNT(wFifoCount), .RD_EN(wFifoRen), .RD_DATA(wFifoRdData), .EMPTY(wFifoEmpty) ); // Process the formatted PCI packets in the FIFO and completions. // Completions take top priority. Mux the data into the AXI interface // for the PCIe Endpoint. tx_engine_lower_32 #(.C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH), .C_NUM_CHNL(C_NUM_CHNL)) lower ( .RST(RST), .CLK(CLK), .CONFIG_COMPLETER_ID(CONFIG_COMPLETER_ID), .TX_DATA(TX_DATA), .TX_DATA_BYTE_ENABLE(TX_DATA_BYTE_ENABLE), .TX_TLP_END_FLAG(TX_TLP_END_FLAG), .TX_TLP_START_FLAG(TX_TLP_START_FLAG), .TX_DATA_VALID(TX_DATA_VALID), .S_AXIS_SRC_DSC(S_AXIS_SRC_DSC), .TX_DATA_READY(TX_DATA_READY), .COMPL_REQ(COMPL_REQ), .COMPL_DONE(COMPL_DONE), .REQ_TC(REQ_TC), .REQ_TD(REQ_TD), .REQ_EP(REQ_EP), .REQ_ATTR(REQ_ATTR), .REQ_LEN(REQ_LEN), .REQ_ID(REQ_ID), .REQ_TAG(REQ_TAG), .REQ_BE(REQ_BE), .REQ_ADDR(REQ_ADDR), .REQ_DATA(REQ_DATA), .REQ_DATA_SENT(REQ_DATA_SENT), .FIFO_DATA(wFifoRdData), .FIFO_EMPTY(wFifoEmpty), .FIFO_REN(wFifoRen), .WR_SENT(WR_SENT) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_engine_64.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_engine_64.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Transmit engine for PCIe using AXI interface from Xilinx // PCIe Endpoint core. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: Very good PCIe header reference: // http://www.pzk-agro.com/0321156307_ch04lev1sec5.html#ch04lev4sec14 //----------------------------------------------------------------------------- module tx_engine_64 #( parameter C_PCI_DATA_WIDTH = 9'd64, parameter C_NUM_CHNL = 4'd12, parameter C_TAG_WIDTH = 5, // Number of outstanding requests parameter C_ALTERA = 1'b1, // 1 if Altera, 0 if Xilinx // Local parameters parameter C_FIFO_DEPTH = 512, parameter C_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_FIFO_DEPTH))+1) ) ( input CLK, input RST, input [15:0] CONFIG_COMPLETER_ID, input [2:0] CONFIG_MAX_PAYLOAD_SIZE, // Maximum write payload: 000=128B, 001=256B, 010=512B, 011=1024B output [C_PCI_DATA_WIDTH-1:0] TX_DATA, // AXI data output output [(C_PCI_DATA_WIDTH/8)-1:0] TX_DATA_BYTE_ENABLE, // AXI data keep output TX_TLP_END_FLAG, // AXI data last output TX_TLP_START_FLAG, // AXI data first output TX_DATA_VALID, // AXI data valid output S_AXIS_SRC_DSC, // AXI data discontinue input TX_DATA_READY, // AXI ready for data input [C_NUM_CHNL-1:0] WR_REQ, // Write request input [(C_NUM_CHNL*64)-1:0] WR_ADDR, // Write address input [(C_NUM_CHNL*10)-1:0] WR_LEN, // Write data length input [(C_NUM_CHNL*C_PCI_DATA_WIDTH)-1:0] WR_DATA, // Write data output [C_NUM_CHNL-1:0] WR_DATA_REN, // Write data read enable output [C_NUM_CHNL-1:0] WR_ACK, // Write request has been accepted output [C_NUM_CHNL-1:0] WR_SENT, // Pulsed at channel pos when write request sent input [C_NUM_CHNL-1:0] RD_REQ, // Read request input [(C_NUM_CHNL*2)-1:0] RD_SG_CHNL, // Read request channel for scatter gather lists input [(C_NUM_CHNL*64)-1:0] RD_ADDR, // Read request address input [(C_NUM_CHNL*10)-1:0] RD_LEN, // Read request length output [C_NUM_CHNL-1:0] RD_ACK, // Read request has been accepted output [5:0] INT_TAG, // Internal tag to exchange with external output INT_TAG_VALID, // High to signal tag exchange input [C_TAG_WIDTH-1:0] EXT_TAG, // External tag to provide in exchange for internal tag input EXT_TAG_VALID, // High to signal external tag is valid output TX_ENG_RD_REQ_SENT, // Read completion request issued input RXBUF_SPACE_AVAIL, input COMPL_REQ, // RX Engine request for completion output COMPL_DONE, // Completion done input [2:0] REQ_TC, input REQ_TD, input REQ_EP, input [1:0] REQ_ATTR, input [9:0] REQ_LEN, input [15:0] REQ_ID, input [7:0] REQ_TAG, input [3:0] REQ_BE, input [29:0] REQ_ADDR, input [31:0] REQ_DATA, output [31:0] REQ_DATA_SENT // Actual completion data sent ); `include "common_functions.v" wire [C_PCI_DATA_WIDTH-1:0] wFifoWrData; wire [C_PCI_DATA_WIDTH-1:0] wFifoRdData; wire [C_FIFO_DEPTH_WIDTH-1:0] wFifoCount; wire wFifoEmpty; wire wFifoRen; wire wFifoWen; wire wAltera = C_ALTERA; // Convert the read and write requests into PCI packet format and mux // them together into a FIFO. tx_engine_upper_64 #( .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH), .C_NUM_CHNL(C_NUM_CHNL), .C_FIFO_DEPTH(C_FIFO_DEPTH), .C_TAG_WIDTH(C_TAG_WIDTH), .C_ALTERA(C_ALTERA) ) upper ( .RST(RST), .CLK(CLK), .CONFIG_COMPLETER_ID(CONFIG_COMPLETER_ID), .CONFIG_MAX_PAYLOAD_SIZE(CONFIG_MAX_PAYLOAD_SIZE), .WR_REQ(WR_REQ), .WR_ADDR(WR_ADDR), .WR_LEN(WR_LEN), .WR_DATA(WR_DATA), .WR_DATA_REN(WR_DATA_REN), .WR_ACK(WR_ACK), .RD_REQ(RD_REQ), .RD_SG_CHNL(RD_SG_CHNL), .RD_ADDR(RD_ADDR), .RD_LEN(RD_LEN), .RD_ACK(RD_ACK), .TX_ENG_RD_REQ_SENT(TX_ENG_RD_REQ_SENT), .RXBUF_SPACE_AVAIL(RXBUF_SPACE_AVAIL | !wAltera), .INT_TAG(INT_TAG), .INT_TAG_VALID(INT_TAG_VALID), .EXT_TAG(EXT_TAG), .EXT_TAG_VALID(EXT_TAG_VALID), .FIFO_DATA(wFifoWrData), .FIFO_COUNT(wFifoCount), .FIFO_WEN(wFifoWen) ); // FIFO for storing outbound read/write requests. (* RAM_STYLE="BLOCK" *) sync_fifo #(.C_WIDTH(C_PCI_DATA_WIDTH), .C_DEPTH(C_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) fifo ( .RST(RST), .CLK(CLK), .WR_EN(wFifoWen), .WR_DATA(wFifoWrData), .FULL(), .COUNT(wFifoCount), .RD_EN(wFifoRen), .RD_DATA(wFifoRdData), .EMPTY(wFifoEmpty) ); // Process the formatted PCI packets in the FIFO and completions. // Completions take top priority. Mux the data into the AXI interface // for the PCIe Endpoint. tx_engine_lower_64 #( .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH), .C_NUM_CHNL(C_NUM_CHNL), .C_ALTERA(C_ALTERA) ) lower ( .RST(RST), .CLK(CLK), .CONFIG_COMPLETER_ID(CONFIG_COMPLETER_ID), .TX_DATA(TX_DATA), .TX_DATA_BYTE_ENABLE(TX_DATA_BYTE_ENABLE), .TX_TLP_END_FLAG(TX_TLP_END_FLAG), .TX_TLP_START_FLAG(TX_TLP_START_FLAG), .TX_DATA_VALID(TX_DATA_VALID), .S_AXIS_SRC_DSC(S_AXIS_SRC_DSC), .TX_DATA_READY(TX_DATA_READY), .COMPL_REQ(COMPL_REQ), .COMPL_DONE(COMPL_DONE), .REQ_TC(REQ_TC), .REQ_TD(REQ_TD), .REQ_EP(REQ_EP), .REQ_ATTR(REQ_ATTR), .REQ_LEN(REQ_LEN), .REQ_ID(REQ_ID), .REQ_TAG(REQ_TAG), .REQ_BE(REQ_BE), .REQ_ADDR(REQ_ADDR), .REQ_DATA(REQ_DATA), .REQ_DATA_SENT(REQ_DATA_SENT), .FIFO_DATA(wFifoRdData), .FIFO_EMPTY(wFifoEmpty), .FIFO_REN(wFifoRen), .WR_SENT(WR_SENT) ); endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_engine_formatter_128.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_engine_formatter_128.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Formats read and write request data into PCI packets. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: Very good PCIe header reference: // http://www.pzk-agro.com/0321156307_ch04lev1sec5.html#ch04lev4sec14 //----------------------------------------------------------------------------- `define FMT_TXENGFMTR128_WR32 7'b10_00000 `define FMT_TXENGFMTR128_RD32 7'b00_00000 `define FMT_TXENGFMTR128_WR64 7'b11_00000 `define FMT_TXENGFMTR128_RD64 7'b01_00000 `define S_TXENGFMTR128_IDLE 1'b0 `define S_TXENGFMTR128_WR 1'b1 module tx_engine_formatter_128 #( parameter C_PCI_DATA_WIDTH = 9'd128, // Local parameters parameter C_TRAFFIC_CLASS = 3'b0, parameter C_RELAXED_ORDER = 1'b0, parameter C_NO_SNOOP = 1'b0 ) ( input CLK, input RST, input [15:0] CONFIG_COMPLETER_ID, input VALID, // Are input parameters valid? input WNR, // Is a write request, not a read? input [7:0] TAG, // External tag input [3:0] CHNL, // Internal tag (just channel portion) input [61:0] ADDR, // Request address input ADDR_64, // Request address is 64 bit input [9:0] LEN, // Request length input LEN_ONE, // Request length equals 1 input [C_PCI_DATA_WIDTH-1:0] WR_DATA, // Request data, timed to arrive accordingly output [C_PCI_DATA_WIDTH-1:0] OUT_DATA, // Formatted PCI packet data output OUT_DATA_WEN // Write enable for formatted packet data ); reg rState=`S_TXENGFMTR128_IDLE, _rState=`S_TXENGFMTR128_IDLE; reg rAddr64=0, _rAddr64=0; reg [C_PCI_DATA_WIDTH-1:0] rData={C_PCI_DATA_WIDTH{1'd0}}, _rData={C_PCI_DATA_WIDTH{1'd0}}; reg [C_PCI_DATA_WIDTH-1:0] rPrevData={C_PCI_DATA_WIDTH{1'd0}}, _rPrevData={C_PCI_DATA_WIDTH{1'd0}}; reg rDataWen=0, _rDataWen=0; reg [9:0] rLen=0, _rLen=0; reg rDone=0, _rDone=0; assign OUT_DATA = rData; assign OUT_DATA_WEN = rDataWen; // Format read and write requests into PCIe packets. wire [63:0] wHdrData = ({WR_DATA[31:0], ADDR[29:0], 2'b00, ADDR[61:30]})>>(32*(!ADDR_64)); wire [C_PCI_DATA_WIDTH-1:0] wWrData = ({WR_DATA[31:0], rPrevData})>>(32*(!rAddr64)); always @ (posedge CLK) begin rState <= #1 (RST ? `S_TXENGFMTR128_IDLE : _rState); rDataWen <= #1 (RST ? 1'd0 : _rDataWen); rData <= #1 _rData; rLen <= #1 _rLen; rAddr64 <= #1 _rAddr64; rPrevData <= #1 _rPrevData; rDone <= #1 _rDone; end always @ (*) begin _rState = rState; _rLen = rLen; _rData = rData; _rDataWen = rDataWen; _rPrevData = WR_DATA; _rAddr64 = rAddr64; case (rState) `S_TXENGFMTR128_IDLE : begin // FIFO data should be available now (if it's a write) _rLen = LEN - !ADDR_64; // Subtract 1 for 32 bit (HDR has one) _rAddr64 = ADDR_64; _rData = {wHdrData, // DW3, DW2 CONFIG_COMPLETER_ID[15:3], 3'b0, TAG, (LEN_ONE ? 4'b0 : 4'b1111), 4'b1111, // DW1 1'b0, {WNR, ADDR_64, 5'd0}, 1'b0, C_TRAFFIC_CLASS, CHNL, 1'b0, 1'b0, // Use the reserved 4 bits before traffic class to hide the internal tag C_RELAXED_ORDER, C_NO_SNOOP, 2'b0, LEN}; // DW0 _rDataWen = VALID; _rDone = (LEN <= {1'b1, 1'b0, !ADDR_64}); _rState = (VALID & WNR & (ADDR_64 | !LEN_ONE) ? `S_TXENGFMTR128_WR : `S_TXENGFMTR128_IDLE); end `S_TXENGFMTR128_WR : begin _rLen = rLen - 3'd4; _rDone = (rLen <= 4'd8); _rData = wWrData; _rState = (rDone ? `S_TXENGFMTR128_IDLE : `S_TXENGFMTR128_WR); end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_engine_formatter_32.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_engine_formatter_32.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Formats read and write request data into PCI packets. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: Very good PCIe header reference: // http://www.pzk-agro.com/0321156307_ch04lev1sec5.html#ch04lev4sec14 //----------------------------------------------------------------------------- `define FMT_TXENGFMTR32_WR32 7'b10_00000 `define FMT_TXENGFMTR32_RD32 7'b00_00000 `define FMT_TXENGFMTR32_WR64 7'b11_00000 `define FMT_TXENGFMTR32_RD64 7'b01_00000 `define S_TXENGFMTR32_IDLE 3'd0 `define S_TXENGFMTR32_HDR_0 3'd1 `define S_TXENGFMTR32_HDR_1 3'd2 `define S_TXENGFMTR32_HDR_2 3'd3 `define S_TXENGFMTR32_WR 3'd4 module tx_engine_formatter_32 #( parameter C_PCI_DATA_WIDTH = 9'd32, // Local parameters parameter C_TRAFFIC_CLASS = 3'b0, parameter C_RELAXED_ORDER = 1'b0, parameter C_NO_SNOOP = 1'b0 ) ( input CLK, input RST, input [15:0] CONFIG_COMPLETER_ID, input VALID, // Are input parameters valid? input WNR, // Is a write request, not a read? input [7:0] TAG, // External tag input [3:0] CHNL, // Internal tag (just channel portion) input [61:0] ADDR, // Request address input ADDR_64, // Request address is 64 bit input [9:0] LEN, // Request length input LEN_ONE, // Request length equals 1 input [C_PCI_DATA_WIDTH-1:0] WR_DATA, // Request data, timed to arrive accordingly output [C_PCI_DATA_WIDTH-1:0] OUT_DATA, // Formatted PCI packet data output OUT_DATA_WEN // Write enable for formatted packet data ); reg [2:0] rState=`S_TXENGFMTR32_IDLE, _rState=`S_TXENGFMTR32_IDLE; reg [61:0] rAddr=62'd0, _rAddr=62'd0; reg rAddr64=0, _rAddr64=0; reg [C_PCI_DATA_WIDTH-1:0] rData={C_PCI_DATA_WIDTH{1'd0}}, _rData={C_PCI_DATA_WIDTH{1'd0}}; reg [C_PCI_DATA_WIDTH-1:0] rPrevData={C_PCI_DATA_WIDTH{1'd0}}, _rPrevData={C_PCI_DATA_WIDTH{1'd0}}; reg rDataWen=0, _rDataWen=0; reg [9:0] rLen=0, _rLen=0; reg rLenEQ1=0, _rLenEQ1=0; reg rWNR=0, _rWNR=0; reg [7:0] rTag=0, _rTag=0; reg rInitDone=0, _rInitDone=0; reg rDone=0, _rDone=0; assign OUT_DATA = rData; assign OUT_DATA_WEN = rDataWen; // Format read and write requests into PCIe packets. wire [31:0] wData = ({rPrevData, WR_DATA}>>(32*rAddr64)); always @ (posedge CLK) begin rState <= #1 (RST ? `S_TXENGFMTR32_IDLE : _rState); rDataWen <= #1 (RST ? 1'd0 : _rDataWen); rData <= #1 _rData; rLen <= #1 _rLen; rAddr <= #1 _rAddr; rAddr64 <= #1 _rAddr64; rWNR <= #1 _rWNR; rTag <= #1 _rTag; rLenEQ1 <= #1 _rLenEQ1; rInitDone <= #1 _rInitDone; rDone <= #1 _rDone; rPrevData <= #1 _rPrevData; end always @ (*) begin _rState = rState; _rLen = rLen; _rData = rData; _rDataWen = rDataWen; _rAddr64 = rAddr64; _rAddr = rAddr; _rWNR = rWNR; _rTag = rTag; _rLenEQ1 = rLenEQ1; _rInitDone = rInitDone; _rDone = rDone; _rPrevData = WR_DATA; case (rState) `S_TXENGFMTR32_IDLE : begin _rLen = LEN; _rAddr64 = ADDR_64; _rAddr = ADDR; _rWNR = WNR; _rTag = TAG; _rLenEQ1 = LEN_ONE; _rData = {1'b0, {WNR, ADDR_64, 5'd0}, 1'b0, C_TRAFFIC_CLASS, CHNL, 1'b0, 1'b0, // Use the reserved 4 bits before traffic class to hide the internal tag C_RELAXED_ORDER, C_NO_SNOOP, 2'b0, LEN}; _rDataWen = VALID; _rState = (VALID ? `S_TXENGFMTR32_HDR_0 : `S_TXENGFMTR32_IDLE); end `S_TXENGFMTR32_HDR_0 : begin _rData = {CONFIG_COMPLETER_ID[15:3], 3'b0, rTag, (rLenEQ1 ? 4'b0 : 4'b1111), 4'b1111}; _rInitDone = (!rAddr64 & !rWNR); _rState = (rAddr64 ? `S_TXENGFMTR32_HDR_1 : `S_TXENGFMTR32_HDR_2); end `S_TXENGFMTR32_HDR_1 : begin _rData = rAddr[61:30]; _rInitDone = !rWNR; _rState = `S_TXENGFMTR32_HDR_2; end `S_TXENGFMTR32_HDR_2 : begin // FIFO data should be available now (if it's a write) _rData = {rAddr[29:0], 2'b00}; _rDone = rLenEQ1; _rState = (rInitDone ? `S_TXENGFMTR32_IDLE : `S_TXENGFMTR32_WR); end `S_TXENGFMTR32_WR : begin _rLen = rLen - 1'd1; _rData = wData; _rDone = (rLen == 2'd2); _rState = (rDone ? `S_TXENGFMTR32_IDLE : `S_TXENGFMTR32_WR); end default : begin _rState = `S_TXENGFMTR32_IDLE; end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_engine_formatter_64.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_engine_formatter_64.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Formats read and write request data into PCI packets. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: Very good PCIe header reference: // http://www.pzk-agro.com/0321156307_ch04lev1sec5.html#ch04lev4sec14 //----------------------------------------------------------------------------- `define FMT_TXENGFMTR64_WR32 7'b10_00000 `define FMT_TXENGFMTR64_RD32 7'b00_00000 `define FMT_TXENGFMTR64_WR64 7'b11_00000 `define FMT_TXENGFMTR64_RD64 7'b01_00000 `define S_TXENGFMTR64_IDLE 2'b10 `define S_TXENGFMTR64_HDR 2'b01 `define S_TXENGFMTR64_WR 2'b00 module tx_engine_formatter_64 #( parameter C_PCI_DATA_WIDTH = 9'd64, // Local parameters parameter C_TRAFFIC_CLASS = 3'b0, parameter C_RELAXED_ORDER = 1'b0, parameter C_NO_SNOOP = 1'b0 ) ( input CLK, input RST, input [15:0] CONFIG_COMPLETER_ID, input VALID, // Are input parameters valid? input WNR, // Is a write request, not a read? input [7:0] TAG, // External tag input [3:0] CHNL, // Internal tag (just channel portion) input [61:0] ADDR, // Request address input ADDR_64, // Request address is 64 bit input [9:0] LEN, // Request length input LEN_ONE, // Request length equals 1 input [C_PCI_DATA_WIDTH-1:0] WR_DATA, // Request data, timed to arrive accordingly output [C_PCI_DATA_WIDTH-1:0] OUT_DATA, // Formatted PCI packet data output OUT_DATA_WEN // Write enable for formatted packet data ); (* fsm_encoding = "user" *) reg [1:0] rState=`S_TXENGFMTR64_IDLE, _rState=`S_TXENGFMTR64_IDLE; reg [61:0] rAddr=62'd0, _rAddr=62'd0; reg rAddr64=0, _rAddr64=0; reg [C_PCI_DATA_WIDTH-1:0] rData={C_PCI_DATA_WIDTH{1'd0}}, _rData={C_PCI_DATA_WIDTH{1'd0}}; reg [C_PCI_DATA_WIDTH-1:0] rPrevData={C_PCI_DATA_WIDTH{1'd0}}, _rPrevData={C_PCI_DATA_WIDTH{1'd0}}; reg rDataWen=0, _rDataWen=0; reg [9:0] rLen=0, _rLen=0; reg rInitDone=0, _rInitDone=0; reg rDone=0, _rDone=0; assign OUT_DATA = rData; assign OUT_DATA_WEN = rDataWen; // Format read and write requests into PCIe packets. wire [C_PCI_DATA_WIDTH-1:0] wHdrData = ({WR_DATA[31:0], rAddr[29:0], 2'b00, rAddr[61:30]})>>(32*(!rAddr64)); wire [C_PCI_DATA_WIDTH-1:0] wWrData = ({WR_DATA[31:0], rPrevData})>>(32*(!rAddr64)); always @ (posedge CLK) begin rState <= #1 (RST ? `S_TXENGFMTR64_IDLE : _rState); rDataWen <= #1 (RST ? 1'd0 : _rDataWen); rData <= #1 _rData; rLen <= #1 _rLen; rAddr <= #1 _rAddr; rAddr64 <= #1 _rAddr64; rPrevData <= #1 _rPrevData; rInitDone <= #1 _rInitDone; rDone <= #1 _rDone; end always @ (*) begin _rState = rState; _rLen = rLen; _rData = rData; _rDataWen = rDataWen; _rPrevData = WR_DATA; _rAddr64 = rAddr64; _rAddr = rAddr; _rInitDone = rInitDone; _rDone = (rLen <= 3'd4); case (rState) `S_TXENGFMTR64_IDLE : begin _rLen = LEN - !ADDR_64 + 2'd2; // Subtract 1 for 32 bit (HDR has one), add 2 so we can always decrement by 2 _rAddr64 = ADDR_64; _rAddr = ADDR; _rData = {CONFIG_COMPLETER_ID[15:3], 3'b0, TAG, (LEN_ONE ? 4'b0 : 4'b1111), 4'b1111, // DW1 1'b0, {WNR, ADDR_64, 5'd0}, 1'b0, C_TRAFFIC_CLASS, CHNL, 1'b0, 1'b0, // Use the reserved 4 bits before traffic class to hide the internal tag C_RELAXED_ORDER, C_NO_SNOOP, 2'b0, LEN}; // DW0 _rDataWen = VALID; _rInitDone = ((!ADDR_64 & LEN_ONE) | !WNR); _rState = (VALID ? `S_TXENGFMTR64_HDR : `S_TXENGFMTR64_IDLE); end `S_TXENGFMTR64_HDR : begin // FIFO data should be available now (if it's a write) _rLen = rLen - 2'd2; _rData = wHdrData; _rState = (rInitDone ? `S_TXENGFMTR64_IDLE : `S_TXENGFMTR64_WR); end `S_TXENGFMTR64_WR : begin _rLen = rLen - 2'd2; _rData = wWrData; _rState = (rDone ? `S_TXENGFMTR64_IDLE : `S_TXENGFMTR64_WR); end default : begin _rState = `S_TXENGFMTR64_IDLE; end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_engine_lower_128.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_engine_lower_128.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Transmit engine for completion requests and pre-formatted // PCIe read/write data. Muxes traffic for the AXI interface on the Xilinx PCIe // Endpoint core. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: Very good PCIe header reference: // http://www.pzk-agro.com/0321156307_ch04lev1sec5.html#ch04lev4sec14 // Also byte swap each payload word due to Xilinx incorrect mapping, see // http://forums.xilinx.com/t5/PCI-Express/PCI-Express-payload-required-to-be-Big-Endian-by-specification/td-p/285551 //----------------------------------------------------------------------------- `define FMT_TXENGLWR128_CPLD 7'b10_01010 `define S_TXENGLWR128_IDLE 2'd0 `define S_TXENGLWR128_CPLD_0 2'd1 `define S_TXENGLWR128_CPLD_1 2'd2 `define S_TXENGLWR128_WR 2'd3 module tx_engine_lower_128 #( parameter C_PCI_DATA_WIDTH = 9'd128, parameter C_NUM_CHNL = 4'd12, parameter C_ALTERA = 1'b1 ) ( input CLK, input RST, input [15:0] CONFIG_COMPLETER_ID, output [C_PCI_DATA_WIDTH-1:0] TX_DATA, // AXI data output output [(C_PCI_DATA_WIDTH/8)-1:0] TX_DATA_BYTE_ENABLE, // AXI data keep output TX_TLP_END_FLAG, // AXI data last output TX_DATA_VALID, // AXI data valid output S_AXIS_SRC_DSC, // AXI data discontinue output TX_TLP_START_FLAG, // AXI data start input TX_DATA_READY, // AXI ready for data input COMPL_REQ, // RX Engine request for completion output COMPL_DONE, // Completion done input [2:0] REQ_TC, input REQ_TD, input REQ_EP, input [1:0] REQ_ATTR, input [9:0] REQ_LEN, input [15:0] REQ_ID, input [7:0] REQ_TAG, input [3:0] REQ_BE, input [29:0] REQ_ADDR, input [31:0] REQ_DATA, output [31:0] REQ_DATA_SENT, // Actual completion data sent input [C_PCI_DATA_WIDTH-1:0] FIFO_DATA, // Read/Write FIFO requests + data input FIFO_EMPTY, // Read/Write FIFO is empty output FIFO_REN, // Read/Write FIFO read enable output [C_NUM_CHNL-1:0] WR_SENT // Pulsed at channel pos when write request sent ); reg [11:0] rByteCount=0; reg [6:0] rLowerAddr=0; reg rFifoRen=0, _rFifoRen=0; reg rFifoRenIssued=0, _rFifoRenIssued=0; reg rFifoDataEmpty=1, _rFifoDataEmpty=1; reg [2:0] rFifoDataValid=0, _rFifoDataValid=0; reg [(3*C_PCI_DATA_WIDTH)-1:0] rFifoData={3*C_PCI_DATA_WIDTH{1'd0}}, _rFifoData={3*C_PCI_DATA_WIDTH{1'd0}}; wire [(3*C_PCI_DATA_WIDTH)-1:0] wFifoData = (rFifoData>>(C_PCI_DATA_WIDTH*(!rFifoRen)))>>(C_PCI_DATA_WIDTH*(!rFifoRenIssued)); wire [2:0] wFifoDataValid = (rFifoDataValid>>(!rFifoRen))>>(!rFifoRenIssued); reg [1:0] rState=`S_TXENGLWR128_IDLE, _rState=`S_TXENGLWR128_IDLE; reg rComplDone=0, _rComplDone=0; reg rValid=0, _rValid=0; reg [C_PCI_DATA_WIDTH-1:0] rData={C_PCI_DATA_WIDTH{1'd0}}, _rData={C_PCI_DATA_WIDTH{1'd0}}; reg rLast=0, _rLast=0; reg rFirst=0, _rFirst=0; reg [3:0] rKeep=0, _rKeep=0; reg [C_NUM_CHNL-1:0] rDone=0, _rDone=0; reg [9:0] rLen=0, _rLen=0; reg rIsLast=0, _rIsLast=0; wire [31:0] wReqDataSwap; wire [7:0] wKeep = (8'b00001111<<(rLen[2:0])) | {8{!rIsLast}}; assign TX_DATA = rData; assign TX_DATA_BYTE_ENABLE = {{4{rKeep[3]}}, {4{rKeep[2]}}, {4{rKeep[1]}}, {4{rKeep[0]}}}; assign TX_TLP_END_FLAG = rLast; assign TX_TLP_START_FLAG = rFirst; assign TX_DATA_VALID = rValid; assign S_AXIS_SRC_DSC = 0; assign COMPL_DONE = rComplDone; generate if(C_ALTERA == 1'b1) begin : altera_data assign REQ_DATA_SENT = rData[127:96]; assign wReqDataSwap = REQ_DATA[31:0]; end else begin : xilinx_data assign REQ_DATA_SENT = {rData[103:96], rData[111:104], rData[119:112], rData[127:120]}; assign wReqDataSwap = {REQ_DATA[7:0], REQ_DATA[15:8], REQ_DATA[23:16], REQ_DATA[31:24]}; end endgenerate assign FIFO_REN = rFifoRen; assign WR_SENT = rDone; // Calculate byte count based on byte enable always @ (REQ_BE) begin casex (REQ_BE) 4'b1xx1 : rByteCount = 12'h004; 4'b01x1 : rByteCount = 12'h003; 4'b1x10 : rByteCount = 12'h003; 4'b0011 : rByteCount = 12'h002; 4'b0110 : rByteCount = 12'h002; 4'b1100 : rByteCount = 12'h002; 4'b0001 : rByteCount = 12'h001; 4'b0010 : rByteCount = 12'h001; 4'b0100 : rByteCount = 12'h001; 4'b1000 : rByteCount = 12'h001; 4'b0000 : rByteCount = 12'h001; endcase end // Calculate lower address based on byte enable always @ (REQ_BE or REQ_ADDR) begin casex (REQ_BE) 4'b0000 : rLowerAddr = {REQ_ADDR[4:0], 2'b00}; 4'bxxx1 : rLowerAddr = {REQ_ADDR[4:0], 2'b00}; 4'bxx10 : rLowerAddr = {REQ_ADDR[4:0], 2'b01}; 4'bx100 : rLowerAddr = {REQ_ADDR[4:0], 2'b10}; 4'b1000 : rLowerAddr = {REQ_ADDR[4:0], 2'b11}; endcase end // Read in the pre-formatted PCIe data. always @ (posedge CLK) begin rFifoRenIssued <= #1 (RST ? 1'd0 : _rFifoRenIssued); rFifoDataValid <= #1 (RST ? 1'd0 : _rFifoDataValid); rFifoDataEmpty <= #1 (RST ? 1'd1 : _rFifoDataEmpty); rFifoData <= #1 _rFifoData; end always @ (*) begin _rFifoRenIssued = rFifoRen; _rFifoDataEmpty = (rFifoRen ? FIFO_EMPTY : rFifoDataEmpty); if (rFifoRenIssued) begin _rFifoData = ((rFifoData<<(C_PCI_DATA_WIDTH)) | FIFO_DATA); _rFifoDataValid = ((rFifoDataValid<<1) | (!rFifoDataEmpty)); end else begin _rFifoData = rFifoData; _rFifoDataValid = rFifoDataValid; end end // Multiplex completion requests and read/write pre-formatted PCIe data onto // the AXI PCIe Endpoint interface. Remember that TX_DATA_READY may drop at // *any* time during transmission. So be sure to buffer enough data to // accommodate starts and stops. always @ (posedge CLK) begin rState <= #1 (RST ? `S_TXENGLWR128_IDLE : _rState); rComplDone <= #1 (RST ? 1'd0 : _rComplDone); rValid <= #1 (RST ? 1'd0 : _rValid); rFifoRen <= #1 (RST ? 1'd0 : _rFifoRen); rDone <= #1 (RST ? {C_NUM_CHNL{1'd0}} : _rDone); rData <= #1 _rData; rLast <= #1 _rLast; rKeep <= #1 _rKeep; rLen <= #1 _rLen; rIsLast <= #1 _rIsLast; rFirst <= #1 _rFirst; end always @ (*) begin _rState = rState; _rComplDone = rComplDone; _rValid = rValid; _rFifoRen = rFifoRen; _rData = rData; _rLast = rLast; _rKeep = rKeep; _rDone = rDone; _rLen = rLen; _rIsLast = rIsLast; _rFirst = rFirst; case (rState) `S_TXENGLWR128_IDLE : begin _rFifoRen = (TX_DATA_READY & !COMPL_REQ); _rDone = ((TX_DATA_READY & !COMPL_REQ & wFifoDataValid[0] & wFifoData[30])<>(!wFifoData[30] & !wFifoData[29])); // Not WRITE TLP && !64 bit _rLen = wFifoData[9:0] - !wFifoData[29]; // LEN - !64 bit _rIsLast = (wFifoData[9:0] <= {1'b1, 1'b0, !wFifoData[29]}); // LEN <= 4 + !64 bit if (COMPL_REQ) // PIO read completions _rState = `S_TXENGLWR128_CPLD_0; else if (wFifoDataValid[0]) // Read FIFO data if it's ready _rState = (wFifoData[30] & (wFifoData[29] | wFifoData[36]) ? `S_TXENGLWR128_WR : `S_TXENGLWR128_IDLE); // WRITE TLP & (64 bit | LEN != 1)? end end `S_TXENGLWR128_CPLD_0 : begin if (TX_DATA_READY) begin // Check for throttling _rComplDone = 1; _rValid = 1; _rLast = 1; _rFirst = 1; _rKeep = 4'b1111; _rData = {wReqDataSwap, // DW3 REQ_ID, REQ_TAG, 1'b0, rLowerAddr, // DW2 CONFIG_COMPLETER_ID[15:3], 3'b0, 3'b0, 1'b0, rByteCount, // DW1 1'b0, `FMT_TXENGLWR128_CPLD, 1'b0, REQ_TC, 4'b0, REQ_TD, REQ_EP, REQ_ATTR, 2'b0, REQ_LEN}; // DW0 _rState = `S_TXENGLWR128_CPLD_1; end end `S_TXENGLWR128_CPLD_1 : begin // Just wait a cycle for the COMP_REQ to drop. _rComplDone = 0; if (TX_DATA_READY) begin // Check for throttling _rFirst = 0; _rValid = 0; _rState = `S_TXENGLWR128_IDLE; end end `S_TXENGLWR128_WR : begin _rFifoRen = TX_DATA_READY; _rDone = 0; if (TX_DATA_READY) begin // Check for throttling _rFirst = 0; _rData = wFifoData[127:0]; _rValid = 1; _rLast = rIsLast; _rKeep = wKeep[7:4]; _rLen = rLen - 3'd4; _rIsLast = (rLen <= 4'd8); _rState = (rIsLast ? `S_TXENGLWR128_IDLE : `S_TXENGLWR128_WR); end end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_engine_lower_32.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_engine_lower_32.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Transmit engine for completion requests and pre-formatted // PCIe read/write data. Muxes traffic for the AXI interface on the Xilinx PCIe // Endpoint core. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: Very good PCIe header reference: // http://www.pzk-agro.com/0321156307_ch04lev1sec5.html#ch04lev4sec14 // Also byte swap each payload word due to Xilinx incorrect mapping, see // http://forums.xilinx.com/t5/PCI-Express/PCI-Express-payload-required-to-be-Big-Endian-by-specification/td-p/285551 //----------------------------------------------------------------------------- `define FMT_TXENGLWR32_CPLD 7'b10_01010 `define S_TXENGLWR32_IDLE 4'd0 `define S_TXENGLWR32_CPLD_0 4'd1 `define S_TXENGLWR32_CPLD_1 4'd2 `define S_TXENGLWR32_CPLD_2 4'd3 `define S_TXENGLWR32_CPLD_3 4'd4 `define S_TXENGLWR32_CPLD_4 4'd5 `define S_TXENGLWR32_MEM_0 4'd6 `define S_TXENGLWR32_RD_0 4'd7 `define S_TXENGLWR32_RD_1 4'd8 `define S_TXENGLWR32_WR_0 4'd9 `define S_TXENGLWR32_WR_1 4'd10 `define S_TXENGLWR32_WR_2 4'd11 module tx_engine_lower_32 #( parameter C_PCI_DATA_WIDTH = 9'd32, parameter C_NUM_CHNL = 4'd12 ) ( input CLK, input RST, input [15:0] CONFIG_COMPLETER_ID, output [C_PCI_DATA_WIDTH-1:0] TX_DATA, // AXI data output output [(C_PCI_DATA_WIDTH/8)-1:0] TX_DATA_BYTE_ENABLE, // AXI data keep output TX_TLP_END_FLAG, // AXI data last output TX_TLP_START_FLAG, // AXI data start output TX_DATA_VALID, // AXI data valid output S_AXIS_SRC_DSC, // AXI data discontinue input TX_DATA_READY, // AXI ready for data input COMPL_REQ, // RX Engine request for completion output COMPL_DONE, // Completion done input [2:0] REQ_TC, input REQ_TD, input REQ_EP, input [1:0] REQ_ATTR, input [9:0] REQ_LEN, input [15:0] REQ_ID, input [7:0] REQ_TAG, input [3:0] REQ_BE, input [29:0] REQ_ADDR, input [31:0] REQ_DATA, output [31:0] REQ_DATA_SENT, // Actual completion data sent input [C_PCI_DATA_WIDTH-1:0] FIFO_DATA, // Read/Write FIFO requests + data input FIFO_EMPTY, // Read/Write FIFO is empty output FIFO_REN, // Read/Write FIFO read enable output [C_NUM_CHNL-1:0] WR_SENT // Pulsed at channel pos when write request sent ); reg [11:0] rByteCount=0; reg [6:0] rLowerAddr=0; reg rFifoRen=0, _rFifoRen=0; reg rFifoRenIssued=0, _rFifoRenIssued=0; reg rFifoDataEmpty=1, _rFifoDataEmpty=1; reg [2:0] rFifoDataValid=0, _rFifoDataValid=0; reg [(3*C_PCI_DATA_WIDTH)-1:0] rFifoData={3*C_PCI_DATA_WIDTH{1'd0}}, _rFifoData={3*C_PCI_DATA_WIDTH{1'd0}}; wire [C_PCI_DATA_WIDTH-1:0] wFifoData = (rFifoData>>(C_PCI_DATA_WIDTH*(!rFifoRen)))>>(C_PCI_DATA_WIDTH*(!rFifoRenIssued)); wire wFifoDataValid = (rFifoDataValid>>(!rFifoRen))>>(!rFifoRenIssued); reg [3:0] rState=`S_TXENGLWR32_IDLE, _rState=`S_TXENGLWR32_IDLE; reg rComplDone=0, _rComplDone=0; reg rValid=0, _rValid=0; reg [C_PCI_DATA_WIDTH-1:0] rData={C_PCI_DATA_WIDTH{1'd0}}, _rData={C_PCI_DATA_WIDTH{1'd0}}; reg rLast=0, _rLast=0; reg [C_NUM_CHNL-1:0] rDone=0, _rDone=0; reg [9:0] rLen=0, _rLen=0; reg [3:0] rChnl=0, _rChnl=0; reg r3DW=0, _r3DW=0; reg rRNW=0, _rRNW=0; reg rIsLast=0, _rIsLast=0; assign TX_DATA = rData; assign TX_DATA_BYTE_ENABLE = {4'hF}; assign TX_TLP_END_FLAG = rLast; assign TX_TLP_START_FLAG = 1'b0; assign TX_DATA_VALID = rValid; assign S_AXIS_SRC_DSC = 1'b0; assign COMPL_DONE = rComplDone; assign REQ_DATA_SENT = {rData[7:0], rData[15:8], rData[23:16], rData[31:24]}; assign FIFO_REN = rFifoRen; assign WR_SENT = rDone; // Calculate byte count based on byte enable always @ (REQ_BE) begin casex (REQ_BE) 4'b1xx1 : rByteCount = 12'h004; 4'b01x1 : rByteCount = 12'h003; 4'b1x10 : rByteCount = 12'h003; 4'b0011 : rByteCount = 12'h002; 4'b0110 : rByteCount = 12'h002; 4'b1100 : rByteCount = 12'h002; 4'b0001 : rByteCount = 12'h001; 4'b0010 : rByteCount = 12'h001; 4'b0100 : rByteCount = 12'h001; 4'b1000 : rByteCount = 12'h001; 4'b0000 : rByteCount = 12'h001; endcase end // Calculate lower address based on byte enable always @ (REQ_BE or REQ_ADDR) begin casex (REQ_BE) 4'b0000 : rLowerAddr = {REQ_ADDR[4:0], 2'b00}; 4'bxxx1 : rLowerAddr = {REQ_ADDR[4:0], 2'b00}; 4'bxx10 : rLowerAddr = {REQ_ADDR[4:0], 2'b01}; 4'bx100 : rLowerAddr = {REQ_ADDR[4:0], 2'b10}; 4'b1000 : rLowerAddr = {REQ_ADDR[4:0], 2'b11}; endcase end // Read in the pre-formatted PCIe data. always @ (posedge CLK) begin rFifoRenIssued <= #1 (RST ? 1'd0 : _rFifoRenIssued); rFifoDataValid <= #1 (RST ? 1'd0 : _rFifoDataValid); rFifoDataEmpty <= #1 (RST ? 1'd1 : _rFifoDataEmpty); rFifoData <= #1 _rFifoData; end always @ (*) begin _rFifoRenIssued = rFifoRen; _rFifoDataEmpty = (rFifoRen ? FIFO_EMPTY : rFifoDataEmpty); if (rFifoRenIssued) begin _rFifoData = ((rFifoData<<(C_PCI_DATA_WIDTH)) | FIFO_DATA); _rFifoDataValid = ((rFifoDataValid<<1) | (!rFifoDataEmpty)); end else begin _rFifoData = rFifoData; _rFifoDataValid = rFifoDataValid; end end // Multiplex completion requests and read/write pre-formatted PCIe data onto // the AXI PCIe Endpoint interface. Remember that TX_DATA_READY may drop at // *any* time during transmission. So be sure to buffer enough data to // accommodate starts and stops. always @ (posedge CLK) begin rState <= #1 (RST ? `S_TXENGLWR32_IDLE : _rState); rComplDone <= #1 (RST ? 1'd0 : _rComplDone); rValid <= #1 (RST ? 1'd0 : _rValid); rFifoRen <= #1 (RST ? 1'd0 : _rFifoRen); rDone <= #1 (RST ? {C_NUM_CHNL{1'd0}} : _rDone); rData <= #1 _rData; rLast <= #1 _rLast; rChnl <= #1 _rChnl; r3DW <= #1 _r3DW; rRNW <= #1 _rRNW; rLen <= #1 _rLen; rIsLast <= #1 _rIsLast; end always @ (*) begin _rState = rState; _rComplDone = rComplDone; _rValid = rValid; _rFifoRen = rFifoRen; _rData = rData; _rLast = rLast; _rChnl = rChnl; _rDone = rDone; _r3DW = r3DW; _rRNW = rRNW; _rLen = rLen; _rIsLast = rIsLast; case (rState) `S_TXENGLWR32_IDLE : begin _rFifoRen = (TX_DATA_READY & !COMPL_REQ); _rDone = 0; if (TX_DATA_READY) begin // Check for throttling _rData = {wFifoData[31:20], 4'd0, wFifoData[15:0]}; // Revert the reserved 4 bits back to 0. _rValid = (!COMPL_REQ & wFifoDataValid); _rLast = 0; _rChnl = wFifoData[19:16]; // CHNL buried in header _r3DW = !wFifoData[29]; // !64 bit _rRNW = !wFifoData[30]; // !Write TLP _rLen = wFifoData[9:0]; // LEN if (COMPL_REQ) // PIO read completions _rState = `S_TXENGLWR32_CPLD_0; else if (wFifoDataValid) // Read FIFO data if it's ready _rState = `S_TXENGLWR32_MEM_0; end end `S_TXENGLWR32_CPLD_0 : begin if (TX_DATA_READY) begin // Check for throttling _rValid = 1; _rLast = 0; _rData = {1'b0, `FMT_TXENGLWR32_CPLD, 1'b0, REQ_TC, 4'b0, REQ_TD, REQ_EP, REQ_ATTR, 2'b0, REQ_LEN}; _rState = `S_TXENGLWR32_CPLD_1; end end `S_TXENGLWR32_CPLD_1 : begin if (TX_DATA_READY) begin // Check for throttling _rValid = 1; _rLast = 0; _rData = {CONFIG_COMPLETER_ID[15:3], 3'b0, 3'b0, 1'b0, rByteCount}; _rState = `S_TXENGLWR32_CPLD_2; end end `S_TXENGLWR32_CPLD_2 : begin if (TX_DATA_READY) begin // Check for throttling _rValid = 1; _rLast = 0; _rData = {REQ_ID, REQ_TAG, 1'b0, rLowerAddr}; _rState = `S_TXENGLWR32_CPLD_3; end end `S_TXENGLWR32_CPLD_3 : begin if (TX_DATA_READY) begin // Check for throttling _rComplDone = 1; _rValid = 1; _rLast = 1; _rData = {REQ_DATA[7:0], REQ_DATA[15:8], REQ_DATA[23:16], REQ_DATA[31:24]}; _rState = `S_TXENGLWR32_CPLD_4; end end `S_TXENGLWR32_CPLD_4 : begin // Just wait a cycle for the COMP_REQ to drop. _rComplDone = 0; if (TX_DATA_READY) begin // Check for throttling _rValid = 0; _rState = `S_TXENGLWR32_IDLE; end end `S_TXENGLWR32_MEM_0 : begin _rFifoRen = TX_DATA_READY; if (TX_DATA_READY) begin // Check for throttling _rData = wFifoData; _rValid = 1; _rLast = 0; _rState = (rRNW ? `S_TXENGLWR32_RD_0 : `S_TXENGLWR32_WR_0); end end `S_TXENGLWR32_RD_0 : begin _rFifoRen = TX_DATA_READY; if (TX_DATA_READY) begin // Check for throttling _rData = wFifoData; _rValid = 1; _rLast = r3DW; _rState = (r3DW ? `S_TXENGLWR32_IDLE : `S_TXENGLWR32_RD_1); end end `S_TXENGLWR32_RD_1 : begin _rFifoRen = TX_DATA_READY; if (TX_DATA_READY) begin // Check for throttling _rData = wFifoData; _rValid = 1; _rLast = 1; _rState = `S_TXENGLWR32_IDLE; end end `S_TXENGLWR32_WR_0 : begin _rFifoRen = TX_DATA_READY; if (TX_DATA_READY) begin // Check for throttling _rDone = (1'd1<>(C_PCI_DATA_WIDTH*(!rFifoRen)))>>(C_PCI_DATA_WIDTH*(!rFifoRenIssued)); wire wFifoDataValid = (rFifoDataValid>>(!rFifoRen))>>(!rFifoRenIssued); reg [2:0] rState=`S_TXENGLWR64_IDLE, _rState=`S_TXENGLWR64_IDLE; reg rComplDone=0, _rComplDone=0; reg rValid=0, _rValid=0; reg [C_PCI_DATA_WIDTH-1:0] rData={C_PCI_DATA_WIDTH{1'd0}}, _rData={C_PCI_DATA_WIDTH{1'd0}}; reg rLast=0, _rLast=0; reg rFirst=0, _rFirst=0; reg rKeep=0, _rKeep=0; reg [C_NUM_CHNL-1:0] rDone=0, _rDone=0; reg [9:0] rInitLen=0, _rInitLen=0; reg [9:0] rLen=0, _rLen=0; reg [3:0] rChnl=0, _rChnl=0; reg r3DW=0, _r3DW=0; reg rIsLast=0, _rIsLast=0; reg rInitIsLast=0, _rInitIsLast=0; wire [31:0] wReqDataSwap; assign TX_DATA = rData; assign TX_DATA_BYTE_ENABLE = {{4{rKeep}}, 4'hF}; assign TX_TLP_END_FLAG = rLast; assign TX_TLP_START_FLAG = rFirst; assign TX_DATA_VALID = rValid; assign S_AXIS_SRC_DSC = 0; assign COMPL_DONE = rComplDone; generate if(C_ALTERA == 1'b1) begin : altera_data assign REQ_DATA_SENT = rData[63:32]; assign wReqDataSwap = REQ_DATA[31:0]; end else begin : xilinx_data assign REQ_DATA_SENT = {rData[39:32], rData[47:40], rData[55:48], rData[63:56]}; assign wReqDataSwap = {REQ_DATA[7:0], REQ_DATA[15:8], REQ_DATA[23:16], REQ_DATA[31:24]}; end endgenerate assign FIFO_REN = rFifoRen; assign WR_SENT = rDone; // Calculate byte count based on byte enable always @ (REQ_BE) begin casex (REQ_BE) 4'b1xx1 : rByteCount = 12'h004; 4'b01x1 : rByteCount = 12'h003; 4'b1x10 : rByteCount = 12'h003; 4'b0011 : rByteCount = 12'h002; 4'b0110 : rByteCount = 12'h002; 4'b1100 : rByteCount = 12'h002; 4'b0001 : rByteCount = 12'h001; 4'b0010 : rByteCount = 12'h001; 4'b0100 : rByteCount = 12'h001; 4'b1000 : rByteCount = 12'h001; 4'b0000 : rByteCount = 12'h001; endcase end // Calculate lower address based on byte enable always @ (REQ_BE or REQ_ADDR) begin casex (REQ_BE) 4'b0000 : rLowerAddr = {REQ_ADDR[4:0], 2'b00}; 4'bxxx1 : rLowerAddr = {REQ_ADDR[4:0], 2'b00}; 4'bxx10 : rLowerAddr = {REQ_ADDR[4:0], 2'b01}; 4'bx100 : rLowerAddr = {REQ_ADDR[4:0], 2'b10}; 4'b1000 : rLowerAddr = {REQ_ADDR[4:0], 2'b11}; endcase end // Read in the pre-formatted PCIe data. always @ (posedge CLK) begin rFifoRenIssued <= #1 (RST ? 1'd0 : _rFifoRenIssued); rFifoDataValid <= #1 (RST ? 1'd0 : _rFifoDataValid); rFifoDataEmpty <= #1 (RST ? 1'd1 : _rFifoDataEmpty); rFifoData <= #1 _rFifoData; end always @ (*) begin _rFifoRenIssued = rFifoRen; _rFifoDataEmpty = (rFifoRen ? FIFO_EMPTY : rFifoDataEmpty); if (rFifoRenIssued) begin _rFifoData = ((rFifoData<<(C_PCI_DATA_WIDTH)) | FIFO_DATA); _rFifoDataValid = ((rFifoDataValid<<1) | (!rFifoDataEmpty)); end else begin _rFifoData = rFifoData; _rFifoDataValid = rFifoDataValid; end end // Multiplex completion requests and read/write pre-formatted PCIe data onto // the AXI PCIe Endpoint interface. Remember that TX_DATA_READY may drop at // *any* time during transmission. So be sure to buffer enough data to // accommodate starts and stops. always @ (posedge CLK) begin rState <= #1 (RST ? `S_TXENGLWR64_IDLE : _rState); rComplDone <= #1 (RST ? 1'd0 : _rComplDone); rValid <= #1 (RST ? 1'd0 : _rValid); rFifoRen <= #1 (RST ? 1'd0 : _rFifoRen); rDone <= #1 (RST ? {C_NUM_CHNL{1'd0}} : _rDone); rData <= #1 _rData; rLast <= #1 _rLast; rKeep <= #1 _rKeep; rChnl <= #1 _rChnl; r3DW <= #1 _r3DW; rLen <= #1 _rLen; rInitLen <= #1 _rInitLen; rIsLast <= #1 _rIsLast; rInitIsLast <= #1 _rInitIsLast; rFirst <= #1 _rFirst; end always @ (*) begin _rState = rState; _rComplDone = rComplDone; _rValid = rValid; _rFifoRen = rFifoRen; _rData = rData; _rLast = rLast; _rKeep = rKeep; _rChnl = rChnl; _rDone = rDone; _r3DW = r3DW; _rLen = rLen; _rInitLen = rInitLen; _rIsLast = rIsLast; _rInitIsLast = rInitIsLast; _rFirst = rFirst; case (rState) `S_TXENGLWR64_IDLE : begin _rFifoRen = (TX_DATA_READY & !COMPL_REQ); _rDone = 0; if (TX_DATA_READY) begin // Check for throttling _rData = {wFifoData[63:20], 4'd0, wFifoData[15:0]}; // Revert the reserved 4 bits back to 0. _rValid = (!COMPL_REQ & wFifoDataValid); _rFirst = 1; _rLast = 0; _rKeep = 1; _rChnl = wFifoData[19:16]; // CHNL buried in header _r3DW = !wFifoData[29]; // !64 bit _rInitLen = wFifoData[9:0]; // LEN _rInitIsLast = (!wFifoData[29] & !wFifoData[36]); // !64 bit && !(LEN != 1) if (COMPL_REQ) // PIO read completions _rState = `S_TXENGLWR64_CPLD_0; else if (wFifoDataValid) // Read FIFO data if it's ready _rState = (wFifoData[30] ? `S_TXENGLWR64_WR_0 : `S_TXENGLWR64_RD_0); // WRITE TLP? end end `S_TXENGLWR64_CPLD_0 : begin if (TX_DATA_READY) begin // Check for throttling _rFirst = 1; _rValid = 1; _rLast = 0; _rKeep = 1; _rData = {CONFIG_COMPLETER_ID[15:3], 3'b0, 3'b0, 1'b0, rByteCount, // DW1 1'b0, `FMT_TXENGLWR64_CPLD, 1'b0, REQ_TC, 4'b0, REQ_TD, REQ_EP, REQ_ATTR, 2'b0, REQ_LEN}; // DW0 _rState = `S_TXENGLWR64_CPLD_1; end end `S_TXENGLWR64_CPLD_1 : begin // Send rest of header and requested data if (TX_DATA_READY) begin // Check for throttling _rComplDone = 1; _rValid = 1; _rFirst = 0; _rLast = 1; _rKeep = 1; _rData = {wReqDataSwap, // DW3 REQ_ID, REQ_TAG, 1'b0, rLowerAddr}; // DW2 _rState = `S_TXENGLWR64_CPLD_2; end end `S_TXENGLWR64_CPLD_2 : begin // Just wait a cycle for the COMP_REQ to drop. _rComplDone = 0; if (TX_DATA_READY) begin // Check for throttling _rValid = 0; _rFirst = 0; _rState = `S_TXENGLWR64_IDLE; end end `S_TXENGLWR64_RD_0 : begin _rFifoRen = TX_DATA_READY; if (TX_DATA_READY) begin // Check for throttling _rData = wFifoData; _rValid = 1; _rFirst = 0; _rLast = 1; _rKeep = !r3DW; _rState = `S_TXENGLWR64_IDLE; end end `S_TXENGLWR64_WR_0 : begin _rFifoRen = TX_DATA_READY; if (TX_DATA_READY) begin // Check for throttling _rDone = (1'd1<>(rChnlNextNext)); reg rReq=0, _rReq=0; wire wReq = (REQ_ALL>>(rReqChnl)); reg rReqChnlNextUpdated=0, _rReqChnlNextUpdated=0; assign REQ = rReq; assign CHNL = rReqChnl; // Search for the next request so that we can move onto it immediately after // the current channel has released its request. always @ (posedge CLK) begin rReq <= #1 (RST ? 1'd0 : _rReq); rReqChnl <= #1 (RST ? 4'd0 : _rReqChnl); rReqChnlNext <= #1 (RST ? 4'd0 : _rReqChnlNext); rChnlNext <= #1 (RST ? 4'd0 : _rChnlNext); rChnlNextNext <= #1 (RST ? 4'd0 : _rChnlNextNext); rChnlNextDfrnt <= #1 (RST ? 1'd0 : _rChnlNextDfrnt); rChnlNextNextOn <= #1 (RST ? 1'd0 : _rChnlNextNextOn); rReqChnlsSame <= #1 (RST ? 1'd0 : _rReqChnlsSame); rReqChnlNextUpdated <= #1 (RST ? 1'd1 : _rReqChnlNextUpdated); end always @ (*) begin // Go through each channel (RR), looking for requests _rChnlNextNextOn = wChnlNextNextOn; _rChnlNext = rChnlNextNext; _rChnlNextNext = (rChnlNextNext == C_NUM_CHNL - 1 ? 4'd0 : rChnlNextNext + 1'd1); _rChnlNextDfrnt = (rChnlNextNext != rReqChnl); _rReqChnlsSame = (rReqChnlNext == rReqChnl); // Save ready channel if it is not the same channel we're currently on if (rChnlNextNextOn & rChnlNextDfrnt & rReqChnlsSame & !rReqChnlNextUpdated) begin _rReqChnlNextUpdated = 1; _rReqChnlNext = rChnlNext; end else begin _rReqChnlNextUpdated = 0; _rReqChnlNext = rReqChnlNext; end // Assign the new channel _rReq = wReq; _rReqChnl = (!rReq ? rReqChnlNext : rReqChnl); end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_engine_upper_128.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_engine_upper_128.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Formats read/write requests into PCI packets and adds // them to a FIFO. The FIFO will be read by the tx_engine_lower core and transmitted // to the attached PCIe Endpoint. // Author: Matt Jacobsen // History: @mattj: Version 2.0 // Additional Comments: Very good PCIe header reference: // http://www.pzk-agro.com/0321156307_ch04lev1sec5.html#ch04lev4sec14 // Also byte swap each payload word due to Xilinx incorrect mapping, see // http://forums.xilinx.com/t5/PCI-Express/PCI-Express-payload-required-to-be-Big-Endian-by-specification/td-p/285551 //----------------------------------------------------------------------------- `define FMT_TXENGUPR128_WR32 7'b10_00000 `define FMT_TXENGUPR128_RD32 7'b00_00000 `define FMT_TXENGUPR128_WR64 7'b11_00000 `define FMT_TXENGUPR128_RD64 7'b01_00000 `define S_TXENGUPR128_MAIN_IDLE 1'b0 `define S_TXENGUPR128_MAIN_WR 1'b1 `define S_TXENGUPR128_CAP_RD_WR 4'b0001 `define S_TXENGUPR128_CAP_WR_RD 4'b0010 `define S_TXENGUPR128_CAP_CAP 4'b0100 `define S_TXENGUPR128_CAP_REL 4'b1000 module tx_engine_upper_128 #( parameter C_PCI_DATA_WIDTH = 9'd128, parameter C_NUM_CHNL = 4'd12, parameter C_FIFO_DEPTH = 512, parameter C_TAG_WIDTH = 5, // Number of outstanding requests parameter C_ALTERA = 1'b1, // Local parameters parameter C_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_FIFO_DEPTH))+1), parameter C_MAX_ENTRIES = (11'd128*11'd8/C_PCI_DATA_WIDTH), parameter C_DATA_DELAY = 3'd6 // Delays read/write params to accommodate tx_port_buffer delay and tx_engine_formatter delay. ) ( input CLK, input RST, input [15:0] CONFIG_COMPLETER_ID, input [2:0] CONFIG_MAX_PAYLOAD_SIZE, // Maximum write payload: 000=128B, 001=256B, 010=512B, 011=1024B input [C_NUM_CHNL-1:0] WR_REQ, // Write request input [(C_NUM_CHNL*64)-1:0] WR_ADDR, // Write address input [(C_NUM_CHNL*10)-1:0] WR_LEN, // Write data length input [(C_NUM_CHNL*C_PCI_DATA_WIDTH)-1:0] WR_DATA, // Write data output [C_NUM_CHNL-1:0] WR_DATA_REN, // Write data read enable output [C_NUM_CHNL-1:0] WR_ACK, // Write request has been accepted input [C_NUM_CHNL-1:0] RD_REQ, // Read request input [(C_NUM_CHNL*2)-1:0] RD_SG_CHNL, // Read request channel for scatter gather lists input [(C_NUM_CHNL*64)-1:0] RD_ADDR, // Read request address input [(C_NUM_CHNL*10)-1:0] RD_LEN, // Read request length output [C_NUM_CHNL-1:0] RD_ACK, // Read request has been accepted output [5:0] INT_TAG, // Internal tag to exchange with external output INT_TAG_VALID, // High to signal tag exchange input [C_TAG_WIDTH-1:0] EXT_TAG, // External tag to provide in exchange for internal tag input EXT_TAG_VALID, // High to signal external tag is valid output TX_ENG_RD_REQ_SENT, // Read completion request issued input RXBUF_SPACE_AVAIL, output [C_PCI_DATA_WIDTH-1:0] FIFO_DATA, // Formatted read/write request data input [C_FIFO_DEPTH_WIDTH-1:0] FIFO_COUNT, // Formatted read/write FIFO count output FIFO_WEN // Formatted read/write FIFO read enable ); `include "common_functions.v" reg rMainState=`S_TXENGUPR128_MAIN_IDLE, _rMainState=`S_TXENGUPR128_MAIN_IDLE; reg rCountIsWr=0, _rCountIsWr=0; reg [9:0] rCountLen=0, _rCountLen=0; reg [3:0] rCountChnl=0, _rCountChnl=0; reg [C_TAG_WIDTH-1:0] rCountTag=0, _rCountTag=0; reg [61:0] rCountAddr=62'd0, _rCountAddr=62'd0; reg rCountAddr64=0, _rCountAddr64=0; reg [9:0] rCount=0, _rCount=0; reg rCountDone=0, _rCountDone=0; reg rCountValid=0, _rCountValid=0; reg [C_NUM_CHNL-1:0] rWrDataRen=0, _rWrDataRen=0; reg rTxEngRdReqAck, _rTxEngRdReqAck; wire wRdReq; wire [3:0] wRdReqChnl; wire wWrReq; wire [3:0] wWrReqChnl; wire wRdAck; wire [3:0] wCountChnl; wire [11:0] wCountChnlShiftDW = (wCountChnl*C_PCI_DATA_WIDTH); // Mult can exceed 9 bits, so make this a wire wire [63:0] wRdAddr = (RD_ADDR>>(wRdReqChnl*64)); wire [9:0] wRdLen = (RD_LEN>>(wRdReqChnl*10)); wire [1:0] wRdSgChnl = (RD_SG_CHNL>>(wRdReqChnl*2)); wire [63:0] wWrAddr = (WR_ADDR>>(wWrReqChnl*64)); wire [9:0] wWrLen = (WR_LEN>>(wWrReqChnl*10)); wire [C_PCI_DATA_WIDTH-1:0] wWrData = (WR_DATA>>wCountChnlShiftDW); wire [C_PCI_DATA_WIDTH-1:0] wWrDataSwap; reg [3:0] rRdChnl=0, _rRdChnl=0; reg [61:0] rRdAddr=62'd0, _rRdAddr=62'd0; reg [9:0] rRdLen=0, _rRdLen=0; reg [1:0] rRdSgChnl=0, _rRdSgChnl=0; reg [3:0] rWrChnl=0, _rWrChnl=0; reg [61:0] rWrAddr=62'd0, _rWrAddr=62'd0; reg [9:0] rWrLen=0, _rWrLen=0; reg [C_PCI_DATA_WIDTH-1:0] rWrData={C_PCI_DATA_WIDTH{1'd0}}, _rWrData={C_PCI_DATA_WIDTH{1'd0}}; generate if(C_ALTERA == 1'b1) begin : altera_data assign wWrDataSwap = rWrData; end else begin : xilinx_data assign wWrDataSwap = {rWrData[103:96], rWrData[111:104], rWrData[119:112], rWrData[127:120], rWrData[71:64], rWrData[79:72], rWrData[87:80], rWrData[95:88], rWrData[39:32], rWrData[47:40], rWrData[55:48], rWrData[63:56], rWrData[07:00], rWrData[15:08], rWrData[23:16], rWrData[31:24]}; end endgenerate (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [3:0] rCapState=`S_TXENGUPR128_CAP_RD_WR, _rCapState=`S_TXENGUPR128_CAP_RD_WR; reg [C_NUM_CHNL-1:0] rRdAck=0, _rRdAck=0; reg [C_NUM_CHNL-1:0] rWrAck=0, _rWrAck=0; reg rIsWr=0, _rIsWr=0; reg [5:0] rCapChnl=0, _rCapChnl=0; reg [61:0] rCapAddr=62'd0, _rCapAddr=62'd0; reg rCapAddr64=0, _rCapAddr64=0; reg [9:0] rCapLen=0, _rCapLen=0; reg rCapIsWr=0, _rCapIsWr=0; reg rExtTagReq=0, _rExtTagReq=0; reg [C_TAG_WIDTH-1:0] rExtTag=0, _rExtTag=0; reg [C_FIFO_DEPTH_WIDTH-1:0] rFifoCount=0, _rFifoCount=0; reg [9:0] rMaxEntries=0, _rMaxEntries=0; reg rSpaceAvail=0, _rSpaceAvail=0; reg [C_DATA_DELAY-1:0] rWnR=0, _rWnR=0; reg [(C_DATA_DELAY*4)-1:0] rChnl=0, _rChnl=0; reg [(C_DATA_DELAY*8)-1:0] rTag=0, _rTag=0; reg [(C_DATA_DELAY*62)-1:0] rAddr=0, _rAddr=0; reg [C_DATA_DELAY-1:0] rAddr64=0, _rAddr64=0; reg [(C_DATA_DELAY*10)-1:0] rLen=0, _rLen=0; reg [C_DATA_DELAY-1:0] rLenEQ1=0, _rLenEQ1=0; reg [C_DATA_DELAY-1:0] rValid=0, _rValid=0; assign WR_DATA_REN = rWrDataRen; assign WR_ACK = rWrAck; assign RD_ACK = rRdAck; assign INT_TAG = {rRdSgChnl, rRdChnl}; assign INT_TAG_VALID = rExtTagReq; assign TX_ENG_RD_REQ_SENT = rTxEngRdReqAck; assign wRdAck = (wRdReq & EXT_TAG_VALID & RXBUF_SPACE_AVAIL); // Search for the next request so that we can move onto it immediately after // the current channel has released its request. tx_engine_selector #(.C_NUM_CHNL(C_NUM_CHNL)) selRd (.RST(RST), .CLK(CLK), .REQ_ALL(RD_REQ), .REQ(wRdReq), .CHNL(wRdReqChnl)); tx_engine_selector #(.C_NUM_CHNL(C_NUM_CHNL)) selWr (.RST(RST), .CLK(CLK), .REQ_ALL(WR_REQ), .REQ(wWrReq), .CHNL(wWrReqChnl)); // Buffer shift-selected channel request signals and FIFO data. always @ (posedge CLK) begin rRdChnl <= #1 _rRdChnl; rRdAddr <= #1 _rRdAddr; rRdLen <= #1 _rRdLen; rRdSgChnl <= #1 _rRdSgChnl; rWrChnl <= #1 _rWrChnl; rWrAddr <= #1 _rWrAddr; rWrLen <= #1 _rWrLen; rWrData <= #1 _rWrData; end always @ (*) begin _rRdChnl = wRdReqChnl; _rRdAddr = wRdAddr[63:2]; _rRdLen = wRdLen; _rRdSgChnl = wRdSgChnl; _rWrChnl = wWrReqChnl; _rWrAddr = wWrAddr[63:2]; _rWrLen = wWrLen; _rWrData = wWrData; end // Accept requests when the selector indicates. Capture the buffered // request parameters for hand-off to the formatting pipeline. Then // acknowledge the receipt to the channel so it can deassert the // request, and let the selector choose another channel. always @ (posedge CLK) begin rCapState <= #1 (RST ? `S_TXENGUPR128_CAP_RD_WR : _rCapState); rRdAck <= #1 (RST ? {C_NUM_CHNL{1'd0}} : _rRdAck); rWrAck <= #1 (RST ? {C_NUM_CHNL{1'd0}} : _rWrAck); rIsWr <= #1 _rIsWr; rCapChnl <= #1 _rCapChnl; rCapAddr <= #1 _rCapAddr; rCapAddr64 <= #1 _rCapAddr64; rCapLen <= #1 _rCapLen; rCapIsWr <= #1 _rCapIsWr; rExtTagReq <= #1 _rExtTagReq; rExtTag <= #1 _rExtTag; rTxEngRdReqAck <= #1 _rTxEngRdReqAck; end always @ (*) begin _rCapState = rCapState; _rRdAck = rRdAck; _rWrAck = rWrAck; _rIsWr = rIsWr; _rCapChnl = rCapChnl; _rCapAddr = rCapAddr; _rCapAddr64 = rCapAddr64; _rCapLen = rCapLen; _rCapIsWr = rCapIsWr; _rExtTagReq = rExtTagReq; _rExtTag = rExtTag; _rTxEngRdReqAck = rTxEngRdReqAck; case (rCapState) `S_TXENGUPR128_CAP_RD_WR : begin _rIsWr = !wRdReq; _rRdAck = ((wRdAck)<>(rCapIsWr)); // Changes to S_TXENGUPR128_CAP_RD_WR end default : begin _rCapState = `S_TXENGUPR128_CAP_RD_WR; end endcase end // Calculate the available space in the FIFO, accounting for the // formatting pipeline depth. This will be conservative. wire [9:0] wMaxEntries = (C_MAX_ENTRIES<>(wRdReqChnl*64)); wire [9:0] wRdLen = (RD_LEN>>(wRdReqChnl*10)); wire [1:0] wRdSgChnl = (RD_SG_CHNL>>(wRdReqChnl*2)); wire [63:0] wWrAddr = (WR_ADDR>>(wWrReqChnl*64)); wire [9:0] wWrLen = (WR_LEN>>(wWrReqChnl*10)); wire [C_PCI_DATA_WIDTH-1:0] wWrData = (WR_DATA>>wCountChnlShiftDW); reg [3:0] rRdChnl=0, _rRdChnl=0; reg [61:0] rRdAddr=62'd0, _rRdAddr=62'd0; reg [9:0] rRdLen=0, _rRdLen=0; reg [1:0] rRdSgChnl=0, _rRdSgChnl=0; reg [3:0] rWrChnl=0, _rWrChnl=0; reg [61:0] rWrAddr=62'd0, _rWrAddr=62'd0; reg [9:0] rWrLen=0, _rWrLen=0; reg [C_PCI_DATA_WIDTH-1:0] rWrData={C_PCI_DATA_WIDTH{1'd0}}, _rWrData={C_PCI_DATA_WIDTH{1'd0}}; wire [C_PCI_DATA_WIDTH-1:0] wWrDataSwap = {rWrData[7:0], rWrData[15:8], rWrData[23:16], rWrData[31:24]}; (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [3:0] rCapState=`S_TXENGUPR32_CAP_RD_WR, _rCapState=`S_TXENGUPR32_CAP_RD_WR; reg [C_NUM_CHNL-1:0] rRdAck=0, _rRdAck=0; reg [C_NUM_CHNL-1:0] rWrAck=0, _rWrAck=0; reg rIsWr=0, _rIsWr=0; reg [5:0] rCapChnl=0, _rCapChnl=0; reg [61:0] rCapAddr=62'd0, _rCapAddr=62'd0; reg rCapAddr64=0, _rCapAddr64=0; reg [9:0] rCapLen=0, _rCapLen=0; reg rCapIsWr=0, _rCapIsWr=0; reg rExtTagReq=0, _rExtTagReq=0; reg [C_TAG_WIDTH-1:0] rExtTag=0, _rExtTag=0; reg [C_FIFO_DEPTH_WIDTH-1:0] rFifoCount=0, _rFifoCount=0; reg [9:0] rMaxEntries=0, _rMaxEntries=0; reg rSpaceAvail=0, _rSpaceAvail=0; reg [C_DATA_DELAY-1:0] rWnR=0, _rWnR=0; reg [(C_DATA_DELAY*4)-1:0] rChnl=0, _rChnl=0; reg [(C_DATA_DELAY*8)-1:0] rTag=0, _rTag=0; reg [(C_DATA_DELAY*62)-1:0] rAddr=0, _rAddr=0; reg [C_DATA_DELAY-1:0] rAddr64=0, _rAddr64=0; reg [(C_DATA_DELAY*10)-1:0] rLen=0, _rLen=0; reg [C_DATA_DELAY-1:0] rLenEQ1=0, _rLenEQ1=0; reg [C_DATA_DELAY-1:0] rValid=0, _rValid=0; assign WR_DATA_REN = rWrDataRen; assign WR_ACK = rWrAck; assign RD_ACK = rRdAck; assign INT_TAG = {rRdSgChnl, rRdChnl}; assign INT_TAG_VALID = rExtTagReq; assign TX_ENG_RD_REQ_SENT = rTxEngRdReqAck; assign wRdAck = (wRdReq & EXT_TAG_VALID & RXBUF_SPACE_AVAIL); // Search for the next request so that we can move onto it immediately after // the current channel has released its request. tx_engine_selector #(.C_NUM_CHNL(C_NUM_CHNL)) selRd (.RST(RST), .CLK(CLK), .REQ_ALL(RD_REQ), .REQ(wRdReq), .CHNL(wRdReqChnl)); tx_engine_selector #(.C_NUM_CHNL(C_NUM_CHNL)) selWr (.RST(RST), .CLK(CLK), .REQ_ALL(WR_REQ), .REQ(wWrReq), .CHNL(wWrReqChnl)); // Buffer shift-selected channel request signals and FIFO data. always @ (posedge CLK) begin rRdChnl <= #1 _rRdChnl; rRdAddr <= #1 _rRdAddr; rRdLen <= #1 _rRdLen; rRdSgChnl <= #1 _rRdSgChnl; rWrChnl <= #1 _rWrChnl; rWrAddr <= #1 _rWrAddr; rWrLen <= #1 _rWrLen; rWrData <= #1 _rWrData; end always @ (*) begin _rRdChnl = wRdReqChnl; _rRdAddr = wRdAddr[63:2]; _rRdLen = wRdLen; _rRdSgChnl = wRdSgChnl; _rWrChnl = wWrReqChnl; _rWrAddr = wWrAddr[63:2]; _rWrLen = wWrLen; _rWrData = wWrData; end // Accept requests when the selector indicates. Capture the buffered // request parameters for hand-off to the formatting pipeline. Then // acknowledge the receipt to the channel so it can deassert the // request, and let the selector choose another channel. always @ (posedge CLK) begin rCapState <= #1 (RST ? `S_TXENGUPR32_CAP_RD_WR : _rCapState); rRdAck <= #1 (RST ? {C_NUM_CHNL{1'd0}} : _rRdAck); rWrAck <= #1 (RST ? {C_NUM_CHNL{1'd0}} : _rWrAck); rIsWr <= #1 _rIsWr; rCapChnl <= #1 _rCapChnl; rCapAddr <= #1 _rCapAddr; rCapAddr64 <= #1 _rCapAddr64; rCapLen <= #1 _rCapLen; rCapIsWr <= #1 _rCapIsWr; rExtTagReq <= #1 _rExtTagReq; rExtTag <= #1 _rExtTag; rTxEngRdReqAck <= #1 _rTxEngRdReqAck; end always @ (*) begin _rCapState = rCapState; _rRdAck = rRdAck; _rWrAck = rWrAck; _rIsWr = rIsWr; _rCapChnl = rCapChnl; _rCapAddr = rCapAddr; _rCapAddr64 = (rCapAddr[61:30] != 0); _rCapLen = rCapLen; _rCapIsWr = rCapIsWr; _rExtTagReq = rExtTagReq; _rExtTag = rExtTag; _rTxEngRdReqAck = rTxEngRdReqAck; case (rCapState) `S_TXENGUPR32_CAP_RD_WR : begin _rIsWr = !wRdReq; _rRdAck = ((wRdAck)<>(rCapIsWr)); // Changes to S_TXENGUPR32_CAP_RD_WR end default : begin _rCapState = `S_TXENGUPR32_CAP_RD_WR; end endcase end // Calculate the available space in the FIFO, accounting for the // formatting pipeline depth. This will be conservative. wire [9:0] wMaxEntries = (C_MAX_ENTRIES<>(wRdReqChnl*64)); wire [9:0] wRdLen = (RD_LEN>>(wRdReqChnl*10)); wire [1:0] wRdSgChnl = (RD_SG_CHNL>>(wRdReqChnl*2)); wire [63:0] wWrAddr = (WR_ADDR>>(wWrReqChnl*64)); wire [9:0] wWrLen = (WR_LEN>>(wWrReqChnl*10)); wire [C_PCI_DATA_WIDTH-1:0] wWrData = (WR_DATA>>wCountChnlShiftDW); reg [3:0] rRdChnl=0, _rRdChnl=0; reg [61:0] rRdAddr=62'd0, _rRdAddr=62'd0; reg [9:0] rRdLen=0, _rRdLen=0; reg [1:0] rRdSgChnl=0, _rRdSgChnl=0; reg [3:0] rWrChnl=0, _rWrChnl=0; reg [61:0] rWrAddr=62'd0, _rWrAddr=62'd0; reg [9:0] rWrLen=0, _rWrLen=0; reg [C_PCI_DATA_WIDTH-1:0] rWrData={C_PCI_DATA_WIDTH{1'd0}}, _rWrData={C_PCI_DATA_WIDTH{1'd0}}; generate if(C_ALTERA == 1'b1) begin : altera_data assign wWrDataSwap = rWrData; end else begin : xilinx_data assign wWrDataSwap = {rWrData[39:32], rWrData[47:40], rWrData[55:48], rWrData[63:56], rWrData[07:00], rWrData[15:08], rWrData[23:16], rWrData[31:24]}; end endgenerate (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [3:0] rCapState=`S_TXENGUPR64_CAP_RD_WR, _rCapState=`S_TXENGUPR64_CAP_RD_WR; reg [C_NUM_CHNL-1:0] rRdAck=0, _rRdAck=0; reg [C_NUM_CHNL-1:0] rWrAck=0, _rWrAck=0; reg rIsWr=0, _rIsWr=0; reg [5:0] rCapChnl=0, _rCapChnl=0; reg [61:0] rCapAddr=62'd0, _rCapAddr=62'd0; reg rCapAddr64=0, _rCapAddr64=0; reg [9:0] rCapLen=0, _rCapLen=0; reg rCapIsWr=0, _rCapIsWr=0; reg rExtTagReq=0, _rExtTagReq=0; reg [C_TAG_WIDTH-1:0] rExtTag=0, _rExtTag=0; reg [C_FIFO_DEPTH_WIDTH-1:0] rFifoCount=0, _rFifoCount=0; reg [9:0] rMaxEntries=0, _rMaxEntries=0; reg rSpaceAvail=0, _rSpaceAvail=0; reg [C_DATA_DELAY-1:0] rWnR=0, _rWnR=0; reg [(C_DATA_DELAY*4)-1:0] rChnl=0, _rChnl=0; reg [(C_DATA_DELAY*8)-1:0] rTag=0, _rTag=0; reg [(C_DATA_DELAY*62)-1:0] rAddr=0, _rAddr=0; reg [C_DATA_DELAY-1:0] rAddr64=0, _rAddr64=0; reg [(C_DATA_DELAY*10)-1:0] rLen=0, _rLen=0; reg [C_DATA_DELAY-1:0] rLenEQ1=0, _rLenEQ1=0; reg [C_DATA_DELAY-1:0] rValid=0, _rValid=0; assign WR_DATA_REN = rWrDataRen; assign WR_ACK = rWrAck; assign RD_ACK = rRdAck; assign INT_TAG = {rRdSgChnl, rRdChnl}; assign INT_TAG_VALID = rExtTagReq; assign TX_ENG_RD_REQ_SENT = rTxEngRdReqAck; assign wRdAck = (wRdReq & EXT_TAG_VALID & RXBUF_SPACE_AVAIL); // Search for the next request so that we can move onto it immediately after // the current channel has released its request. tx_engine_selector #(.C_NUM_CHNL(C_NUM_CHNL)) selRd (.RST(RST), .CLK(CLK), .REQ_ALL(RD_REQ), .REQ(wRdReq), .CHNL(wRdReqChnl)); tx_engine_selector #(.C_NUM_CHNL(C_NUM_CHNL)) selWr (.RST(RST), .CLK(CLK), .REQ_ALL(WR_REQ), .REQ(wWrReq), .CHNL(wWrReqChnl)); // Buffer shift-selected channel request signals and FIFO data. always @ (posedge CLK) begin rRdChnl <= #1 _rRdChnl; rRdAddr <= #1 _rRdAddr; rRdLen <= #1 _rRdLen; rRdSgChnl <= #1 _rRdSgChnl; rWrChnl <= #1 _rWrChnl; rWrAddr <= #1 _rWrAddr; rWrLen <= #1 _rWrLen; rWrData <= #1 _rWrData; end always @ (*) begin _rRdChnl = wRdReqChnl; _rRdAddr = wRdAddr[63:2]; _rRdLen = wRdLen; _rRdSgChnl = wRdSgChnl; _rWrChnl = wWrReqChnl; _rWrAddr = wWrAddr[63:2]; _rWrLen = wWrLen; _rWrData = wWrData; end // Accept requests when the selector indicates. Capture the buffered // request parameters for hand-off to the formatting pipeline. Then // acknowledge the receipt to the channel so it can deassert the // request, and let the selector choose another channel. always @ (posedge CLK) begin rCapState <= #1 (RST ? `S_TXENGUPR64_CAP_RD_WR : _rCapState); rRdAck <= #1 (RST ? {C_NUM_CHNL{1'd0}} : _rRdAck); rWrAck <= #1 (RST ? {C_NUM_CHNL{1'd0}} : _rWrAck); rIsWr <= #1 _rIsWr; rCapChnl <= #1 _rCapChnl; rCapAddr <= #1 _rCapAddr; rCapAddr64 <= #1 _rCapAddr64; rCapLen <= #1 _rCapLen; rCapIsWr <= #1 _rCapIsWr; rExtTagReq <= #1 _rExtTagReq; rExtTag <= #1 _rExtTag; rTxEngRdReqAck <= #1 _rTxEngRdReqAck; end always @ (*) begin _rCapState = rCapState; _rRdAck = rRdAck; _rWrAck = rWrAck; _rIsWr = rIsWr; _rCapChnl = rCapChnl; _rCapAddr = rCapAddr; _rCapAddr64 = (rCapAddr[61:30] != 0); _rCapLen = rCapLen; _rCapIsWr = rCapIsWr; _rExtTagReq = rExtTagReq; _rExtTag = rExtTag; _rTxEngRdReqAck = rTxEngRdReqAck; case (rCapState) `S_TXENGUPR64_CAP_RD_WR : begin _rIsWr = !wRdReq; _rRdAck = (wRdAck<>(rCapIsWr)); // Changes to S_TXENGUPR64_CAP_RD_WR end default : begin _rCapState = `S_TXENGUPR64_CAP_RD_WR; end endcase end // Calculate the available space in the FIFO, accounting for the // formatting pipeline depth. This will be conservative. wire [9:0] wMaxEntries = (C_MAX_ENTRIES<>({rConsumedHist[8:6], 5'd0})) | (rFifoData<<({rCountHist[7:6], 5'd0}))); else _rData = (rData>>({rConsumedHist[8:6], 5'd0})); end // Buffer up to 4 length LSB values for use to detect unread data that was // part of a consumed packet. Should only need 2. This is basically a FIFO. always @ (posedge CLK) begin rRdPtr <= #1 (RST ? 2'd0 : _rRdPtr); rWrPtr <= #1 (RST ? 2'd0 : _rWrPtr); rLenLSB0 <= #1 _rLenLSB0; rLenLSB1 <= #1 _rLenLSB1; rLenLast <= #1 _rLenLast; end always @ (*) begin _rRdPtr = (wAfterEnd ? rRdPtr + 1'd1 : rRdPtr); _rWrPtr = (rLenValid ? rWrPtr + 1'd1 : rWrPtr); _rLenLSB0 = rLenLSB0; _rLenLSB1 = rLenLSB1; {_rLenLSB1[rWrPtr], _rLenLSB0[rWrPtr]} = (rLenValid ? (~LEN_LSB + 1'd1) : {rLenLSB1[rWrPtr], rLenLSB0[rWrPtr]}); _rLenLast = rLenLast; _rLenLast[rWrPtr] = (rLenValid ? LEN_LAST : rLenLast[rWrPtr]); end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_port_buffer_32.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_port_buffer_32.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Wraps a FIFO for saving channel data and provides a // registered read output. Data is available 3 cycles after RD_EN is asserted // (not 1, like a traditional FIFO). // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module tx_port_buffer_32 #( parameter C_FIFO_DATA_WIDTH = 9'd32, parameter C_FIFO_DEPTH = 512, // Local parameters parameter C_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_FIFO_DEPTH))+1) ) ( input RST, input CLK, input [C_FIFO_DATA_WIDTH-1:0] WR_DATA, // Input data input WR_EN, // Input data write enable output [C_FIFO_DEPTH_WIDTH-1:0] WR_COUNT, // Input data FIFO is full output [C_FIFO_DATA_WIDTH-1:0] RD_DATA, // Output data input RD_EN // Output data read enable ); `include "common_functions.v" reg rFifoRdEn=0, _rFifoRdEn=0; reg [C_FIFO_DATA_WIDTH-1:0] rFifoData={C_FIFO_DATA_WIDTH{1'd0}}, _rFifoData={C_FIFO_DATA_WIDTH{1'd0}}; wire [C_FIFO_DATA_WIDTH-1:0] wFifoData; assign RD_DATA = rFifoData; // Buffer the input signals that come from outside the tx_port. always @ (posedge CLK) begin rFifoRdEn <= #1 (RST ? 1'd0 : _rFifoRdEn); end always @ (*) begin _rFifoRdEn = RD_EN; end // FIFO for storing data from the channel. (* RAM_STYLE="BLOCK" *) sync_fifo #(.C_WIDTH(C_FIFO_DATA_WIDTH), .C_DEPTH(C_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) fifo ( .CLK(CLK), .RST(RST), .WR_EN(WR_EN), .WR_DATA(WR_DATA), .FULL(), .COUNT(WR_COUNT), .RD_EN(rFifoRdEn), .RD_DATA(wFifoData), .EMPTY() ); // Buffer data from the FIFO. always @ (posedge CLK) begin rFifoData <= #1 _rFifoData; end always @ (*) begin _rFifoData = wFifoData; end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_port_buffer_64.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_port_buffer_64.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Wraps a FIFO for saving channel data and provides a // registered read output. Retains unread words from reads that are a length // which is not a multiple of the data bus width (C_FIFO_DATA_WIDTH). Data is // available 5 cycles after RD_EN is asserted (not 1, like a traditional FIFO). // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- module tx_port_buffer_64 #( parameter C_FIFO_DATA_WIDTH = 9'd64, parameter C_FIFO_DEPTH = 512, // Local parameters parameter C_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_FIFO_DEPTH))+1), parameter C_RD_EN_HIST = 2, parameter C_FIFO_RD_EN_HIST = 2, parameter C_CONSUME_HIST = 3, parameter C_COUNT_HIST = 3, parameter C_LEN_LAST_HIST = 1 ) ( input RST, input CLK, input LEN_VALID, // Transfer length is valid input [0:0] LEN_LSB, // LSBs of transfer length input LEN_LAST, // Last transfer in transaction input [C_FIFO_DATA_WIDTH-1:0] WR_DATA, // Input data input WR_EN, // Input data write enable output [C_FIFO_DEPTH_WIDTH-1:0] WR_COUNT, // Input data FIFO is full output [C_FIFO_DATA_WIDTH-1:0] RD_DATA, // Output data input RD_EN // Output data read enable ); `include "common_functions.v" reg [1:0] rRdPtr=0, _rRdPtr=0; reg [1:0] rWrPtr=0, _rWrPtr=0; reg [3:0] rLenLSB=0, _rLenLSB=0; reg [3:0] rLenLast=0, _rLenLast=0; reg rLenValid=0, _rLenValid=0; reg rRen=0, _rRen=0; reg [1:0] rCount=0, _rCount=0; reg [(C_COUNT_HIST*2)-1:0] rCountHist={C_COUNT_HIST{2'd0}}, _rCountHist={C_COUNT_HIST{2'd0}}; reg [C_LEN_LAST_HIST-1:0] rLenLastHist={C_LEN_LAST_HIST{1'd0}}, _rLenLastHist={C_LEN_LAST_HIST{1'd0}}; reg [C_RD_EN_HIST-1:0] rRdEnHist={C_RD_EN_HIST{1'd0}}, _rRdEnHist={C_RD_EN_HIST{1'd0}}; reg rFifoRdEn=0, _rFifoRdEn=0; reg [C_FIFO_RD_EN_HIST-1:0] rFifoRdEnHist={C_FIFO_RD_EN_HIST{1'd0}}, _rFifoRdEnHist={C_FIFO_RD_EN_HIST{1'd0}}; reg [(C_CONSUME_HIST*2)-1:0] rConsumedHist={C_CONSUME_HIST{2'd0}}, _rConsumedHist={C_CONSUME_HIST{2'd0}}; reg [C_FIFO_DATA_WIDTH-1:0] rFifoData={C_FIFO_DATA_WIDTH{1'd0}}, _rFifoData={C_FIFO_DATA_WIDTH{1'd0}}; reg [95:0] rData=96'd0, _rData=96'd0; wire [C_FIFO_DATA_WIDTH-1:0] wFifoData; assign RD_DATA = rData[0 +:C_FIFO_DATA_WIDTH]; // Buffer the input signals that come from outside the tx_port. always @ (posedge CLK) begin rLenValid <= #1 (RST ? 1'd0 : _rLenValid); rRen <= #1 (RST ? 1'd0 : _rRen); end always @ (*) begin _rLenValid = LEN_VALID; _rRen = RD_EN; end // FIFO for storing data from the channel. (* RAM_STYLE="BLOCK" *) sync_fifo #(.C_WIDTH(C_FIFO_DATA_WIDTH), .C_DEPTH(C_FIFO_DEPTH), .C_PROVIDE_COUNT(1)) fifo ( .CLK(CLK), .RST(RST), .WR_EN(WR_EN), .WR_DATA(WR_DATA), .FULL(), .COUNT(WR_COUNT), .RD_EN(rFifoRdEn), .RD_DATA(wFifoData), .EMPTY() ); // Manage shifting of data in from the FIFO and shifting of data out once // it is consumed. We'll keep 3 words of output registers to hold an input // packet with up to 1 extra word of unread data. wire wLenOdd = rLenLSB[rRdPtr]; wire wLenLast = rLenLast[rRdPtr]; wire wAfterEnd = (!rRen & rRdEnHist[0]); wire [1:0] wConsumed = ({(rRdEnHist[0] | (!rRdEnHist[0] & rRdEnHist[1] & rLenLastHist[0])), 1'd0}) - (wAfterEnd & wLenOdd); always @ (posedge CLK) begin rCount <= #1 (RST ? 2'd0 : _rCount); rCountHist <= #1 _rCountHist; rRdEnHist <= #1 (RST ? {C_RD_EN_HIST{1'd0}} : _rRdEnHist); rFifoRdEn <= #1 (RST ? 1'd0 : _rFifoRdEn); rFifoRdEnHist <= #1 (RST ? {C_FIFO_RD_EN_HIST{1'd0}} : _rFifoRdEnHist); rConsumedHist <= #1 _rConsumedHist; rLenLastHist <= #1 (RST ? {C_LEN_LAST_HIST{1'd0}} : _rLenLastHist); rFifoData <= #1 _rFifoData; rData <= #1 _rData; end always @ (*) begin // Keep track of words in our buffer. Subtract 2 when we reach 2 on RD_EN. // Add 1 when we finish a sequence of RD_EN that read an odd number of words. _rCount = rCount + (wAfterEnd & wLenOdd & !wLenLast) - ({rRen & rCount[1], 1'd0}) - ({(wAfterEnd & wLenLast)&rCount[1], (wAfterEnd & wLenLast)&rCount[0]}); _rCountHist = ((rCountHist<<2) | rCount); // Track read enables in the pipeline. _rRdEnHist = ((rRdEnHist<<1) | rRen); _rFifoRdEnHist = ((rFifoRdEnHist<<1) | rFifoRdEn); // Track delayed length last value _rLenLastHist = ((rLenLastHist<<1) | wLenLast); // Calculate the amount to shift out each RD_EN. This is always 2 unless // it's the last RD_EN in the sequence and the read words length is odd. _rConsumedHist = ((rConsumedHist<<2) | wConsumed); // Read from the FIFO unless we have 2 words cached. _rFifoRdEn = (!rCount[1] & rRen); // Buffer the FIFO data. _rFifoData = wFifoData; // Shift the buffered FIFO data into and the consumed data out of the output register. if (rFifoRdEnHist[1]) _rData = ((rData>>({rConsumedHist[5:4], 5'd0})) | (rFifoData<<({rCountHist[4], 5'd0}))); else _rData = (rData>>({rConsumedHist[5:4], 5'd0})); end // Buffer up to 4 length LSB values for use to detect unread data that was // part of a consumed packet. Should only need 2. This is basically a FIFO. always @ (posedge CLK) begin rRdPtr <= #1 (RST ? 2'd0 : _rRdPtr); rWrPtr <= #1 (RST ? 2'd0 : _rWrPtr); rLenLSB <= #1 _rLenLSB; rLenLast <= #1 _rLenLast; end always @ (*) begin _rRdPtr = (wAfterEnd ? rRdPtr + 1'd1 : rRdPtr); _rWrPtr = (rLenValid ? rWrPtr + 1'd1 : rWrPtr); _rLenLSB = rLenLSB; _rLenLSB[rWrPtr] = (rLenValid ? (~LEN_LSB + 1'd1) : rLenLSB[rWrPtr]); _rLenLast = rLenLast; _rLenLast[rWrPtr] = (rLenValid ? LEN_LAST : rLenLast[rWrPtr]); end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_port_channel_gate_128.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_port_channel_gate_128.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Captures transaction open/close events as well as data // and passes it to the RD_CLK domain through the async_fifo. CHNL_TX_DATA_REN can // only be high after CHNL_TX goes high and after the CHNL_TX_ACK pulse. When // CHNL_TX drops, the channel closes (until the next transaction -- signaled by // CHNL_TX going up again). // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_TXPORTGATE128_IDLE 2'b00 `define S_TXPORTGATE128_OPENING 2'b01 `define S_TXPORTGATE128_OPEN 2'b10 `define S_TXPORTGATE128_CLOSED 2'b11 module tx_port_channel_gate_128 #( parameter C_DATA_WIDTH = 9'd128, // Local parameters parameter C_FIFO_DEPTH = 8, parameter C_FIFO_DATA_WIDTH = C_DATA_WIDTH+1 ) ( input RST, input RD_CLK, // FIFO read clock output [C_FIFO_DATA_WIDTH-1:0] RD_DATA, // FIFO read data output RD_EMPTY, // FIFO is empty input RD_EN, // FIFO read enable input CHNL_CLK, // Channel write clock input CHNL_TX, // Channel write receive signal output CHNL_TX_ACK, // Channel write acknowledgement signal input CHNL_TX_LAST, // Channel last write input [31:0] CHNL_TX_LEN, // Channel write length (in 32 bit words) input [30:0] CHNL_TX_OFF, // Channel write offset input [C_DATA_WIDTH-1:0] CHNL_TX_DATA, // Channel write data input CHNL_TX_DATA_VALID, // Channel write data valid output CHNL_TX_DATA_REN // Channel write data has been recieved ); (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [1:0] rState=`S_TXPORTGATE128_IDLE, _rState=`S_TXPORTGATE128_IDLE; reg rFifoWen=0, _rFifoWen=0; reg [C_FIFO_DATA_WIDTH-1:0] rFifoData=0, _rFifoData=0; wire wFifoFull; reg rChnlTx=0, _rChnlTx=0; reg rChnlLast=0, _rChnlLast=0; reg [31:0] rChnlLen=0, _rChnlLen=0; reg [30:0] rChnlOff=0, _rChnlOff=0; reg rAck=0, _rAck=0; reg rPause=0, _rPause=0; reg rClosed=0, _rClosed=0; assign CHNL_TX_ACK = rAck; assign CHNL_TX_DATA_REN = (rState[1] & !rState[0] & !wFifoFull); // S_TXPORTGATE128_OPEN // Buffer the input signals that come from outside the tx_port. always @ (posedge CHNL_CLK) begin rChnlTx <= #1 (RST ? 1'd0 : _rChnlTx); rChnlLast <= #1 _rChnlLast; rChnlLen <= #1 _rChnlLen; rChnlOff <= #1 _rChnlOff; end always @ (*) begin _rChnlTx = CHNL_TX; _rChnlLast = CHNL_TX_LAST; _rChnlLen = CHNL_TX_LEN; _rChnlOff = CHNL_TX_OFF; end // FIFO for temporarily storing data from the channel. (* RAM_STYLE="DISTRIBUTED" *) async_fifo #(.C_WIDTH(C_FIFO_DATA_WIDTH), .C_DEPTH(C_FIFO_DEPTH)) fifo ( .WR_CLK(CHNL_CLK), .WR_RST(RST), .WR_EN(rFifoWen), .WR_DATA(rFifoData), .WR_FULL(wFifoFull), .RD_CLK(RD_CLK), .RD_RST(RST), .RD_EN(RD_EN), .RD_DATA(RD_DATA), .RD_EMPTY(RD_EMPTY) ); // Pass the transaction open event, transaction data, and the transaction // close event through to the RD_CLK domain via the async_fifo. always @ (posedge CHNL_CLK) begin rState <= #1 (RST ? `S_TXPORTGATE128_IDLE : _rState); rFifoWen <= #1 (RST ? 1'd0 : _rFifoWen); rFifoData <= #1 _rFifoData; rAck <= #1 (RST ? 1'd0 : _rAck); rPause <= #1 (RST ? 1'd0 : _rPause); rClosed <= #1 (RST ? 1'd0 : _rClosed); end always @ (*) begin _rState = rState; _rFifoWen = rFifoWen; _rFifoData = rFifoData; _rPause = rPause; _rAck = rAck; _rClosed = rClosed; case (rState) `S_TXPORTGATE128_IDLE: begin // Write the len, off, last _rPause = 0; _rClosed = 0; if (!wFifoFull) begin _rAck = rChnlTx; _rFifoWen = rChnlTx; _rFifoData = {1'd1, 64'd0, rChnlLen, rChnlOff, rChnlLast}; if (rChnlTx) _rState = `S_TXPORTGATE128_OPENING; end end `S_TXPORTGATE128_OPENING: begin // Write the len, off, last (again) _rAck = 0; _rClosed = (rClosed | !rChnlTx); if (!wFifoFull) begin if (rClosed | !rChnlTx) _rState = `S_TXPORTGATE128_CLOSED; else _rState = `S_TXPORTGATE128_OPEN; end end `S_TXPORTGATE128_OPEN: begin // Copy channel data into the FIFO if (!wFifoFull) begin _rFifoWen = CHNL_TX_DATA_VALID; // CHNL_TX_DATA_VALID & CHNL_TX_DATA should really be buffered _rFifoData = {1'd0, CHNL_TX_DATA}; // but the VALID+REN model seem to make this difficult. end if (!rChnlTx) _rState = `S_TXPORTGATE128_CLOSED; end `S_TXPORTGATE128_CLOSED: begin // Write the end marker (twice) if (!wFifoFull) begin _rPause = 1; _rFifoWen = 1; _rFifoData = {1'd1, {C_DATA_WIDTH{1'd0}}}; if (rPause) _rState = `S_TXPORTGATE128_IDLE; end end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_port_channel_gate_32.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_port_channel_gate_32.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Captures transaction open/close events as well as data // and passes it to the RD_CLK domain through the async_fifo. CHNL_TX_DATA_REN can // only be high after CHNL_TX goes high and after the CHNL_TX_ACK pulse. When // CHNL_TX drops, the channel closes (until the next transaction -- signaled by // CHNL_TX going up again). // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_TXPORTGATE32_IDLE 2'b00 `define S_TXPORTGATE32_OPENING 2'b01 `define S_TXPORTGATE32_OPEN 2'b10 `define S_TXPORTGATE32_CLOSED 2'b11 module tx_port_channel_gate_32 #( parameter C_DATA_WIDTH = 9'd32, // Local parameters parameter C_FIFO_DEPTH = 8, parameter C_FIFO_DATA_WIDTH = C_DATA_WIDTH+1 ) ( input RST, input RD_CLK, // FIFO read clock output [C_FIFO_DATA_WIDTH-1:0] RD_DATA, // FIFO read data output RD_EMPTY, // FIFO is empty input RD_EN, // FIFO read enable input CHNL_CLK, // Channel write clock input CHNL_TX, // Channel write receive signal output CHNL_TX_ACK, // Channel write acknowledgement signal input CHNL_TX_LAST, // Channel last write input [31:0] CHNL_TX_LEN, // Channel write length (in 32 bit words) input [30:0] CHNL_TX_OFF, // Channel write offset input [C_DATA_WIDTH-1:0] CHNL_TX_DATA, // Channel write data input CHNL_TX_DATA_VALID, // Channel write data valid output CHNL_TX_DATA_REN // Channel write data has been recieved ); (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [1:0] rState=`S_TXPORTGATE32_IDLE, _rState=`S_TXPORTGATE32_IDLE; reg rFifoWen=0, _rFifoWen=0; reg [C_FIFO_DATA_WIDTH-1:0] rFifoData=0, _rFifoData=0; wire wFifoFull; reg rChnlTx=0, _rChnlTx=0; reg rChnlLast=0, _rChnlLast=0; reg [31:0] rChnlLen=0, _rChnlLen=0; reg [30:0] rChnlOff=0, _rChnlOff=0; reg rAck=0, _rAck=0; reg rPause=0, _rPause=0; reg rClosed=0, _rClosed=0; assign CHNL_TX_ACK = rAck; assign CHNL_TX_DATA_REN = (rState[1] & !rState[0] & !wFifoFull); // S_TXPORTGATE32_OPEN // Buffer the input signals that come from outside the tx_port. always @ (posedge CHNL_CLK) begin rChnlTx <= #1 (RST ? 1'd0 : _rChnlTx); rChnlLast <= #1 _rChnlLast; rChnlLen <= #1 _rChnlLen; rChnlOff <= #1 _rChnlOff; end always @ (*) begin _rChnlTx = CHNL_TX; _rChnlLast = CHNL_TX_LAST; _rChnlLen = CHNL_TX_LEN; _rChnlOff = CHNL_TX_OFF; end // FIFO for temporarily storing data from the channel. (* RAM_STYLE="DISTRIBUTED" *) async_fifo #(.C_WIDTH(C_FIFO_DATA_WIDTH), .C_DEPTH(C_FIFO_DEPTH)) fifo ( .WR_CLK(CHNL_CLK), .WR_RST(RST), .WR_EN(rFifoWen), .WR_DATA(rFifoData), .WR_FULL(wFifoFull), .RD_CLK(RD_CLK), .RD_RST(RST), .RD_EN(RD_EN), .RD_DATA(RD_DATA), .RD_EMPTY(RD_EMPTY) ); // Pass the transaction open event, transaction data, and the transaction // close event through to the RD_CLK domain via the async_fifo. always @ (posedge CHNL_CLK) begin rState <= #1 (RST ? `S_TXPORTGATE32_IDLE : _rState); rFifoWen <= #1 (RST ? 1'd0 : _rFifoWen); rFifoData <= #1 _rFifoData; rAck <= #1 (RST ? 1'd0 : _rAck); rPause <= #1 (RST ? 1'd0 : _rPause); rClosed <= #1 (RST ? 1'd0 : _rClosed); end always @ (*) begin _rState = rState; _rFifoWen = rFifoWen; _rFifoData = rFifoData; _rPause = rPause; _rAck = rAck; _rClosed = rClosed; case (rState) `S_TXPORTGATE32_IDLE: begin // Write the len _rPause = 0; _rClosed = 0; if (!wFifoFull) begin _rFifoWen = rChnlTx; _rFifoData = {1'd1, rChnlLen}; if (rChnlTx) _rState = `S_TXPORTGATE32_OPENING; end end `S_TXPORTGATE32_OPENING: begin // Write the off, last _rClosed = (rClosed | !rChnlTx); if (!wFifoFull) begin _rAck = rChnlTx; _rFifoData = {1'd1, rChnlOff, rChnlLast}; if (rClosed | !rChnlTx) _rState = `S_TXPORTGATE32_CLOSED; else _rState = `S_TXPORTGATE32_OPEN; end end `S_TXPORTGATE32_OPEN: begin // Copy channel data into the FIFO _rAck = 0; if (!wFifoFull) begin _rFifoWen = CHNL_TX_DATA_VALID; // CHNL_TX_DATA_VALID & CHNL_TX_DATA should really be buffered _rFifoData = {1'd0, CHNL_TX_DATA}; // but the VALID+REN model seem to make this difficult. end if (!rChnlTx) _rState = `S_TXPORTGATE32_CLOSED; end `S_TXPORTGATE32_CLOSED: begin // Write the end marker (twice) _rAck = 0; if (!wFifoFull) begin _rPause = 1; _rFifoWen = 1; _rFifoData = {1'd1, {C_DATA_WIDTH{1'd0}}}; if (rPause) _rState = `S_TXPORTGATE32_IDLE; end end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_port_channel_gate_64.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_port_channel_gate_64.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Captures transaction open/close events as well as data // and passes it to the RD_CLK domain through the async_fifo. CHNL_TX_DATA_REN can // only be high after CHNL_TX goes high and after the CHNL_TX_ACK pulse. When // CHNL_TX drops, the channel closes (until the next transaction -- signaled by // CHNL_TX going up again). // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_TXPORTGATE64_IDLE 2'b00 `define S_TXPORTGATE64_OPENING 2'b01 `define S_TXPORTGATE64_OPEN 2'b10 `define S_TXPORTGATE64_CLOSED 2'b11 module tx_port_channel_gate_64 #( parameter C_DATA_WIDTH = 9'd64, // Local parameters parameter C_FIFO_DEPTH = 8, parameter C_FIFO_DATA_WIDTH = C_DATA_WIDTH+1 ) ( input RST, input RD_CLK, // FIFO read clock output [C_FIFO_DATA_WIDTH-1:0] RD_DATA, // FIFO read data output RD_EMPTY, // FIFO is empty input RD_EN, // FIFO read enable input CHNL_CLK, // Channel write clock input CHNL_TX, // Channel write receive signal output CHNL_TX_ACK, // Channel write acknowledgement signal input CHNL_TX_LAST, // Channel last write input [31:0] CHNL_TX_LEN, // Channel write length (in 32 bit words) input [30:0] CHNL_TX_OFF, // Channel write offset input [C_DATA_WIDTH-1:0] CHNL_TX_DATA, // Channel write data input CHNL_TX_DATA_VALID, // Channel write data valid output CHNL_TX_DATA_REN // Channel write data has been recieved ); (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [1:0] rState=`S_TXPORTGATE64_IDLE, _rState=`S_TXPORTGATE64_IDLE; reg rFifoWen=0, _rFifoWen=0; reg [C_FIFO_DATA_WIDTH-1:0] rFifoData=0, _rFifoData=0; wire wFifoFull; reg rChnlTx=0, _rChnlTx=0; reg rChnlLast=0, _rChnlLast=0; reg [31:0] rChnlLen=0, _rChnlLen=0; reg [30:0] rChnlOff=0, _rChnlOff=0; reg rAck=0, _rAck=0; reg rPause=0, _rPause=0; reg rClosed=0, _rClosed=0; assign CHNL_TX_ACK = rAck; assign CHNL_TX_DATA_REN = (rState[1] & !rState[0] & !wFifoFull); // S_TXPORTGATE64_OPEN // Buffer the input signals that come from outside the tx_port. always @ (posedge CHNL_CLK) begin rChnlTx <= #1 (RST ? 1'd0 : _rChnlTx); rChnlLast <= #1 _rChnlLast; rChnlLen <= #1 _rChnlLen; rChnlOff <= #1 _rChnlOff; end always @ (*) begin _rChnlTx = CHNL_TX; _rChnlLast = CHNL_TX_LAST; _rChnlLen = CHNL_TX_LEN; _rChnlOff = CHNL_TX_OFF; end // FIFO for temporarily storing data from the channel. (* RAM_STYLE="DISTRIBUTED" *) async_fifo #(.C_WIDTH(C_FIFO_DATA_WIDTH), .C_DEPTH(C_FIFO_DEPTH)) fifo ( .WR_CLK(CHNL_CLK), .WR_RST(RST), .WR_EN(rFifoWen), .WR_DATA(rFifoData), .WR_FULL(wFifoFull), .RD_CLK(RD_CLK), .RD_RST(RST), .RD_EN(RD_EN), .RD_DATA(RD_DATA), .RD_EMPTY(RD_EMPTY) ); // Pass the transaction open event, transaction data, and the transaction // close event through to the RD_CLK domain via the async_fifo. always @ (posedge CHNL_CLK) begin rState <= #1 (RST ? `S_TXPORTGATE64_IDLE : _rState); rFifoWen <= #1 (RST ? 1'd0 : _rFifoWen); rFifoData <= #1 _rFifoData; rAck <= #1 (RST ? 1'd0 : _rAck); rPause <= #1 (RST ? 1'd0 : _rPause); rClosed <= #1 (RST ? 1'd0 : _rClosed); end always @ (*) begin _rState = rState; _rFifoWen = rFifoWen; _rFifoData = rFifoData; _rPause = rPause; _rAck = rAck; _rClosed = rClosed; case (rState) `S_TXPORTGATE64_IDLE: begin // Write the len, off, last _rPause = 0; _rClosed = 0; if (!wFifoFull) begin _rAck = rChnlTx; _rFifoWen = rChnlTx; _rFifoData = {1'd1, rChnlLen, rChnlOff, rChnlLast}; if (rChnlTx) _rState = `S_TXPORTGATE64_OPENING; end end `S_TXPORTGATE64_OPENING: begin // Write the len, off, last (again) _rAck = 0; _rClosed = (rClosed | !rChnlTx); if (!wFifoFull) begin if (rClosed | !rChnlTx) _rState = `S_TXPORTGATE64_CLOSED; else _rState = `S_TXPORTGATE64_OPEN; end end `S_TXPORTGATE64_OPEN: begin // Copy channel data into the FIFO if (!wFifoFull) begin _rFifoWen = CHNL_TX_DATA_VALID; // CHNL_TX_DATA_VALID & CHNL_TX_DATA should really be buffered _rFifoData = {1'd0, CHNL_TX_DATA}; // but the VALID+REN model seem to make this difficult. end if (!rChnlTx) _rState = `S_TXPORTGATE64_CLOSED; end `S_TXPORTGATE64_CLOSED: begin // Write the end marker (twice) if (!wFifoFull) begin _rPause = 1; _rFifoWen = 1; _rFifoData = {1'd1, {C_DATA_WIDTH{1'd0}}}; if (rPause) _rState = `S_TXPORTGATE64_IDLE; end end endcase end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_port_monitor_128.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_port_monitor_128.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Detects transaction open/close events from the stream // of data from the tx_port_channel_gate. Filters out events and passes data // onto the tx_port_buffer. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_TXPORTMON128_NEXT 5'b0_0001 `define S_TXPORTMON128_TXN 5'b0_0010 `define S_TXPORTMON128_READ 5'b0_0100 `define S_TXPORTMON128_END_0 5'b0_1000 `define S_TXPORTMON128_END_1 5'b1_0000 module tx_port_monitor_128 #( parameter C_DATA_WIDTH = 9'd128, parameter C_FIFO_DEPTH = 512, // Local parameters parameter C_FIFO_DEPTH_THRESH = (C_FIFO_DEPTH - 4), parameter C_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_FIFO_DEPTH))+1), parameter C_VALID_HIST = 1 ) ( input RST, input CLK, input [C_DATA_WIDTH:0] EVT_DATA, // Event data from tx_port_channel_gate input EVT_DATA_EMPTY, // Event data FIFO is empty output EVT_DATA_RD_EN, // Event data FIFO read enable output [C_DATA_WIDTH-1:0] WR_DATA, // Output data output WR_EN, // Write enable for output data input [C_FIFO_DEPTH_WIDTH-1:0] WR_COUNT, // Output FIFO count output TXN, // Transaction parameters are valid input ACK, // Transaction parameter read, continue output LAST, // Channel last write output [31:0] LEN, // Channel write length (in 32 bit words) output [30:0] OFF, // Channel write offset output [31:0] WORDS_RECVD, // Count of data words received in transaction output DONE, // Transaction is closed input TX_ERR // Transaction encountered an error ); `include "common_functions.v" (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [4:0] rState=`S_TXPORTMON128_NEXT, _rState=`S_TXPORTMON128_NEXT; reg rRead=0, _rRead=0; reg [C_VALID_HIST-1:0] rDataValid={C_VALID_HIST{1'd0}}, _rDataValid={C_VALID_HIST{1'd0}}; reg rEvent=0, _rEvent=0; reg [63:0] rReadData=64'd0, _rReadData=64'd0; reg [31:0] rWordsRecvd=0, _rWordsRecvd=0; reg [31:0] rWordsRecvdAdv=0, _rWordsRecvdAdv=0; reg rAlmostAllRecvd=0, _rAlmostAllRecvd=0; reg rAlmostFull=0, _rAlmostFull=0; reg rLenEQ0Hi=0, _rLenEQ0Hi=0; reg rLenEQ0Lo=0, _rLenEQ0Lo=0; reg rLenLE4Lo=0, _rLenLE4Lo=0; reg rTxErr=0, _rTxErr=0; assign EVT_DATA_RD_EN = rRead; assign WR_DATA = EVT_DATA[C_DATA_WIDTH-1:0]; assign WR_EN = wPayloadData; // S_TXPORTMON128_READ assign TXN = rState[1]; // S_TXPORTMON128_TXN assign LAST = rReadData[0]; assign OFF = rReadData[31:1]; assign LEN = rReadData[63:32]; assign WORDS_RECVD = rWordsRecvd; assign DONE = !rState[2]; // !S_TXPORTMON128_READ wire wEventData = (rDataValid[0] & EVT_DATA[C_DATA_WIDTH]); wire wPayloadData = (rDataValid[0] & !EVT_DATA[C_DATA_WIDTH] & rState[2]); // S_TXPORTMON128_READ wire wAllWordsRecvd = ((rAlmostAllRecvd | (rLenEQ0Hi & rLenLE4Lo)) & wPayloadData); // Buffer the input signals that come from outside the tx_port. always @ (posedge CLK) begin rTxErr <= #1 (RST ? 1'd0 : _rTxErr); end always @ (*) begin _rTxErr = TX_ERR; end // Transaction monitoring FSM. always @ (posedge CLK) begin rState <= #1 (RST ? `S_TXPORTMON128_NEXT : _rState); end always @ (*) begin _rState = rState; case (rState) `S_TXPORTMON128_NEXT: begin // Read, wait for start of transaction event if (rEvent) _rState = `S_TXPORTMON128_TXN; end `S_TXPORTMON128_TXN: begin // Don't read, wait until transaction has been acknowledged if (ACK) _rState = ((rLenEQ0Hi && rLenEQ0Lo) ? `S_TXPORTMON128_END_0 : `S_TXPORTMON128_READ); end `S_TXPORTMON128_READ: begin // Continue reading, wait for end of transaction event or all expected data if (rEvent) _rState = `S_TXPORTMON128_END_1; else if (wAllWordsRecvd | rTxErr) _rState = `S_TXPORTMON128_END_0; end `S_TXPORTMON128_END_0: begin // Continue reading, wait for first end of transaction event if (rEvent) _rState = `S_TXPORTMON128_END_1; end `S_TXPORTMON128_END_1: begin // Continue reading, wait for second end of transaction event if (rEvent) _rState = `S_TXPORTMON128_NEXT; end default: begin _rState = `S_TXPORTMON128_NEXT; end endcase end // Manage reading from the FIFO and tracking amounts read. always @ (posedge CLK) begin rRead <= #1 (RST ? 1'd0 : _rRead); rDataValid <= #1 (RST ? {C_VALID_HIST{1'd0}} : _rDataValid); rEvent <= #1 (RST ? 1'd0 : _rEvent); rReadData <= #1 _rReadData; rWordsRecvd <= #1 _rWordsRecvd; rWordsRecvdAdv <= #1 _rWordsRecvdAdv; rAlmostAllRecvd <= #1 _rAlmostAllRecvd; rAlmostFull <= #1 _rAlmostFull; rLenEQ0Hi <= #1 _rLenEQ0Hi; rLenEQ0Lo <= #1 _rLenEQ0Lo; rLenLE4Lo <= #1 _rLenLE4Lo; end always @ (*) begin // Don't get to the full point in the output FIFO _rAlmostFull = (WR_COUNT >= C_FIFO_DEPTH_THRESH); // Track read history so we know when data is valid _rDataValid = ((rDataValid<<1) | (rRead & !EVT_DATA_EMPTY)); // Read until we get a (valid) event _rRead = (!rState[1] & !wEventData & !rAlmostFull); // !S_TXPORTMON128_TXN // Track detected events _rEvent = wEventData; // Save event data when valid if (wEventData) _rReadData = EVT_DATA[63:0]; else _rReadData = rReadData; // If LEN == 0, we don't want to send any data to the output _rLenEQ0Hi = (LEN[31:16] == 16'd0); _rLenEQ0Lo = (LEN[15:0] == 16'd0); // If LEN <= 4, we want to trigger the almost all received flag _rLenLE4Lo = (LEN[15:0] <= 16'd4); // Count received non-event data _rWordsRecvd = (ACK ? 0 : rWordsRecvd + (wPayloadData<<2)); _rWordsRecvdAdv = (ACK ? 2*(C_DATA_WIDTH/32) : rWordsRecvdAdv + (wPayloadData<<2)); _rAlmostAllRecvd = ((rWordsRecvdAdv >= LEN) && wPayloadData); end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_port_monitor_32.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_port_monitor_32.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Detects transaction open/close events from the stream // of data from the tx_port_channel_gate. Filters out events and passes data // onto the tx_port_buffer. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_TXPORTMON32_NEXT 5'b0_0001 `define S_TXPORTMON32_TXN 5'b0_0010 `define S_TXPORTMON32_READ 5'b0_0100 `define S_TXPORTMON32_END_0 5'b0_1000 `define S_TXPORTMON32_END_1 5'b1_0000 module tx_port_monitor_32 #( parameter C_DATA_WIDTH = 9'd32, parameter C_FIFO_DEPTH = 512, // Local parameters parameter C_FIFO_DEPTH_THRESH = (C_FIFO_DEPTH - 4), parameter C_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_FIFO_DEPTH))+1), parameter C_VALID_HIST = 1 ) ( input RST, input CLK, input [C_DATA_WIDTH:0] EVT_DATA, // Event data from tx_port_channel_gate input EVT_DATA_EMPTY, // Event data FIFO is empty output EVT_DATA_RD_EN, // Event data FIFO read enable output [C_DATA_WIDTH-1:0] WR_DATA, // Output data output WR_EN, // Write enable for output data input [C_FIFO_DEPTH_WIDTH-1:0] WR_COUNT, // Output FIFO count output TXN, // Transaction parameters are valid input ACK, // Transaction parameter read, continue output LAST, // Channel last write output [31:0] LEN, // Channel write length (in 32 bit words) output [30:0] OFF, // Channel write offset output [31:0] WORDS_RECVD, // Count of data words received in transaction output DONE, // Transaction is closed input TX_ERR // Transaction encountered an error ); `include "common_functions.v" (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [4:0] rState=`S_TXPORTMON32_NEXT, _rState=`S_TXPORTMON32_NEXT; reg rRead=0, _rRead=0; reg [C_VALID_HIST-1:0] rDataValid={C_VALID_HIST{1'd0}}, _rDataValid={C_VALID_HIST{1'd0}}; reg rEvent=0, _rEvent=0; reg [31:0] rReadOffLast=0, _rReadOffLast=0; reg [31:0] rReadLen=0, _rReadLen=0; reg rReadCount=0, _rReadCount=0; reg [31:0] rWordsRecvd=0, _rWordsRecvd=0; reg [31:0] rWordsRecvdAdv=0, _rWordsRecvdAdv=0; reg rAlmostAllRecvd=0, _rAlmostAllRecvd=0; reg rAlmostFull=0, _rAlmostFull=0; reg rLenEQ0Hi=0, _rLenEQ0Hi=0; reg rLenEQ0Lo=0, _rLenEQ0Lo=0; reg rLenLE1Lo=0, _rLenLE1Lo=0; reg rTxErr=0, _rTxErr=0; assign EVT_DATA_RD_EN = rRead; assign WR_DATA = EVT_DATA[C_DATA_WIDTH-1:0]; assign WR_EN = wPayloadData; assign TXN = rState[1]; // S_TXPORTMON32_TXN assign LAST = rReadOffLast[0]; assign OFF = rReadOffLast[31:1]; assign LEN = rReadLen; assign WORDS_RECVD = rWordsRecvd; assign DONE = !rState[2]; // !S_TXPORTMON32_READ wire wEventData = (rDataValid[0] & EVT_DATA[C_DATA_WIDTH]); wire wPayloadData = (rDataValid[0] & !EVT_DATA[C_DATA_WIDTH] & rState[2]); // S_TXPORTMON32_READ wire wAllWordsRecvd = ((rAlmostAllRecvd | (rLenEQ0Hi & rLenLE1Lo)) & wPayloadData); // Buffer the input signals that come from outside the tx_port. always @ (posedge CLK) begin rTxErr <= #1 (RST ? 1'd0 : _rTxErr); end always @ (*) begin _rTxErr = TX_ERR; end // Transaction monitoring FSM. always @ (posedge CLK) begin rState <= #1 (RST ? `S_TXPORTMON32_NEXT : _rState); end always @ (*) begin _rState = rState; case (rState) `S_TXPORTMON32_NEXT: begin // Read, wait for start of transaction event if (rEvent) _rState = `S_TXPORTMON32_TXN; end `S_TXPORTMON32_TXN: begin // Don't read, wait until transaction has been acknowledged if (ACK) _rState = ((rLenEQ0Hi && rLenEQ0Lo) ? `S_TXPORTMON32_END_0 : `S_TXPORTMON32_READ); end `S_TXPORTMON32_READ: begin // Continue reading, wait for end of transaction event or all expected data if (rEvent) _rState = `S_TXPORTMON32_END_1; else if (wAllWordsRecvd | rTxErr) _rState = `S_TXPORTMON32_END_0; end `S_TXPORTMON32_END_0: begin // Continue reading, wait for first end of transaction event if (rEvent) _rState = `S_TXPORTMON32_END_1; end `S_TXPORTMON32_END_1: begin // Continue reading, wait for second end of transaction event if (rEvent) _rState = `S_TXPORTMON32_NEXT; end default: begin _rState = `S_TXPORTMON32_NEXT; end endcase end // Manage reading from the FIFO and tracking amounts read. always @ (posedge CLK) begin rRead <= #1 (RST ? 1'd0 : _rRead); rDataValid <= #1 (RST ? {C_VALID_HIST{1'd0}} : _rDataValid); rEvent <= #1 (RST ? 1'd0 : _rEvent); rReadOffLast <= #1 _rReadOffLast; rReadLen <= #1 _rReadLen; rReadCount <= #1 (RST ? 1'd0 : _rReadCount); rWordsRecvd <= #1 _rWordsRecvd; rWordsRecvdAdv <= #1 _rWordsRecvdAdv; rAlmostAllRecvd <= #1 _rAlmostAllRecvd; rAlmostFull <= #1 _rAlmostFull; rLenEQ0Hi <= #1 _rLenEQ0Hi; rLenEQ0Lo <= #1 _rLenEQ0Lo; rLenLE1Lo <= #1 _rLenLE1Lo; end always @ (*) begin // Don't get to the full point in the output FIFO _rAlmostFull = (WR_COUNT >= C_FIFO_DEPTH_THRESH); // Track read history so we know when data is valid _rDataValid = ((rDataValid<<1) | (rRead & !EVT_DATA_EMPTY)); // Read until we get a (valid) event _rRead = (!rState[1] & !wEventData & !rAlmostFull); // !S_TXPORTMON32_TXN // Track detected events _rEvent = wEventData; // Save event data when valid if (wEventData) begin _rReadOffLast = (rReadCount ? EVT_DATA[C_DATA_WIDTH-1:0] : rReadOffLast); _rReadLen = (!rReadCount ? EVT_DATA[C_DATA_WIDTH-1:0] : rReadLen); _rReadCount = rReadCount + 1'd1; end else begin _rReadOffLast = rReadOffLast; _rReadLen = rReadLen; _rReadCount = rReadCount; end // If LEN == 0, we don't want to send any data to the output _rLenEQ0Hi = (LEN[31:16] == 16'd0); _rLenEQ0Lo = (LEN[15:0] == 16'd0); // If LEN <= 1, we want to trigger the almost all received flag _rLenLE1Lo = (LEN[15:0] <= 16'd1); // Count received non-event data _rWordsRecvd = (ACK ? 0 : rWordsRecvd + wPayloadData); _rWordsRecvdAdv = (ACK ? 2*(C_DATA_WIDTH/32) : rWordsRecvdAdv + wPayloadData); _rAlmostAllRecvd = ((rWordsRecvdAdv >= LEN) && wPayloadData); end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_port_monitor_64.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_port_monitor_64.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Detects transaction open/close events from the stream // of data from the tx_port_channel_gate. Filters out events and passes data // onto the tx_port_buffer. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_TXPORTMON64_NEXT 5'b0_0001 `define S_TXPORTMON64_TXN 5'b0_0010 `define S_TXPORTMON64_READ 5'b0_0100 `define S_TXPORTMON64_END_0 5'b0_1000 `define S_TXPORTMON64_END_1 5'b1_0000 module tx_port_monitor_64 #( parameter C_DATA_WIDTH = 9'd64, parameter C_FIFO_DEPTH = 512, // Local parameters parameter C_FIFO_DEPTH_THRESH = (C_FIFO_DEPTH - 4), parameter C_FIFO_DEPTH_WIDTH = clog2((2**clog2(C_FIFO_DEPTH))+1), parameter C_VALID_HIST = 1 ) ( input RST, input CLK, input [C_DATA_WIDTH:0] EVT_DATA, // Event data from tx_port_channel_gate input EVT_DATA_EMPTY, // Event data FIFO is empty output EVT_DATA_RD_EN, // Event data FIFO read enable output [C_DATA_WIDTH-1:0] WR_DATA, // Output data output WR_EN, // Write enable for output data input [C_FIFO_DEPTH_WIDTH-1:0] WR_COUNT, // Output FIFO count output TXN, // Transaction parameters are valid input ACK, // Transaction parameter read, continue output LAST, // Channel last write output [31:0] LEN, // Channel write length (in 32 bit words) output [30:0] OFF, // Channel write offset output [31:0] WORDS_RECVD, // Count of data words received in transaction output DONE, // Transaction is closed input TX_ERR // Transaction encountered an error ); `include "common_functions.v" (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [4:0] rState=`S_TXPORTMON64_NEXT, _rState=`S_TXPORTMON64_NEXT; reg rRead=0, _rRead=0; reg [C_VALID_HIST-1:0] rDataValid={C_VALID_HIST{1'd0}}, _rDataValid={C_VALID_HIST{1'd0}}; reg rEvent=0, _rEvent=0; reg [63:0] rReadData=64'd0, _rReadData=64'd0; reg [31:0] rWordsRecvd=0, _rWordsRecvd=0; reg [31:0] rWordsRecvdAdv=0, _rWordsRecvdAdv=0; reg rAlmostAllRecvd=0, _rAlmostAllRecvd=0; reg rAlmostFull=0, _rAlmostFull=0; reg rLenEQ0Hi=0, _rLenEQ0Hi=0; reg rLenEQ0Lo=0, _rLenEQ0Lo=0; reg rLenLE2Lo=0, _rLenLE2Lo=0; reg rTxErr=0, _rTxErr=0; assign EVT_DATA_RD_EN = rRead; assign WR_DATA = EVT_DATA[C_DATA_WIDTH-1:0]; assign WR_EN = wPayloadData; // S_TXPORTMON64_READ assign TXN = rState[1]; // S_TXPORTMON64_TXN assign LAST = rReadData[0]; assign OFF = rReadData[31:1]; assign LEN = rReadData[63:32]; assign WORDS_RECVD = rWordsRecvd; assign DONE = !rState[2]; // !S_TXPORTMON64_READ wire wEventData = (rDataValid[0] & EVT_DATA[C_DATA_WIDTH]); wire wPayloadData = (rDataValid[0] & !EVT_DATA[C_DATA_WIDTH] & rState[2]); // S_TXPORTMON64_READ wire wAllWordsRecvd = ((rAlmostAllRecvd | (rLenEQ0Hi & rLenLE2Lo)) & wPayloadData); // Buffer the input signals that come from outside the tx_port. always @ (posedge CLK) begin rTxErr <= #1 (RST ? 1'd0 : _rTxErr); end always @ (*) begin _rTxErr = TX_ERR; end // Transaction monitoring FSM. always @ (posedge CLK) begin rState <= #1 (RST ? `S_TXPORTMON64_NEXT : _rState); end always @ (*) begin _rState = rState; case (rState) `S_TXPORTMON64_NEXT: begin // Read, wait for start of transaction event if (rEvent) _rState = `S_TXPORTMON64_TXN; end `S_TXPORTMON64_TXN: begin // Don't read, wait until transaction has been acknowledged if (ACK) _rState = ((rLenEQ0Hi && rLenEQ0Lo) ? `S_TXPORTMON64_END_0 : `S_TXPORTMON64_READ); end `S_TXPORTMON64_READ: begin // Continue reading, wait for end of transaction event or all expected data if (rEvent) _rState = `S_TXPORTMON64_END_1; else if (wAllWordsRecvd | rTxErr) _rState = `S_TXPORTMON64_END_0; end `S_TXPORTMON64_END_0: begin // Continue reading, wait for first end of transaction event if (rEvent) _rState = `S_TXPORTMON64_END_1; end `S_TXPORTMON64_END_1: begin // Continue reading, wait for second end of transaction event if (rEvent) _rState = `S_TXPORTMON64_NEXT; end default: begin _rState = `S_TXPORTMON64_NEXT; end endcase end // Manage reading from the FIFO and tracking amounts read. always @ (posedge CLK) begin rRead <= #1 (RST ? 1'd0 : _rRead); rDataValid <= #1 (RST ? {C_VALID_HIST{1'd0}} : _rDataValid); rEvent <= #1 (RST ? 1'd0 : _rEvent); rReadData <= #1 _rReadData; rWordsRecvd <= #1 _rWordsRecvd; rWordsRecvdAdv <= #1 _rWordsRecvdAdv; rAlmostAllRecvd <= #1 _rAlmostAllRecvd; rAlmostFull <= #1 _rAlmostFull; rLenEQ0Hi <= #1 _rLenEQ0Hi; rLenEQ0Lo <= #1 _rLenEQ0Lo; rLenLE2Lo <= #1 _rLenLE2Lo; end always @ (*) begin // Don't get to the full point in the output FIFO _rAlmostFull = (WR_COUNT >= C_FIFO_DEPTH_THRESH); // Track read history so we know when data is valid _rDataValid = ((rDataValid<<1) | (rRead & !EVT_DATA_EMPTY)); // Read until we get a (valid) event _rRead = (!rState[1] & !wEventData & !rAlmostFull); // !S_TXPORTMON64_TXN // Track detected events _rEvent = wEventData; // Save event data when valid if (wEventData) _rReadData = EVT_DATA[C_DATA_WIDTH-1:0]; else _rReadData = rReadData; // If LEN == 0, we don't want to send any data to the output _rLenEQ0Hi = (LEN[31:16] == 16'd0); _rLenEQ0Lo = (LEN[15:0] == 16'd0); // If LEN <= 2, we want to trigger the almost all received flag _rLenLE2Lo = (LEN[15:0] <= 16'd2); // Count received non-event data _rWordsRecvd = (ACK ? 0 : rWordsRecvd + (wPayloadData<<1)); _rWordsRecvdAdv = (ACK ? 2*(C_DATA_WIDTH/32) : rWordsRecvdAdv + (wPayloadData<<1)); _rAlmostAllRecvd = ((rWordsRecvdAdv >= LEN) && wPayloadData); end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_port_writer.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Filename: tx_port_writer.v // Version: 1.00.a // Verilog Standard: Verilog-2001 // Description: Handles receiving new transaction events and data, and // making requests to tx engine. // for the RIFFA channel. // Author: Matt Jacobsen // History: @mattj: Version 2.0 //----------------------------------------------------------------------------- `define S_TXPORTWR_MAIN_IDLE 8'b0000_0001 `define S_TXPORTWR_MAIN_CHECK 8'b0000_0010 `define S_TXPORTWR_MAIN_SIG_NEW 8'b0000_0100 `define S_TXPORTWR_MAIN_NEW_ACK 8'b0000_1000 `define S_TXPORTWR_MAIN_WRITE 8'b0001_0000 `define S_TXPORTWR_MAIN_DONE 8'b0010_0000 `define S_TXPORTWR_MAIN_SIG_DONE 8'b0100_0000 `define S_TXPORTWR_MAIN_RESET 8'b1000_0000 `define S_TXPORTWR_TX_IDLE 8'b0000_0001 `define S_TXPORTWR_TX_BUF 8'b0000_0010 `define S_TXPORTWR_TX_ADJ_0 8'b0000_0100 `define S_TXPORTWR_TX_ADJ_1 8'b0000_1000 `define S_TXPORTWR_TX_ADJ_2 8'b0001_0000 `define S_TXPORTWR_TX_CHECK_DATA 8'b0010_0000 `define S_TXPORTWR_TX_WRITE 8'b0100_0000 `define S_TXPORTWR_TX_WRITE_REM 8'b1000_0000 module tx_port_writer ( input CLK, input RST, input [2:0] CONFIG_MAX_PAYLOAD_SIZE, // Maximum write payload: 000=128B, 001=256B, 010=512B, 011=1024B output TXN, // Write transaction notification input TXN_ACK, // Write transaction acknowledged output [31:0] TXN_LEN, // Write transaction length output [31:0] TXN_OFF_LAST, // Write transaction offset/last output [31:0] TXN_DONE_LEN, // Write transaction actual transfer length output TXN_DONE, // Write transaction done output TXN_ERR, // Write transaction encountered an error input TXN_DONE_ACK, // Write transaction actual transfer length read input NEW_TXN, // Transaction parameters are valid output NEW_TXN_ACK, // Transaction parameter read, continue input NEW_TXN_LAST, // Channel last write input [31:0] NEW_TXN_LEN, // Channel write length (in 32 bit words) input [30:0] NEW_TXN_OFF, // Channel write offset input [31:0] NEW_TXN_WORDS_RECVD, // Count of data words received in transaction input NEW_TXN_DONE, // Transaction is closed input [63:0] SG_ELEM_ADDR, // Scatter gather element address input [31:0] SG_ELEM_LEN, // Scatter gather element length (in words) input SG_ELEM_RDY, // Scatter gather element ready input SG_ELEM_EMPTY, // Scatter gather elements empty output SG_ELEM_REN, // Scatter gather element read enable output SG_RST, // Scatter gather data reset input SG_ERR, // Scatter gather read encountered an error output TX_REQ, // Outgoing write request input TX_REQ_ACK, // Outgoing write request acknowledged output [63:0] TX_ADDR, // Outgoing write high address output [9:0] TX_LEN, // Outgoing write length (in 32 bit words) output TX_LAST, // Outgoing write is last request for transaction input TX_SENT // Outgoing write complete ); `include "common_functions.v" (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [7:0] rMainState=`S_TXPORTWR_MAIN_IDLE, _rMainState=`S_TXPORTWR_MAIN_IDLE; reg [31:0] rOffLast=0, _rOffLast=0; reg rWordsEQ0=0, _rWordsEQ0=0; reg rStarted=0, _rStarted=0; reg [31:0] rDoneLen=0, _rDoneLen=0; reg rSgErr=0, _rSgErr=0; reg rTxErrd=0, _rTxErrd=0; reg rTxnAck=0, _rTxnAck=0; (* syn_encoding = "user" *) (* fsm_encoding = "user" *) reg [7:0] rTxState=`S_TXPORTWR_TX_IDLE, _rTxState=`S_TXPORTWR_TX_IDLE; reg [31:0] rSentWords=0, _rSentWords=0; reg [31:0] rWords=0, _rWords=0; reg [31:0] rBufWords=0, _rBufWords=0; reg [31:0] rBufWordsInit=0, _rBufWordsInit=0; reg rLargeBuf=0, _rLargeBuf=0; reg [63:0] rAddr=64'd0, _rAddr=64'd0; reg [2:0] rCarry=0, _rCarry=0; reg rValsPropagated=0, _rValsPropagated=0; reg [5:0] rValsProp=0, _rValsProp=0; reg rCopyBufWords=0, _rCopyBufWords=0; reg rUseInit=0, _rUseInit=0; reg [10:0] rPageRem=0, _rPageRem=0; reg rPageSpill=0, _rPageSpill=0; reg rPageSpillInit=0, _rPageSpillInit=0; reg [10:0] rPreLen=0, _rPreLen=0; reg [2:0] rMaxPayloadSize=0, _rMaxPayloadSize=0; reg [2:0] rMaxPayloadShift=0, _rMaxPayloadShift=0; reg [9:0] rMaxPayload=0, _rMaxPayload=0; reg rPayloadSpill=0, _rPayloadSpill=0; reg rMaxLen=1, _rMaxLen=1; reg [9:0] rLen=0, _rLen=0; reg [31:0] rSendingWords=0, _rSendingWords=0; reg rAvail=0, _rAvail=0; reg [1:0] rTxnDone=0, _rTxnDone=0; reg [9:0] rLastLen=0, _rLastLen=0; reg rLastLenEQ0=0, _rLastLenEQ0=0; reg rLenEQWords=0, _rLenEQWords=0; reg rLenEQBufWords=0, _rLenEQBufWords=0; reg rNotRequesting=1, _rNotRequesting=1; reg [63:0] rReqAddr=64'd0, _rReqAddr=64'd0; reg [9:0] rReqLen=0, _rReqLen=0; reg rReqLast=0, _rReqLast=0; reg rTxReqAck=0, _rTxReqAck=0; reg rDone=0, _rDone=0; reg [9:0] rAckCount=0, _rAckCount=0; reg rTxSent=0, _rTxSent=0; reg rLastDoneRead=1, _rLastDoneRead=1; reg rTxnDoneAck=0, _rTxnDoneAck=0; reg rReqPartialDone=0, _rReqPartialDone=0; reg rPartialDone=0, _rPartialDone=0; assign NEW_TXN_ACK = rMainState[1]; // S_TXPORTWR_MAIN_CHECK assign TXN = rMainState[2]; // S_TXPORTWR_MAIN_SIG_NEW assign TXN_DONE = (rMainState[6] | rPartialDone); // S_TXPORTWR_MAIN_SIG_DONE assign TXN_LEN = rWords; assign TXN_OFF_LAST = rOffLast; assign TXN_DONE_LEN = rDoneLen; assign TXN_ERR = rTxErrd; assign SG_ELEM_REN = rTxState[2]; // S_TXPORTWR_TX_ADJ_0 assign SG_RST = rMainState[3]; // S_TXPORTWR_MAIN_NEW_ACK assign TX_REQ = !rNotRequesting; assign TX_ADDR = rReqAddr; assign TX_LEN = rReqLen; assign TX_LAST = rReqLast; // Buffer the input signals that come from outside the tx_port. always @ (posedge CLK) begin rTxnAck <= #1 (RST ? 1'd0 : _rTxnAck); rTxnDoneAck <= #1 (RST ? 1'd0 : _rTxnDoneAck); rSgErr <= #1 (RST ? 1'd0 : _rSgErr); rTxReqAck <= #1 (RST ? 1'd0 : _rTxReqAck); rTxSent <= #1 (RST ? 1'd0 : _rTxSent); end always @ (*) begin _rTxnAck = TXN_ACK; _rTxnDoneAck = TXN_DONE_ACK; _rSgErr = SG_ERR; _rTxReqAck = TX_REQ_ACK; _rTxSent = TX_SENT; end // Wait for a NEW_TXN request. Then request transfers until all the data is sent // or until the specified length is reached. Then signal TXN_DONE. always @ (posedge CLK) begin rMainState <= #1 (RST ? `S_TXPORTWR_MAIN_IDLE : _rMainState); rOffLast <= #1 _rOffLast; rWordsEQ0 <= #1 _rWordsEQ0; rStarted <= #1 _rStarted; rDoneLen <= #1 (RST ? 0 : _rDoneLen); rTxErrd <= #1 (RST ? 1'd0 : _rTxErrd); end always @ (*) begin _rMainState = rMainState; _rOffLast = rOffLast; _rWordsEQ0 = rWordsEQ0; _rStarted = rStarted; _rDoneLen = rDoneLen; _rTxErrd = rTxErrd; case (rMainState) `S_TXPORTWR_MAIN_IDLE: begin // Wait for channel write request _rStarted = 0; _rWordsEQ0 = (NEW_TXN_LEN == 0); _rOffLast = {NEW_TXN_OFF, NEW_TXN_LAST}; if (NEW_TXN) _rMainState = `S_TXPORTWR_MAIN_CHECK; end `S_TXPORTWR_MAIN_CHECK: begin // Continue with transaction? if (rOffLast[0] | !rWordsEQ0) _rMainState = `S_TXPORTWR_MAIN_SIG_NEW; else _rMainState = `S_TXPORTWR_MAIN_RESET; end `S_TXPORTWR_MAIN_SIG_NEW: begin // Signal new write _rMainState = `S_TXPORTWR_MAIN_NEW_ACK; end `S_TXPORTWR_MAIN_NEW_ACK: begin // Wait for acknowledgement if (rTxnAck) // ACK'd on PC read of TXN length _rMainState = (rWordsEQ0 ? `S_TXPORTWR_MAIN_SIG_DONE : `S_TXPORTWR_MAIN_WRITE); end `S_TXPORTWR_MAIN_WRITE: begin // Start writing and wait for all writes to complete _rStarted = (rStarted | rTxState[1]); // S_TXPORTWR_TX_BUF _rTxErrd = (rTxErrd | rSgErr); if (rTxState[0] & rStarted) // S_TXPORTWR_TX_IDLE _rMainState = `S_TXPORTWR_MAIN_DONE; end `S_TXPORTWR_MAIN_DONE: begin // Wait for the last transaction to complete if (rDone & rLastDoneRead) begin _rDoneLen = rSentWords; _rMainState = `S_TXPORTWR_MAIN_SIG_DONE; end end `S_TXPORTWR_MAIN_SIG_DONE: begin // Signal the done port _rTxErrd = 0; _rMainState = `S_TXPORTWR_MAIN_RESET; end `S_TXPORTWR_MAIN_RESET: begin // Wait for the channel tx to drop if (NEW_TXN_DONE) _rMainState = `S_TXPORTWR_MAIN_IDLE; end default: begin _rMainState = `S_TXPORTWR_MAIN_IDLE; end endcase end // Manage sending TX requests to the TX engine. Transfers will be limited // by each scatter gather buffer's size, max payload size, and must not // cross a (4KB) page boundary. The request is only made if there is sufficient // data already written to the buffer. wire [9:0] wLastLen = (NEW_TXN_WORDS_RECVD - rSentWords); wire [9:0] wAddrLoInv = ~rAddr[11:2]; wire [10:0] wPageRem = (wAddrLoInv + 1'd1); always @ (posedge CLK) begin rTxState <= #1 (RST | rSgErr ? `S_TXPORTWR_TX_IDLE : _rTxState); rSentWords <= #1 (rMainState[0] ? 0 : _rSentWords); rWords <= #1 _rWords; rBufWords <= #1 _rBufWords; rBufWordsInit <= #1 _rBufWordsInit; rAddr <= #1 _rAddr; rCarry <= #1 _rCarry; rValsPropagated <= #1 _rValsPropagated; rValsProp <= #1 _rValsProp; rLargeBuf <= #1 _rLargeBuf; rPageRem <= #1 _rPageRem; rPageSpill <= #1 _rPageSpill; rPageSpillInit <= #1 _rPageSpillInit; rCopyBufWords <= #1 _rCopyBufWords; rUseInit <= #1 _rUseInit; rPreLen <= #1 _rPreLen; rMaxPayloadSize <= #1 _rMaxPayloadSize; rMaxPayloadShift <= #1 _rMaxPayloadShift; rMaxPayload <= #1 _rMaxPayload; rPayloadSpill <= #1 _rPayloadSpill; rMaxLen <= #1 (RST ? 1'd1 : _rMaxLen); rLen <= #1 _rLen; rSendingWords <= #1 _rSendingWords; rAvail <= #1 _rAvail; rTxnDone <= #1 _rTxnDone; rLastLen <= #1 _rLastLen; rLastLenEQ0 <= #1 _rLastLenEQ0; rLenEQWords <= #1 _rLenEQWords; rLenEQBufWords <= #1 _rLenEQBufWords; end always @ (*) begin _rTxState = rTxState; _rCopyBufWords = rCopyBufWords; _rUseInit = rUseInit; _rValsProp = ((rValsProp<<1) | rTxState[3]); // S_TXPORTWR_TX_ADJ_1 _rValsPropagated = (rValsProp == 6'd0); _rLargeBuf = (SG_ELEM_LEN > rWords); {_rCarry[0], _rAddr[15:0]} = (rTxState[1] ? SG_ELEM_ADDR[15:0] : (rAddr[15:0] + ({12{rTxState[6]}} & {rLen, 2'd0}))); // S_TXPORTWR_TX_WRITE {_rCarry[1], _rAddr[31:16]} = (rTxState[1] ? SG_ELEM_ADDR[31:16] : (rAddr[31:16] + rCarry[0])); {_rCarry[2], _rAddr[47:32]} = (rTxState[1] ? SG_ELEM_ADDR[47:32] : (rAddr[47:32] + rCarry[1])); _rAddr[63:48] = (rTxState[1] ? SG_ELEM_ADDR[63:48] : (rAddr[63:48] + rCarry[2])); _rSentWords = (rTxState[7] ? NEW_TXN_WORDS_RECVD : rSentWords) + ({10{rTxState[6]}} & rLen); // S_TXPORTWR_TX_WRITE _rWords = (NEW_TXN_ACK ? NEW_TXN_LEN : (rWords - ({10{rTxState[6]}} & rLen))); // S_TXPORTWR_TX_WRITE _rBufWordsInit = (rLargeBuf ? rWords : SG_ELEM_LEN); _rBufWords = (rCopyBufWords ? rBufWordsInit : rBufWords) - ({10{rTxState[6]}} & rLen); // S_TXPORTWR_TX_WRITE _rPageRem = wPageRem; _rPageSpillInit = (rBufWordsInit > wPageRem); _rPageSpill = (rBufWords > wPageRem); _rPreLen = ((rPageSpillInit & rUseInit) | (rPageSpill & !rUseInit) ? rPageRem : rBufWords[10:0]); _rMaxPayloadSize = CONFIG_MAX_PAYLOAD_SIZE; _rMaxPayloadShift = (rMaxPayloadSize > 3'd4 ? 3'd4 : rMaxPayloadSize); _rMaxPayload = (6'd32< rMaxPayload); _rMaxLen = ((rMaxLen & !rValsProp[1]) | rTxState[6]); // S_TXPORTWR_TX_WRITE _rLen = (rPayloadSpill | rMaxLen ? rMaxPayload : rPreLen[9:0]); _rSendingWords = rSentWords + rLen; _rAvail = (NEW_TXN_WORDS_RECVD >= rSendingWords); _rTxnDone = ((rTxnDone<<1) | NEW_TXN_DONE); _rLastLen = wLastLen; _rLastLenEQ0 = (rLastLen == 10'd0); _rLenEQWords = (rLen == rWords); _rLenEQBufWords = (rLen == rBufWords); case (rTxState) `S_TXPORTWR_TX_IDLE: begin // Wait for channel write request if (rMainState[4] & !rStarted) // S_TXPORTWR_MAIN_WRITE _rTxState = `S_TXPORTWR_TX_BUF; end `S_TXPORTWR_TX_BUF: begin // Wait for buffer length and address if (SG_ELEM_RDY) _rTxState = `S_TXPORTWR_TX_ADJ_0; end `S_TXPORTWR_TX_ADJ_0: begin // Fix for large buffer _rCopyBufWords = 1; _rTxState = `S_TXPORTWR_TX_ADJ_1; end `S_TXPORTWR_TX_ADJ_1: begin // Check for page boundary crossing _rCopyBufWords = 0; _rUseInit = rCopyBufWords; _rTxState = `S_TXPORTWR_TX_ADJ_2; end `S_TXPORTWR_TX_ADJ_2: begin // Wait for values to propagate // Fix for page boundary crossing // Check for max payload // Fix for max payload _rUseInit = 0; if (rValsProp[2]) _rTxState = `S_TXPORTWR_TX_CHECK_DATA; end `S_TXPORTWR_TX_CHECK_DATA: begin // Wait for available data if (rNotRequesting) begin if (rAvail) _rTxState = `S_TXPORTWR_TX_WRITE; else if (rValsPropagated & rTxnDone[1]) _rTxState = (rLastLenEQ0 ? `S_TXPORTWR_TX_IDLE : `S_TXPORTWR_TX_WRITE_REM); end end `S_TXPORTWR_TX_WRITE: begin // Send len and repeat or finish? if (rLenEQWords) _rTxState = `S_TXPORTWR_TX_IDLE; else if (rLenEQBufWords) _rTxState = `S_TXPORTWR_TX_BUF; else _rTxState = `S_TXPORTWR_TX_ADJ_1; end `S_TXPORTWR_TX_WRITE_REM: begin // Send remaining data and finish _rTxState = `S_TXPORTWR_TX_IDLE; end default: begin _rTxState = `S_TXPORTWR_TX_IDLE; end endcase end // Request TX transfers separately so that the TX FSM can continue calculating // the next set of request parameters without having to wait for the TX_REQ_ACK. always @ (posedge CLK) begin rAckCount <= #1 (RST ? 10'd0 : _rAckCount); rNotRequesting <= #1 (RST ? 1'd1 : _rNotRequesting); rReqAddr <= #1 _rReqAddr; rReqLen <= #1 _rReqLen; rReqLast <= #1 _rReqLast; rDone <= #1 _rDone; rLastDoneRead <= #1 (RST ? 1'd1 : _rLastDoneRead); end always @ (*) begin // Start signaling when the TX FSM is ready. if (rTxState[6] | rTxState[7]) // S_TXPORTWR_TX_WRITE _rNotRequesting = 0; else _rNotRequesting = (rNotRequesting | rTxReqAck); // Pass off the rAddr & rLen when ready and wait for TX_REQ_ACK. if (rTxState[6]) begin // S_TXPORTWR_TX_WRITE _rReqAddr = rAddr; _rReqLen = rLen; _rReqLast = rLenEQWords; end else if (rTxState[7]) begin // S_TXPORTWR_TX_WRITE_REM _rReqAddr = rAddr; _rReqLen = rLastLen; _rReqLast = 1; end else begin _rReqAddr = rReqAddr; _rReqLen = rReqLen; _rReqLast = rReqLast; end // Track TX_REQ_ACK and TX_SENT to determine when the transaction is over. _rDone = (rAckCount == 10'd0); if (rMainState[0]) // S_TXPORTWR_MAIN_IDLE _rAckCount = 0; else _rAckCount = rAckCount + rTxState[6] + rTxState[7] - rTxSent; // S_TXPORTWR_TX_WRITE, S_TXPORTWR_TX_WRITE_REM // Track when the user reads the actual transfer amount. _rLastDoneRead = (rMainState[6] ? 1'd0 : (rLastDoneRead | rTxnDoneAck)); // S_TXPORTWR_MAIN_SIG_DONE end // Facilitate sending a TXN_DONE when we receive a TXN_ACK after the transaction // has begun sending. This will happen when the workstation detects that it has // sent/used all its currently mapped scatter gather elements, but it's not enough // to complete the transaction. The TXN_DONE will let the workstation know it can // release the current scatter gather mappings and allocate new ones. always @ (posedge CLK) begin rPartialDone <= #1 _rPartialDone; rReqPartialDone <= #1 (RST ? 1'd0 : _rReqPartialDone); end always @ (*) begin // Signal TXN_DONE after we've recieved the (seemingly superfluous) TXN_ACK, // we have no outstanding transfer requests, we're not currently requesting a // transfer, and there are no more scatter gather elements. _rPartialDone = (rReqPartialDone & rDone & rNotRequesting & SG_ELEM_EMPTY & rTxState[1]); // S_TXPORTWR_TX_BUF // Keep track of (seemingly superfluous) TXN_ACK requests. if ((rReqPartialDone & rDone & rNotRequesting & SG_ELEM_EMPTY & rTxState[1]) | rMainState[0]) // S_TXPORTWR_MAIN_IDLE _rReqPartialDone = 0; else _rReqPartialDone = (rReqPartialDone | (rTxnAck & !rMainState[3])); // !S_TXPORTWR_MAIN_NEW_ACK end endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_qword_aligner_128.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 19:27:32 05/15/2014 // Design Name: // Module Name: tx_qword_aligner_128 // Project Name: // Target Devices: // Tool versions: // Description: // Shifts the data payload of outgoing TLP's to conform to Altera's Quad-word // alignment requirement. This module has a 2 cycle latency. It also handles the // 2 cycle Transmit ready latency from the specification. // // Dependencies: None // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// `define S_TXALIGNER128UP_IDLE 2'b00 `define S_TXALIGNER128UP_HDR0 2'b01 `define S_TXALIGNER128UP_PAY 2'b10 `define S_TXALIGNER128LOW_IDLE 2'b00 `define S_TXALIGNER128LOW_PROC 2'b01 `define S_TXALIGNER128LOW_PREOVFL 2'b10 `define S_TXALIGNER128LOW_OVFL 2'b11 module tx_qword_aligner_128 #( parameter C_ALTERA = 1'b1, parameter C_PCI_DATA_WIDTH = 9'd128, parameter C_TX_READY_LATENCY = 3'd2 ) ( input CLK, input RST_IN, input [C_PCI_DATA_WIDTH-1:0] TX_DATA, input TX_DATA_VALID, output TX_DATA_READY, input TX_TLP_END_FLAG, input TX_TLP_START_FLAG, output [C_PCI_DATA_WIDTH-1:0] TX_ST_DATA, output [0:0] TX_ST_VALID, input TX_ST_READY, output [0:0] TX_ST_EOP, output [0:0] TX_ST_SOP, output TX_ST_EMPTY ); reg [C_TX_READY_LATENCY-1:0] rTxStReady=0, _rTxStReady=0; // Registers for first cycle of pipeline (upper) // Capture reg [C_PCI_DATA_WIDTH-1:0] rTxData=0,_rTxData=0; reg rTxDataValid=0, _rTxDataValid=0; reg rTxTlpEndFlag=0, _rTxTlpEndFlag=0; reg rTxTlpStartFlag=0, _rTxTlpStartFlag=0; // Computed reg [1:0] rOverflow=0, _rOverflow=0; reg [9:0] rRealLength=0, _rRealLength=0; reg [9:0] rAdjLength=0, _rAdjLength=0; reg rInsBlank=0,_rInsBlank=0; // State (controls pipeline) reg [1:0] rUpState=0, _rUpState=0; // Second cycle of pipeline (lower) reg [C_PCI_DATA_WIDTH+32-1:0] rAlignBuffer=0, _rAlignBuffer=0; reg [1:0] rLowState=0, _rLowState=0; reg rSel=0, _rSel=0; reg rTrigger=0,_rTrigger=0; // Registered outputs reg rTxStValid=0,_rTxStValid=0; reg rTxStEop=0,_rTxStEop=0; reg rTxStSop=0,_rTxStSop=0; reg rTxStEmpty=0,_rTxStEmpty=0; wire [1:0] wRegEn; // Wires (unregistered) from input wire [2:0] wFMT; wire [63:0] w4DWHAddr; wire [31:0] w3DWHAddr; wire w3DWH; wire w4DWH; wire wInsBlank; wire w4DWHQWA; wire w3DWHQWA; wire [9:0] wLength; wire wDataTLP; wire w3DWHInsBlank; wire w4DWHInsBlank; // Overflow indicating wire to the second stage of the pipeline wire wOverflow; wire wSMLowEnable; wire wSMUpEnable; wire wTxStEopCondition; wire [255:0] wAlignBufMux; // Wires from the unregistered TLP Header assign wFMT = TX_DATA[31:29]; assign w4DWHAddr = {TX_DATA[95:64],TX_DATA[127:96]}; assign w3DWHAddr = TX_DATA[95:64]; assign wLength = TX_DATA[9:0]; assign w4DWH = wFMT[0]; assign w3DWH = ~wFMT[0]; assign wDataTLP = wFMT[1]; assign w4DWHQWA = ~w4DWHAddr[2]; assign w3DWHQWA = ~w3DWHAddr[2]; assign w3DWHInsBlank = w3DWHQWA & w3DWH & wDataTLP; assign w4DWHInsBlank = ~w4DWHQWA & w4DWH & wDataTLP; assign wInsBlank = w3DWHInsBlank | w4DWHInsBlank; // Insert a blank DW after the header assign wRegEn[0] = (~rTxDataValid | wRegEn[1]); assign wSMUpEnable = wRegEn[0]; assign TX_DATA_READY = wRegEn[0]; // Unconditional input capture always @(*) begin _rTxStReady = (rTxStReady << 1) | TX_ST_READY; end always @(posedge CLK) begin rTxStReady <= _rTxStReady; end // All of these signals are "valid" when rTxTlpStartFlag and rTxDataValid is high always @(*) begin _rInsBlank = wInsBlank & TX_TLP_START_FLAG & TX_DATA_VALID; _rRealLength = wLength + {7'd0,{w4DWH,~w4DWH,~w4DWH}}; _rAdjLength = wLength + {9'd0,wInsBlank} + {7'd0,{w4DWH,~w4DWH,~w4DWH}}; _rTxData = TX_DATA; _rTxTlpEndFlag = TX_TLP_END_FLAG & TX_DATA_VALID; _rTxTlpStartFlag = TX_TLP_START_FLAG & TX_DATA_VALID; end // always @ begin always @(posedge CLK) begin rInsBlank <= _rInsBlank; rRealLength <= _rRealLength; rAdjLength <= _rAdjLength; if(wRegEn[0]) begin rTxData <= _rTxData; rTxTlpEndFlag <= _rTxTlpEndFlag; rTxTlpStartFlag <= _rTxTlpStartFlag; end end always @(*) begin _rOverflow[0] = TX_TLP_START_FLAG & TX_TLP_END_FLAG & w3DWHInsBlank; _rOverflow[1] = rTxTlpStartFlag & (rRealLength[9:2] < rAdjLength[9:2]); end // always @ begin always @(posedge CLK) begin if(wSMUpEnable) begin rOverflow[0] <= _rOverflow[0]; rOverflow[1] <= _rOverflow[1]; end end // State machine for the upper pipeline // Valid never goes down inside of a TLP. always @(*) begin _rTxDataValid = rTxDataValid; if(wSMUpEnable & TX_DATA_VALID) begin _rTxDataValid = 1'b1; end else if ( wSMUpEnable & rTxTlpEndFlag)begin _rTxDataValid = 1'b0; end _rUpState = rUpState; case (rUpState) `S_TXALIGNER128UP_IDLE: begin if (TX_DATA_VALID & wRegEn[0]) begin _rUpState = `S_TXALIGNER128UP_HDR0; end end `S_TXALIGNER128UP_HDR0: begin if(wSMUpEnable) begin casex ({rTxTlpEndFlag,TX_DATA_VALID}) 2'b0x: _rUpState = `S_TXALIGNER128UP_PAY; 2'b10: _rUpState = `S_TXALIGNER128UP_IDLE; 2'b11: _rUpState = `S_TXALIGNER128UP_HDR0; endcase // case (rTxTlpEndFlag) end end `S_TXALIGNER128UP_PAY : begin if(wSMUpEnable) begin casex ({rTxTlpEndFlag,TX_DATA_VALID}) 2'b0x: _rUpState = `S_TXALIGNER128UP_PAY; 2'b10: _rUpState = `S_TXALIGNER128UP_IDLE; 2'b11: _rUpState = `S_TXALIGNER128UP_HDR0; endcase // case (rTxTlpEndFlag) end end default: _rUpState = `S_TXALIGNER128UP_IDLE; endcase // case (rUpState) end // always @ begin always @(posedge CLK) begin if(RST_IN) begin rTxDataValid <= 0; rUpState <= `S_TXALIGNER128UP_IDLE; end else begin rTxDataValid <= _rTxDataValid; rUpState <= _rUpState; end end // always @ (posedge CLK) // These signals comprise the lower aligner assign wSMLowEnable = rTxStReady[C_TX_READY_LATENCY-1] | ~rTxStValid; assign wRegEn[1] = ~(rLowState == `S_TXALIGNER128LOW_PREOVFL & rTrigger) & (wSMLowEnable); assign wOverflow = (rOverflow[0] | rOverflow[1]); assign wAlignBufMux = ({{rTxData[95:0],rAlignBuffer[159:128]},rTxData}) >> ({rSel,7'd0}); always @(*) begin _rAlignBuffer = {rTxData[127:96], wAlignBufMux[127:0]}; end // always @ begin always @(posedge CLK) begin if(wSMLowEnable) begin rAlignBuffer <= _rAlignBuffer; end end assign wTxStEopCondition = (rLowState == `S_TXALIGNER128LOW_PREOVFL & rTrigger) | (rLowState != `S_TXALIGNER128LOW_PREOVFL & {rTxTlpEndFlag,wOverflow,rTxDataValid} == 3'b101); // Valid never goes down inside of a TLP. always @(*) begin _rLowState = rLowState; _rTrigger = rTrigger; _rTxStValid = rTxStValid; _rTxStEop = rTxStEop; _rTxStSop = rTxStSop; _rSel = rSel; _rTxStEop = wTxStEopCondition; _rTrigger = rTxTlpEndFlag & rTxDataValid; _rTxStEmpty = (rAdjLength[1:0] == 2'b01) | (rAdjLength[1:0] == 2'b10); // Take the next txDataValid if we are taking data // and it's a start flag and the data is valid if ( wRegEn[1] & rTxTlpStartFlag & rTxDataValid ) begin _rTxStValid = 1; end else if ( wSMLowEnable & rTxStEop ) begin _rTxStValid = 0; end if ( wRegEn[1] & rTxDataValid ) begin // DOUBLE CHECK _rTxStSop = rTxTlpStartFlag; end else if ( wSMLowEnable ) begin _rTxStSop = 0; end // rSel should be set on wInsBlank kept high until the end of the packet // Note: rSel is only applicable in multi-cycle packets if (wSMLowEnable & rInsBlank) begin _rSel = 1'b1; end else if (wSMLowEnable & wTxStEopCondition) begin _rSel = 1'b0; end case (rLowState) `S_TXALIGNER128LOW_IDLE : begin if(wSMLowEnable) begin casex({rTxTlpEndFlag,wOverflow,rTxDataValid}) // Set the state for the next cycle 3'bxx0: _rLowState = `S_TXALIGNER128LOW_IDLE; // Stay here 3'b001: _rLowState = `S_TXALIGNER128LOW_PROC; // Process 3'b011: _rLowState = `S_TXALIGNER128LOW_PREOVFL; // Don't set rTxStEop (set trigger) 3'b101: _rLowState = `S_TXALIGNER128LOW_PROC; // Set rTxStEop 3'b111: _rLowState = `S_TXALIGNER128LOW_PREOVFL; // Don't set rTxStEop (set trigger) endcase end end `S_TXALIGNER128LOW_PROC : begin if(wSMLowEnable) begin casex({rTxTlpEndFlag,wOverflow,rTxDataValid}) // Set the state for the next cycle 3'bxx0: _rLowState = `S_TXALIGNER128LOW_IDLE; // If the next cycle is not valid Eop must have been set this cycle and we should go to idle 3'b001: _rLowState = `S_TXALIGNER128LOW_PROC; // Continue processing 3'b011: _rLowState = `S_TXALIGNER128LOW_PREOVFL; // Don't set rTxStEop (set trigger) 3'b101: _rLowState = `S_TXALIGNER128LOW_PROC; // set rTxStEop 3'b111: _rLowState = `S_TXALIGNER128LOW_PREOVFL; // Don't set rTxStEop (set trigger) endcase end end `S_TXALIGNER128LOW_PREOVFL : begin if(wSMLowEnable) begin if(rTrigger) begin _rLowState = `S_TXALIGNER128LOW_OVFL; end end end `S_TXALIGNER128LOW_OVFL : begin if(wSMLowEnable) begin casex({rTxTlpEndFlag,wOverflow,rTxDataValid}) // Set the state for the next cycle 3'bxx0: _rLowState = `S_TXALIGNER128LOW_IDLE; // If the next cycle is not valid Eop must have been set this cycle and we should go to idle 3'b001: _rLowState = `S_TXALIGNER128LOW_PROC; // Continue processing 3'b011: _rLowState = `S_TXALIGNER128LOW_PREOVFL; // Don't set rTxStEop (Don't set trigger) 3'b101: _rLowState = `S_TXALIGNER128LOW_PROC; // set rTxStEop 3'b111: _rLowState = `S_TXALIGNER128LOW_PREOVFL; // Don't set rTxStEop (set trigger) endcase end end endcase end // always @ begin always @(posedge CLK) begin if(RST_IN) begin rLowState <= `S_TXALIGNER128LOW_IDLE; rTxStValid <= 0; rTxStSop <= 0; rSel <= 0; end else begin rTxStValid <= _rTxStValid; rTxStSop <= _rTxStSop; rSel <= _rSel; rLowState <= _rLowState; end // else: !if(RST_IN) if (RST_IN) begin rTxStEop <= 1'b0; end else if (wSMLowEnable) begin rTxStEop <= _rTxStEop; end if (RST_IN) begin rTrigger <= 1'b0; end else if (wRegEn[1]) begin rTrigger <= _rTrigger; end if (RST_IN) begin rTxStEmpty <= 1'b0; end else if(wRegEn[1] & rTxTlpStartFlag) begin rTxStEmpty <= _rTxStEmpty; end end // always @ (posedge CLK) // Outputs from the aligner to the PCIe Core assign TX_ST_VALID = (rTxStValid & rTxStReady[C_TX_READY_LATENCY-1]); assign TX_ST_EOP = rTxStEop; assign TX_ST_SOP = rTxStSop; assign TX_ST_EMPTY = rTxStEmpty; assign TX_ST_DATA = rAlignBuffer[127:0]; endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/riffa/tx_qword_aligner_64.v ================================================ `timescale 1ns/1ns //---------------------------------------------------------------------------- // This software is Copyright © 2012 The Regents of the University of // California. All Rights Reserved. // // Permission to copy, modify, and distribute this software and its // documentation for educational, research and non-profit purposes, without // fee, and without a written agreement is hereby granted, provided that the // above copyright notice, this paragraph and the following three paragraphs // appear in all copies. // // Permission to make commercial use of this software may be obtained by // contacting: // Technology Transfer Office // 9500 Gilman Drive, Mail Code 0910 // University of California // La Jolla, CA 92093-0910 // (858) 534-5815 // invent@ucsd.edu // // This software program and documentation are copyrighted by The Regents of // the University of California. The software program and documentation are // supplied "as is", without any accompanying services from The Regents. The // Regents does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program was // developed for research purposes and is advised not to rely exclusively on // the program for any reason. // // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO // ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, // EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF // CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, // AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR // MODIFICATIONS. //---------------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 19:27:32 06/14/2012 // Design Name: // Module Name: tx_qword_aligner_64 // Project Name: // Target Devices: // Tool versions: // Description: // Shifts the data payload of outgoing TLP's to conform to Altera's Quad-word // alignment requirement. This module has a 2 cycle latency. It also handles the // 2 cycle Transmit ready latency from the specification. // // Dependencies: None // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// `define S_TXALIGNER64UP_IDLE 2'b00 `define S_TXALIGNER64UP_HDR0 2'b01 `define S_TXALIGNER64UP_HDR1 2'b10 `define S_TXALIGNER64UP_PAY 2'b11 `define S_TXALIGNER64LOW_IDLE 2'b00 `define S_TXALIGNER64LOW_PROC 2'b01 `define S_TXALIGNER64LOW_PREOVFL 2'b10 `define S_TXALIGNER64LOW_OVFL 2'b11 module tx_qword_aligner_64 #( parameter C_ALTERA = 1'b1, parameter C_PCI_DATA_WIDTH = 9'd64, parameter C_TX_READY_LATENCY = 3'd1 ) ( input CLK, input RST_IN, input [C_PCI_DATA_WIDTH-1:0] TX_DATA, input TX_DATA_VALID, output TX_DATA_READY, input TX_TLP_END_FLAG, input TX_TLP_START_FLAG, output [C_PCI_DATA_WIDTH-1:0] TX_ST_DATA, output [0:0] TX_ST_VALID, input TX_ST_READY, output [0:0] TX_ST_EOP, output [0:0] TX_ST_SOP, output TX_ST_EMPTY ); reg [C_TX_READY_LATENCY-1:0] rTxStReady, _rTxStReady; // Registers for first cycle of pipeline (upper) // Capture reg [C_PCI_DATA_WIDTH-1:0] rTxData,_rTxData; reg rTxDataValid, _rTxDataValid; reg rTxTlpEndFlag, _rTxTlpEndFlag; reg rTxTlpStartFlag, _rTxTlpStartFlag; // Registers for the second cycle of the state machine reg r3DWHInsBlank,_r3DWHInsBlank; reg [C_PCI_DATA_WIDTH+32-1:0] rAlignBuffer, _rAlignBuffer; // Registers for the third cycle of the state machine reg r4DWHInsBlank,_r4DWHInsBlank; // State (controls upper pipeline) reg [1:0] rUpState, _rUpState; reg rSel, _rSel; reg rTrigger,_rTrigger; // Second stage of pipeline (lower) reg [1:0] rLowState, _rLowState; // Registered Outputs reg rTxStValid,_rTxStValid; reg rTxStEop,_rTxStEop; reg rTxStSop,_rTxStSop; // Wires wire [1:0] wRegEn; reg r4DWH, _r4DWH; reg r3DWH, _r3DWH; reg rDataTLP, _rDataTLP; reg rLenEven,_rLenEven; reg rLenOdd,_rLenOdd; reg r4DWHQWA, _r4DWHQWA; reg r3DWHQWA, _r3DWHQWA; wire [127:0] wAlignBufMux; wire w3DWHInsBlank; wire w4DWHInsBlank; wire wOverflow; wire wSMLowEnable; wire wSMUpEnable; wire wTxStEopCondition; // Unconditional input capture always @(*) begin _rTxStReady = (rTxStReady << 1) | TX_ST_READY; end always @(posedge CLK) begin rTxStReady <= _rTxStReady; end // Take data when: assign wRegEn[0] = (~rTxDataValid | wRegEn[1]); assign wSMUpEnable = wRegEn[0]; assign TX_DATA_READY = wRegEn[0]; always @(*) begin _rTxData = TX_DATA; _rTxTlpEndFlag = TX_TLP_END_FLAG & TX_DATA_VALID; _rTxTlpStartFlag = TX_TLP_START_FLAG & TX_DATA_VALID; end // always @ begin always @(posedge CLK) begin if(wRegEn[0]) begin rTxData <= _rTxData; rTxTlpEndFlag <= _rTxTlpEndFlag; rTxTlpStartFlag <= _rTxTlpStartFlag; end end always @(*) begin _r4DWH = rTxData[29] & rTxTlpStartFlag; _r3DWH = ~rTxData[29] & rTxTlpStartFlag; _rDataTLP = rTxData[30] & rTxTlpStartFlag; _rLenEven = ~rTxData[0] & rTxTlpStartFlag; _rLenOdd = rTxData[0] & rTxTlpStartFlag; _r4DWHQWA = ~TX_DATA[34] & rTxTlpStartFlag; _r3DWHQWA = ~TX_DATA[2] & rTxTlpStartFlag; end // always @ begin always @(posedge CLK) begin if(wRegEn[0]) begin r4DWH <= _r4DWH; r3DWH <= _r3DWH; rDataTLP <= _rDataTLP; rLenEven <= _rLenEven; rLenOdd <= _rLenOdd; r4DWHQWA <= _r4DWHQWA; r3DWHQWA <= _r3DWHQWA; end end // State machine for the upper pipeline // Valid never goes down inside of a TLP. always @(*) begin _rTxDataValid = rTxDataValid; if(wSMUpEnable & TX_DATA_VALID) begin // & TX_TLP_START_FLAG _rTxDataValid = 1'b1; end else if ( wSMUpEnable & rTxTlpEndFlag)begin _rTxDataValid = 1'b0; end _rUpState = rUpState; case (rUpState) `S_TXALIGNER64UP_IDLE: begin if (TX_DATA_VALID & wSMUpEnable) begin _rUpState = `S_TXALIGNER64UP_HDR0; end end `S_TXALIGNER64UP_HDR0: begin if(wSMUpEnable) begin _rUpState = `S_TXALIGNER64UP_HDR1; end end `S_TXALIGNER64UP_HDR1: begin if(wSMUpEnable) begin casex ({rTxTlpEndFlag,TX_DATA_VALID}) 2'b0x: _rUpState = `S_TXALIGNER64UP_PAY; 2'b10: _rUpState = `S_TXALIGNER64UP_IDLE; // No new TLP 2'b11: _rUpState = `S_TXALIGNER64UP_HDR0; endcase // case (rTxTlpEndFlag) end end `S_TXALIGNER64UP_PAY : begin if(wSMUpEnable) begin casex ({rTxTlpEndFlag,TX_DATA_VALID}) 2'b0x: _rUpState = `S_TXALIGNER64UP_PAY; 2'b10: _rUpState = `S_TXALIGNER64UP_IDLE; // No new TLP 2'b11: _rUpState = `S_TXALIGNER64UP_HDR0; endcase // case (rTxTlpEndFlag) end end endcase // case (rUpState) end // always @ begin always @(posedge CLK) begin rTxDataValid <= _rTxDataValid; if(RST_IN) begin rUpState <= `S_TXALIGNER64UP_IDLE; end else begin rUpState <= _rUpState; end end // always @ (posedge CLK) assign wSMLowEnable = rTxStReady[C_TX_READY_LATENCY-1] | ~rTxStValid; assign wRegEn[1] = ~(rLowState == `S_TXALIGNER64LOW_PREOVFL & rTrigger) & (wSMLowEnable); assign w3DWHInsBlank = rDataTLP & r3DWH & r3DWHQWA; assign w4DWHInsBlank = rDataTLP & r4DWH & ~r4DWHQWA; assign wOverflow = (w4DWHInsBlank & rLenEven) | (w3DWHInsBlank & rLenOdd); assign wAlignBufMux = ({{rTxData[31:0],rAlignBuffer[95:64]},rTxData[63:0]}) >> ({rSel,6'd0}); always @(*) begin _rAlignBuffer = {rTxData[63:32], wAlignBufMux[63:0]}; end // always @ begin always @(posedge CLK) begin if(wSMLowEnable) begin rAlignBuffer <= _rAlignBuffer; end end assign wTxStEopCondition = (rLowState == `S_TXALIGNER64LOW_PREOVFL & rTrigger) | (rLowState != `S_TXALIGNER64LOW_PREOVFL & {rTxTlpEndFlag,wOverflow,rTxDataValid} == 3'b101); // Valid never goes down inside of a TLP. always @(*) begin _rLowState = rLowState; _rTrigger = rTrigger; _rTxStValid = rTxStValid; _rTxStEop = rTxStEop; _rTxStSop = rTxStSop; _rSel = rSel; _rTxStEop = wTxStEopCondition; _rTrigger = rTxDataValid & rTxTlpEndFlag; // Take the next txDataValid if we are taking data (wRegEn[1]) // and it's a start flag and the data is valid if ( wRegEn[1] & rTxTlpStartFlag & rTxDataValid ) begin _rTxStValid = 1; end else if ( wSMLowEnable & rTxStEop | RST_IN ) begin _rTxStValid = 0; end if ( wRegEn[1] & rTxDataValid ) begin _rTxStSop = rTxTlpStartFlag; end else if ( wSMLowEnable | RST_IN) begin _rTxStSop = 0; end // rSel should be set on wInsBlank kept high until the end of the packet // Note: rSel is only applicable in multi-cycle packets if (wSMLowEnable & (w3DWHInsBlank | w4DWHInsBlank)) begin _rSel = 1'b1; end else if (wSMLowEnable & wTxStEopCondition | RST_IN) begin _rSel = 1'b0; end case (rLowState) `S_TXALIGNER64LOW_IDLE : begin if(wSMLowEnable) begin casex({rTxTlpEndFlag,wOverflow,rTxDataValid}) // Set the state for the next cycle 3'bxx0: _rLowState = `S_TXALIGNER64LOW_IDLE; // Stay here 3'b001: _rLowState = `S_TXALIGNER64LOW_PROC; // Process 3'b011: _rLowState = `S_TXALIGNER64LOW_PREOVFL; // Don't set rTxStEop (set trigger) 3'b101: _rLowState = `S_TXALIGNER64LOW_PROC; // Set rTxStEop 3'b111: _rLowState = `S_TXALIGNER64LOW_PREOVFL; // Don't set rTxStEop (set trigger) endcase end end `S_TXALIGNER64LOW_PROC : begin if(wSMLowEnable) begin casex({rTxTlpEndFlag,wOverflow,rTxDataValid}) // Set the state for the next cycle 3'bxx0: _rLowState = `S_TXALIGNER64LOW_IDLE; // If the next cycle is not valid Eop must have been set this cycle and we should go to idle 3'b001: _rLowState = `S_TXALIGNER64LOW_PROC; // Continue processing 3'b011: _rLowState = `S_TXALIGNER64LOW_PREOVFL; // Don't set rTxStEop (set trigger) 3'b101: _rLowState = `S_TXALIGNER64LOW_PROC; // set rTxStEop 3'b111: _rLowState = `S_TXALIGNER64LOW_PREOVFL; // Don't set rTxStEop (set trigger) endcase end end `S_TXALIGNER64LOW_PREOVFL : begin if(wSMLowEnable) begin if(rTrigger) begin _rLowState = `S_TXALIGNER64LOW_OVFL; end end end `S_TXALIGNER64LOW_OVFL : begin if(wSMLowEnable) begin casex({rTxTlpEndFlag,wOverflow,rTxDataValid}) // Set the state for the next cycle 3'bxx0: _rLowState = `S_TXALIGNER64LOW_IDLE; // If the next cycle is not valid Eop must have been set this cycle and we should go to idle 3'b001: _rLowState = `S_TXALIGNER64LOW_PROC; // Continue processing 3'b011: _rLowState = `S_TXALIGNER64LOW_PREOVFL; // Don't set rTxStEop (Don't set trigger) 3'b101: _rLowState = `S_TXALIGNER64LOW_PROC; // set rTxStEop 3'b111: _rLowState = `S_TXALIGNER64LOW_PREOVFL; // Don't set rTxStEop (set trigger) endcase end end endcase end // always @ begin always @(posedge CLK) begin if(RST_IN) begin rLowState <= `S_TXALIGNER64LOW_IDLE; rTxStValid <= 0; rTxStSop <= 0; rSel <= 0; end else begin rTxStValid <= _rTxStValid; rTxStSop <= _rTxStSop; rSel <= _rSel; rLowState <= _rLowState; end if (RST_IN) begin rTxStEop <= 1'b0; end else if (wSMLowEnable) begin rTxStEop <= _rTxStEop; end if (RST_IN) begin rTrigger <= 1'b0; end else if (wRegEn[1]) begin rTrigger <= _rTrigger; end end // always @ (posedge CLK) // Outputs from the aligner to the PCIe Core assign TX_ST_VALID = (rTxStValid & rTxStReady[C_TX_READY_LATENCY-1]); assign TX_ST_EOP = rTxStEop; assign TX_ST_SOP = rTxStSop; assign TX_ST_EMPTY = 1'b0; assign TX_ST_DATA = rAlignBuffer[63:0]; endmodule ================================================ FILE: hw/boards/ML605/ipcore_dir/xilinx_mig/example_design/mig.prj ================================================ xilinx_mig 1 0 OFF xc6vlx240t-ff1156/-1 3.92 Differential FALSE HIGH 0 DDR3_SDRAM/SODIMMs/MT4JSF6464HY-1G1 2500 64 1 1 FALSE 13 10 3 Disabled 1 25 ROW_BANK_COLUMN Normal 8 - Fixed Sequential 6 Normal No Slow Exit Enable RZQ/7 RZQ/4 0 Disabled Enabled Output Buffer Enabled Full Array 5 Enabled Normal Dynamic ODT off NATIVE ================================================ FILE: hw/boards/ML605/ipcore_dir/xilinx_mig/user_design/mig.prj ================================================ xilinx_mig 1 0 OFF xc6vlx240t-ff1156/-1 3.92 Differential FALSE HIGH 0 DDR3_SDRAM/SODIMMs/MT4JSF6464HY-1G1 2500 64 1 1 FALSE 13 10 3 Disabled 1 25 ROW_BANK_COLUMN Normal 8 - Fixed Sequential 6 Normal No Slow Exit Enable RZQ/7 RZQ/4 0 Disabled Enabled Output Buffer Enabled Full Array 5 Enabled Normal Dynamic ODT off NATIVE ================================================ FILE: hw/boards/ML605/ipcore_dir/xilinx_mig.xco ================================================ ############################################################## # # Xilinx Core Generator version 14.6 # Date: Fri Feb 3 17:08:27 2017 # ############################################################## # # This file contains the customisation parameters for a # Xilinx CORE Generator IP GUI. It is strongly recommended # that you do not manually alter this file as it may cause # unexpected and unsupported behavior. # ############################################################## # # Generated from component: xilinx.com:ip:mig:3.92 # ############################################################## # # BEGIN Project Options SET addpads = false SET asysymbol = true SET busformat = BusFormatAngleBracketNotRipped SET createndf = false SET designentry = Verilog SET device = xc6vlx240t SET devicefamily = virtex6 SET flowvendor = Other SET formalverification = false SET foundationsym = false SET implementationfiletype = Ngc SET package = ff1156 SET removerpms = false SET simulationfiles = Behavioral SET speedgrade = -1 SET verilogsim = true SET vhdlsim = false # END Project Options # BEGIN Select SELECT MIG_Virtex-6_and_Spartan-6 family Xilinx,_Inc. 3.92 # END Select # BEGIN Parameters CSET component_name=xilinx_mig CSET xml_input_file=./xilinx_mig/user_design/mig.prj # END Parameters # BEGIN Extra information MISC pkg_timestamp=2013-06-08T23:00:50Z # END Extra information GENERATE # CRC: 5879c58d ================================================ FILE: hw/boards/ML605/ipcore_dir/xilinx_mig.xise ================================================
================================================ FILE: hw/boards/ML605/iseq_dispatcher.v ================================================ `timescale 1ns / 1ps module iseq_dispatcher #(parameter ROW_WIDTH = 15, BANK_WIDTH = 3, CKE_WIDTH = 1, CS_WIDTH = 1, nCS_PER_RANK = 1, DQ_WIDTH = 64) ( input clk, input rst, input periodic_read_lock, input process_iseq, output dispatcher_busy, output instr0_fifo_rd, input instr0_fifo_empty, input[31:0] instr0_fifo_data, output instr1_fifo_rd, input instr1_fifo_empty, input[31:0] instr1_fifo_data, //DFI Interface // DFI Control/Address input dfi_ready, input dfi_init_complete, output [ROW_WIDTH-1:0] dfi_address0, output [ROW_WIDTH-1:0] dfi_address1, output [BANK_WIDTH-1:0] dfi_bank0, output [BANK_WIDTH-1:0] dfi_bank1, output dfi_cke0, output dfi_cke1, output dfi_cas_n0, output dfi_cas_n1, output [CS_WIDTH*nCS_PER_RANK-1:0] dfi_cs_n0, output [CS_WIDTH*nCS_PER_RANK-1:0] dfi_cs_n1, output [CS_WIDTH*nCS_PER_RANK-1:0] dfi_odt0, output [CS_WIDTH*nCS_PER_RANK-1:0] dfi_odt1, output dfi_ras_n0, output dfi_ras_n1, output dfi_we_n0, output dfi_we_n1, // DFI Write output dfi_wrdata_en, output [4*DQ_WIDTH-1:0] dfi_wrdata, output [4*(DQ_WIDTH/8)-1:0] dfi_wrdata_mask, // DFI Read output dfi_rddata_en, output dfi_rddata_en_even, output dfi_rddata_en_odd, //Bus Command output io_config_strobe, output[1:0] io_config, //Misc. output pr_rd_ack, //auto-refresh output aref_set_interval, output[27:0] aref_interval, output aref_set_trfc, output[27:0] aref_trfc ); reg dispatcher_busy_r = 1'b0, dispatcher_busy_ns; //check conditions and start transaction always@* dispatcher_busy_ns = ~rst & process_iseq | (dispatcher_busy_r & (~(instr0_fifo_empty & instr1_fifo_empty) | instr0_disp_en | instr1_disp_en)); always@(posedge clk) dispatcher_busy_r <= dispatcher_busy_ns; wire instr0_disp_en, instr1_disp_en; wire instr0_disp_ack, instr1_disp_ack; wire[31:0] instr0, instr1; wire instr0_ready, instr1_ready; assign instr0_fifo_rd = instr0_ready & dispatcher_busy_r; assign instr1_fifo_rd = instr1_ready & dispatcher_busy_r; pipe_reg #(.WIDTH(32)) i_instr0_reg( .clk(clk), .rst(rst), .ready_in(instr0_disp_ack), .valid_in(dispatcher_busy_r & !instr0_fifo_empty), .data_in(instr0_fifo_data), .valid_out(instr0_disp_en), .data_out(instr0), .ready_out(instr0_ready) ); pipe_reg #(.WIDTH(32)) i_instr1_reg( .clk(clk), .rst(rst), .ready_in(instr1_disp_ack), .valid_in(dispatcher_busy_r & !instr1_fifo_empty), .data_in(instr1_fifo_data), .valid_out(instr1_disp_en), .data_out(instr1), .ready_out(instr1_ready) ); //Command Dispatcher Instantiation instr_dispatcher #(.ROW_WIDTH(ROW_WIDTH), .BANK_WIDTH(BANK_WIDTH), .CKE_WIDTH(CKE_WIDTH), .CS_WIDTH(CS_WIDTH), .nCS_PER_RANK(nCS_PER_RANK), .DQ_WIDTH(DQ_WIDTH)) i_instr_dispatcher( .clk(clk), .rst(rst), .periodic_read_lock(periodic_read_lock), .en_in0(instr0_disp_en), .en_ack0(instr0_disp_ack), .instr_in0(instr0), .en_in1(instr1_disp_en), .en_ack1(instr1_disp_ack), .instr_in1(instr1), //DFI Interface // DFI Control/Address .dfi_ready(dfi_ready), .dfi_address0(dfi_address0), .dfi_address1(dfi_address1), .dfi_bank0(dfi_bank0), .dfi_bank1(dfi_bank1), .dfi_cke0(dfi_cke0), .dfi_cke1(dfi_cke1), .dfi_cas_n0(dfi_cas_n0), .dfi_cas_n1(dfi_cas_n1), .dfi_cs_n0(dfi_cs_n0), .dfi_cs_n1(dfi_cs_n1), .dfi_odt0(dfi_odt0), .dfi_odt1(dfi_odt1), .dfi_ras_n0(dfi_ras_n0), .dfi_ras_n1(dfi_ras_n1), .dfi_we_n0(dfi_we_n0), .dfi_we_n1(dfi_we_n1), // DFI Write .dfi_wrdata_en(dfi_wrdata_en), .dfi_wrdata(dfi_wrdata), .dfi_wrdata_mask(dfi_wrdata_mask), // DFI Read .dfi_rddata_en(dfi_rddata_en), .dfi_rddata_en_even(dfi_rddata_en_even), .dfi_rddata_en_odd(dfi_rddata_en_odd), //Bus Command .io_config_strobe(io_config_strobe), .io_config(io_config), //Misc. .pr_rd_ack(pr_rd_ack), //auto-refresh .aref_set_interval(aref_set_interval), .aref_interval(aref_interval), .aref_set_trfc(aref_set_trfc), .aref_trfc(aref_trfc) ); assign dispatcher_busy = dispatcher_busy_r; endmodule ================================================ FILE: hw/boards/ML605/maint_ctrl.v ================================================ `timescale 1ps / 1ps //Hasan module maint_ctrl_top #(parameter RANK_WIDTH = 1, TCQ = 100, tCK = 2500, nCK_PER_CLK = 2, MAINT_PRESCALER_PERIOD = 200000) ( input clk, input rst, input dfi_init_complete, input periodic_rd_ack, output periodic_rd_req, input zq_ack, output zq_req, //Auto-refresh input autoref_en, input[27:0] autoref_interval, input autoref_ack, output autoref_req ); /*** MAINTENANCE CONTROLLER ***/ wire maint_prescaler_tick; maint_ctrl #(.TCQ(TCQ), .tCK(tCK), .nCK_PER_CLK(nCK_PER_CLK), .MAINT_PRESCALER_PERIOD(MAINT_PRESCALER_PERIOD)) i_maint_ctrl( .clk(clk), .rst(rst), .dfi_init_complete(dfi_init_complete), .maint_prescaler_tick(maint_prescaler_tick) ); /*** PERIODIC READ CONTROLLER ***/ periodic_rd_ctrl #(.tCK(tCK), .nCK_PER_CLK(nCK_PER_CLK), .TCQ(TCQ), .MAINT_PRESCALER_PERIOD(MAINT_PRESCALER_PERIOD)) i_prrd_ctrl( .clk(clk), .rst(rst), .maint_prescaler_tick(maint_prescaler_tick), .dfi_init_complete(dfi_init_complete), .periodic_rd_ack(periodic_rd_ack), .periodic_rd_req(periodic_rd_req) ); /*** ZQ CALIBRATION CONTROLLER ***/ zq_calib_ctrl #(.TCQ(TCQ), .MAINT_PRESCALER_PERIOD(MAINT_PRESCALER_PERIOD)) i_zq_calib_ctrl( .clk(clk), .rst(rst), .maint_prescaler_tick(maint_prescaler_tick), .dfi_init_complete(dfi_init_complete), .zq_ack(zq_ack), .zq_request(zq_req) ); autoref_ctrl #(.TCQ(TCQ)) i_autoref_ctrl ( .clk(clk), .rst(rst), .autoref_en(autoref_en), .autoref_interval(autoref_interval), .maint_prescaler_tick(maint_prescaler_tick), .dfi_init_complete(dfi_init_complete), .autoref_ack(autoref_ack), .autoref_req(autoref_req) ); endmodule module maint_ctrl #(parameter TCQ = 100, tCK = 2500, nCK_PER_CLK = 2, MAINT_PRESCALER_PERIOD = 200000) ( input clk, input rst, input dfi_init_complete, output maint_prescaler_tick ); function integer clogb2 (input integer size); // ceiling logb2 begin size = size - 1; for (clogb2=1; size>1; clogb2=clogb2+1) size = size >> 1; end endfunction // clogb2 localparam MAINT_PRESCALER_DIV = MAINT_PRESCALER_PERIOD/(tCK * nCK_PER_CLK); // Round down. localparam MAINT_PRESCALER_WIDTH = clogb2(MAINT_PRESCALER_DIV + 1); localparam ONE = 1; // Maintenance and periodic read prescaler. Nominally 200 nS. reg maint_prescaler_tick_r_lcl; reg [MAINT_PRESCALER_WIDTH-1:0] maint_prescaler_r; reg [MAINT_PRESCALER_WIDTH-1:0] maint_prescaler_ns; wire maint_prescaler_tick_ns = (maint_prescaler_r == ONE[MAINT_PRESCALER_WIDTH-1:0]); always @(/*AS*/dfi_init_complete or maint_prescaler_r or maint_prescaler_tick_ns) begin maint_prescaler_ns = maint_prescaler_r; if (~dfi_init_complete || maint_prescaler_tick_ns) maint_prescaler_ns = MAINT_PRESCALER_DIV[MAINT_PRESCALER_WIDTH-1:0]; else if (|maint_prescaler_r) maint_prescaler_ns = maint_prescaler_r - ONE[MAINT_PRESCALER_WIDTH-1:0]; end always @(posedge clk) maint_prescaler_r <= #TCQ maint_prescaler_ns; always @(posedge clk) maint_prescaler_tick_r_lcl <= #TCQ maint_prescaler_tick_ns; assign maint_prescaler_tick = maint_prescaler_tick_r_lcl; endmodule //NOTE: this module is designed for 1 rank systems module periodic_rd_ctrl #(parameter tCK = 2500, nCK_PER_CLK = 2, TCQ = 100, MAINT_PRESCALER_PERIOD = 200000) ( input clk, input rst, input dfi_init_complete, input maint_prescaler_tick, input periodic_rd_ack, //NOTE: this also should be asserted for regular reads output periodic_rd_req ); function integer clogb2 (input integer size); // ceiling logb2 begin size = size - 1; for (clogb2=1; size>1; clogb2=clogb2+1) size = size >> 1; end endfunction // clogb2 localparam tPRDI = 1_000_000; localparam PERIODIC_RD_TIMER_DIV = tPRDI/MAINT_PRESCALER_PERIOD; localparam PERIODIC_RD_TIMER_WIDTH = clogb2(PERIODIC_RD_TIMER_DIV + /*idle state*/ 1); localparam ONE = 1; reg [PERIODIC_RD_TIMER_WIDTH-1:0] periodic_rd_timer_r, periodic_rd_timer; reg periodic_rd_request_r; always @* begin periodic_rd_timer = periodic_rd_timer_r; if(~dfi_init_complete) begin periodic_rd_timer = {PERIODIC_RD_TIMER_WIDTH{1'b0}}; end else if (periodic_rd_ack) begin periodic_rd_timer = PERIODIC_RD_TIMER_DIV[0+:PERIODIC_RD_TIMER_WIDTH]; end else if (|periodic_rd_timer_r && maint_prescaler_tick) begin periodic_rd_timer = periodic_rd_timer_r - ONE[0+:PERIODIC_RD_TIMER_WIDTH]; end end //always wire periodic_rd_timer_one = maint_prescaler_tick && (periodic_rd_timer_r == ONE[0+:PERIODIC_RD_TIMER_WIDTH]); wire periodic_rd_request = ~rst && (/*((PERIODIC_RD_TIMER_DIV != 0) && ~dfi_init_complete) ||*/ (~periodic_rd_ack && (periodic_rd_request_r || periodic_rd_timer_one))); always @(posedge clk) begin periodic_rd_timer_r <= #TCQ periodic_rd_timer; periodic_rd_request_r <= #TCQ periodic_rd_request; end //always assign periodic_rd_req = periodic_rd_request_r; endmodule module zq_calib_ctrl #(parameter TCQ = 100, MAINT_PRESCALER_PERIOD = 200000) ( input clk, input rst, input zq_ack, output reg zq_request, input dfi_init_complete, input maint_prescaler_tick ); function integer clogb2 (input integer size); // ceiling logb2 begin size = size - 1; for (clogb2=1; size>1; clogb2=clogb2+1) size = size >> 1; end endfunction // clogb2 // ZQ timebase. Nominally 128 mS localparam MAINT_PRESCALER_PERIOD_NS = MAINT_PRESCALER_PERIOD / 1000; localparam tZQI = 128_000_000; localparam ZQ_TIMER_DIV = tZQI/MAINT_PRESCALER_PERIOD_NS; localparam ZQ_TIMER_WIDTH = clogb2(ZQ_TIMER_DIV + 1); localparam ONE = 1; generate begin : zq_cntrl reg zq_tick = 1'b0; if (ZQ_TIMER_DIV !=0) begin : zq_timer reg [ZQ_TIMER_WIDTH-1:0] zq_timer_r; reg [ZQ_TIMER_WIDTH-1:0] zq_timer_ns; always @(/*AS*/dfi_init_complete or maint_prescaler_tick or zq_tick or zq_timer_r) begin zq_timer_ns = zq_timer_r; if (~dfi_init_complete || zq_tick) zq_timer_ns = ZQ_TIMER_DIV[ZQ_TIMER_WIDTH-1:0]; else if (|zq_timer_r && maint_prescaler_tick) zq_timer_ns = zq_timer_r - ONE[ZQ_TIMER_WIDTH-1:0]; end always @(posedge clk) zq_timer_r <= #TCQ zq_timer_ns; always @(/*AS*/maint_prescaler_tick or zq_timer_r) zq_tick = (zq_timer_r == ONE[ZQ_TIMER_WIDTH-1:0] && maint_prescaler_tick); end // zq_timer // ZQ request. Set request with timer tick, and when exiting PHY init. Never // request if ZQ_TIMER_DIV == 0. begin : zq_request_logic wire zq_clears_zq_request = zq_ack; reg zq_request_r; wire zq_request_ns = ~rst && ((~dfi_init_complete && (ZQ_TIMER_DIV != 0)) || (zq_request_r && ~zq_clears_zq_request) || zq_tick); always @(posedge clk) zq_request_r <= #TCQ zq_request_ns; always @(/*AS*/dfi_init_complete or zq_request_r) zq_request = dfi_init_complete && zq_request_r; end // zq_request_logic end endgenerate endmodule module autoref_ctrl #(parameter TCQ = 100) ( input clk, input rst, input autoref_en, input[27:0] autoref_interval, input autoref_ack, output autoref_req, input dfi_init_complete, input maint_prescaler_tick ); localparam ONE = 1; reg [27:0] autoref_timer_r, autoref_timer; reg autoref_request_r; reg ref_en_r; always @* begin autoref_timer = autoref_timer_r; if(~dfi_init_complete || autoref_ack || (~ref_en_r && autoref_en)) begin autoref_timer = autoref_interval; end else if (|autoref_timer_r && maint_prescaler_tick) begin autoref_timer = autoref_timer_r - ONE[0+:28]; end end //always wire autoref_timer_one = maint_prescaler_tick && (autoref_timer_r == ONE[0+:28]); wire autoref_request = ~rst && dfi_init_complete && autoref_en && ( (~autoref_ack && (autoref_request_r || autoref_timer_one))); always @(posedge clk) begin autoref_timer_r <= #TCQ autoref_timer; autoref_request_r <= #TCQ autoref_request; ref_en_r <= #TCQ autoref_en; end //always assign autoref_req = autoref_request_r; endmodule ================================================ FILE: hw/boards/ML605/maint_handler.v ================================================ `timescale 1ps / 1ps `include "softMC.inc" module maint_handler #(parameter CS_WIDTH = 1)( input clk, input rst, input pr_rd_req, input zq_req, input autoref_req, input[1:0] cur_bus_dir, output maint_instr_en, input maint_ack, output reg[31:0] maint_instr, input pr_rd_ack, //comes from the instruction sequence (iseq) dispatcher output reg zq_ack, output reg autoref_ack, output periodic_read_lock, input[27:0] trfc ); localparam HIGH = 1'b1; localparam LOW = 1'b0; //maintenance logic reg pr_rd_process_ns, pr_rd_process_r = 1'b0; reg zq_process_ns, zq_process_r = 1'b0; reg autoref_process_ns, autoref_process_r = 1'b0; wire maint_process; localparam PR_RD_IO = 4'b0000; localparam PR_RD_PRE = 4'b0001; localparam PR_RD_WAIT_PRE = 4'b0010; localparam PR_RD_ACT = 4'b0011; localparam PR_RD_WAIT_ACT = 4'b0100; localparam PR_RD_READ = 4'b0101; localparam PR_RD_WAIT_READ = 4'b0110; localparam PR_RD_PRE2 = 4'b0111; localparam PR_RD_WAIT_PRE2 = 4'b1000; localparam PR_RD_WR_IO = 4'b1001; localparam MAINT_FIN = 4'b1010; localparam ZQ_PRE = 4'b0000; localparam ZQ_WAIT_PRE = 4'b0001; localparam ZQ_ZQ = 4'b0010; localparam ZQ_WAIT_ZQ = 4'b0011; localparam AREF_PRE = 4'b0000; localparam AREF_WAIT_PRE = 4'b0001; localparam AREF_REF = 4'b0010; localparam AREF_WAIT_REF = 4'b0011; reg[3:0] maint_state, maint_state_ns; reg lock_pr_rd_r, lock_pr_rd_ns; reg[1:0] cur_bus_dir_r, cur_bus_dir_ns; always@* begin pr_rd_process_ns = pr_rd_process_r; zq_process_ns = zq_process_r; autoref_process_ns = autoref_process_r; lock_pr_rd_ns = lock_pr_rd_r; zq_ack = 1'b0; autoref_ack = 1'b0; maint_state_ns = maint_state; maint_instr = {`END_ISEQ, 28'd0}; cur_bus_dir_ns = cur_bus_dir_r; //enter maintenance if(~maint_process) begin if(pr_rd_req & ~lock_pr_rd_r) begin pr_rd_process_ns = 1'b1; maint_state_ns = PR_RD_IO; end //pr_rd_req else if(zq_req) begin zq_process_ns = 1'b1; maint_state_ns = ZQ_PRE; end //zq_req else if(autoref_req) begin autoref_process_ns = 1'b1; maint_state_ns = AREF_PRE; end end //~dispatcher_busy_r //process maintenance if(maint_process) begin if(pr_rd_process_r) begin //TODO: optimize to reduce periodic dummy read latency when open bank is available case(maint_state) PR_RD_IO: begin maint_instr[31:28] = `SET_BUSDIR; cur_bus_dir_ns = cur_bus_dir; if(maint_ack) maint_state_ns = PR_RD_PRE; end //PR_RD_IO PR_RD_PRE: begin //Precharge banks 0 maint_instr[31:28] = `DDR_INSTR; maint_instr[`CKE_OFFSET] = HIGH; maint_instr[`CS_OFFSET +: CS_WIDTH] = {{CS_WIDTH-1{HIGH}}, LOW}; maint_instr[`RAS_OFFSET] = LOW; maint_instr[`CAS_OFFSET] = HIGH; maint_instr[`WE_OFFSET] = LOW; maint_instr[10] = LOW; //10th bit of the address field, A[10] if(maint_ack) maint_state_ns = PR_RD_WAIT_PRE; end PR_RD_WAIT_PRE: begin maint_instr[31:28] = `WAIT; maint_instr[27:0] = `DEF_TRP; if(maint_ack) maint_state_ns = PR_RD_ACT; end //PR_RD_WAIT_PRE PR_RD_ACT: begin //activate bank 0, row 0 maint_instr[31:28] = `DDR_INSTR; maint_instr[`CKE_OFFSET] = HIGH; maint_instr[`CS_OFFSET +: CS_WIDTH] = {{CS_WIDTH-1{HIGH}}, LOW}; maint_instr[`RAS_OFFSET] = LOW; maint_instr[`CAS_OFFSET] = HIGH; maint_instr[`WE_OFFSET] = HIGH; if(maint_ack) maint_state_ns = PR_RD_WAIT_ACT; end //PR_RD_ACT PR_RD_WAIT_ACT: begin maint_instr[31:28] = `WAIT; maint_instr[27:0] = `DEF_TRCD; if(maint_ack) maint_state_ns = PR_RD_READ; end //PR_RD_WAIT_ACT PR_RD_READ: begin //Read instruction maint_instr[31:28] = `DDR_INSTR; maint_instr[`CKE_OFFSET] = HIGH; maint_instr[`CS_OFFSET +: CS_WIDTH] = {{CS_WIDTH-1{HIGH}}, LOW}; maint_instr[`RAS_OFFSET] = HIGH; maint_instr[`CAS_OFFSET] = LOW; maint_instr[`WE_OFFSET] = HIGH; if(maint_ack) maint_state_ns = PR_RD_WAIT_READ; end //PR_RD_READ PR_RD_WAIT_READ: begin maint_instr[31:28] = `WAIT; maint_instr[27:0] = `DEF_TRAS - `DEF_TRCD; if(maint_ack) maint_state_ns = PR_RD_PRE2; end //PR_RD_WAIT_READ PR_RD_PRE2: begin //Precharge banks 0 maint_instr[31:28] = `DDR_INSTR; maint_instr[`CKE_OFFSET] = HIGH; maint_instr[`CS_OFFSET +: CS_WIDTH] = {{CS_WIDTH-1{HIGH}}, LOW}; maint_instr[`RAS_OFFSET] = LOW; maint_instr[`CAS_OFFSET] = HIGH; maint_instr[`WE_OFFSET] = LOW; maint_instr[10] = LOW; //10th bit of the address field, A[10] if(maint_ack) maint_state_ns = PR_RD_WAIT_PRE2; end //PR_RD_PRE2 PR_RD_WAIT_PRE2: begin maint_instr[31:28] = `WAIT; maint_instr[27:0] = `DEF_TRP; if(maint_ack) maint_state_ns = (cur_bus_dir_r == `BUS_DIR_READ) ? MAINT_FIN : PR_RD_WR_IO; end //PR_RD_WAIT_PRE2 PR_RD_WR_IO: begin maint_instr[31:28] = `SET_BUSDIR; maint_instr[1:0] = `BUS_DIR_WRITE; if(maint_ack) maint_state_ns = MAINT_FIN; end MAINT_FIN: begin maint_instr[31:28] = `END_ISEQ; pr_rd_process_ns = 1'b0; lock_pr_rd_ns = 1'b1; end //MAINT_FIN endcase //pr_rd_state end //pr_rd_process_r else if(zq_process_r) begin case(maint_state) ZQ_PRE: begin //Precharge all banks maint_instr[31:28] = `DDR_INSTR; maint_instr[`CKE_OFFSET] = HIGH; maint_instr[`CS_OFFSET +: CS_WIDTH] = {{CS_WIDTH-1{HIGH}}, LOW}; maint_instr[`RAS_OFFSET] = LOW; maint_instr[`CAS_OFFSET] = HIGH; maint_instr[`WE_OFFSET] = LOW; maint_instr[10] = HIGH; //10th bit of the address field, A[10] if(maint_ack) maint_state_ns = ZQ_WAIT_PRE; end //ZQ_INIT ZQ_WAIT_PRE: begin maint_instr[31:28] = `WAIT; maint_instr[27:0] = `DEF_TRP; if(maint_ack) maint_state_ns = ZQ_ZQ; end //ZQ_WAIT_PRE ZQ_ZQ: begin //ZQ-Short Instruction maint_instr[31:28] = `DDR_INSTR; maint_instr[`CKE_OFFSET] = HIGH; maint_instr[`CS_OFFSET +: CS_WIDTH] = {{CS_WIDTH-1{HIGH}}, LOW}; maint_instr[`RAS_OFFSET] = HIGH; maint_instr[`CAS_OFFSET] = HIGH; maint_instr[`WE_OFFSET] = LOW; maint_instr[10] = LOW; //10th bit of the address field, A[10] if(maint_ack) maint_state_ns = ZQ_WAIT_ZQ; end //ZQ_ZQ ZQ_WAIT_ZQ: begin maint_instr[31:28] = `WAIT; maint_instr[27:0] = `DEF_TZQCS; if(maint_ack) maint_state_ns = MAINT_FIN; end //ZQ_WAIT_ZQ MAINT_FIN: begin maint_instr[31:28] = `END_ISEQ; zq_process_ns = 1'b0; zq_ack = 1'b1; end //MAINT_FIN endcase //maint_state end //zq_process_r else if(autoref_process_r) begin case(maint_state) AREF_PRE: begin //Precharge all banks maint_instr[31:28] = `DDR_INSTR; maint_instr[`CKE_OFFSET] = HIGH; maint_instr[`CS_OFFSET +: CS_WIDTH] = {{CS_WIDTH-1{HIGH}}, LOW}; maint_instr[`RAS_OFFSET] = LOW; maint_instr[`CAS_OFFSET] = HIGH; maint_instr[`WE_OFFSET] = LOW; maint_instr[10] = HIGH; //10th bit of the address field, A[10] if(maint_ack) maint_state_ns = AREF_WAIT_PRE; end //AREF_PRE AREF_WAIT_PRE: begin maint_instr[31:28] = `WAIT; maint_instr[27:0] = `DEF_TRP; if(maint_ack) maint_state_ns = AREF_REF; end //AREF_WAIT_PRE AREF_REF: begin //Refresh Instruction //TODO: assign CS appropriately when implementing multi-rank support maint_instr[31:28] = `DDR_INSTR; maint_instr[`CKE_OFFSET] = HIGH; maint_instr[`CS_OFFSET +: CS_WIDTH] = {{CS_WIDTH-1{HIGH}}, LOW}; maint_instr[`RAS_OFFSET] = LOW; maint_instr[`CAS_OFFSET] = LOW; maint_instr[`WE_OFFSET] = HIGH; maint_instr[10] = HIGH; //10th bit of the address field, A[10] if(maint_ack) maint_state_ns = AREF_WAIT_REF; end //AREF_REF AREF_WAIT_REF: begin maint_instr[31:28] = `WAIT; maint_instr[27:0] = trfc; if(maint_ack) maint_state_ns = MAINT_FIN; end //AREF_WAIT_REF MAINT_FIN: begin maint_instr[31:28] = `END_ISEQ; autoref_process_ns = 1'b0; autoref_ack = 1'b1; end //MAINT_FIN endcase //maint_state end //autoref_process_r end //maint_process if(pr_rd_ack) begin lock_pr_rd_ns = 1'b0; pr_rd_process_ns = 1'b0; end end //always maintenance assign periodic_read_lock = lock_pr_rd_r; always@(posedge clk) begin if(rst) begin lock_pr_rd_r <= 1'b0; maint_state <= 4'd0; cur_bus_dir_r <= `BUS_DIR_READ; end else begin lock_pr_rd_r <= lock_pr_rd_ns; maint_state <= maint_state_ns; cur_bus_dir_r <= cur_bus_dir_ns; end end assign maint_process = pr_rd_process_r | zq_process_r | autoref_process_r; assign maint_instr_en = maint_process; always@(posedge clk) begin pr_rd_process_r <= pr_rd_process_ns; zq_process_r <= zq_process_ns; autoref_process_r <= autoref_process_ns; end endmodule ================================================ FILE: hw/boards/ML605/patches/iodelay_ctrl.patch ================================================ --- ipcore_dir/xilinx_mig/user_design/rtl/ip_top/iodelay_ctrl.v @@ -94,1 +94,2 @@ input sys_rst, + output clk_200, // single 200MHz clock for ML605 @@ -161,1 +162,2 @@ ); + assign clk_200 = clk_ref_bufg; // ML605 single 200MHz clock source ================================================ FILE: hw/boards/ML605/patches/phy_rdctrl_sync.patch ================================================ --- ipcore_dir/xilinx_mig/user_design/rtl/phy/phy_rdctrl_sync.v 2017-02-03 15:11:19.000000000 +0100 @@ -91,4 +91,8 @@ input dfi_rddata_en, + input dfi_rddata_en_even, + input dfi_rddata_en_odd, input phy_rddata_en, // Control for read logic, initialization logic output reg dfi_rddata_valid, + output reg dfi_rddata_valid_even, + output reg dfi_rddata_valid_odd, @@ -113,3 +117,7 @@ wire rddata_en; + wire rddata_en_even; + wire rddata_en_odd; wire rddata_en_rsync; wire rddata_en_srl_out; + wire rddata_en_srl_out_even; + wire rddata_en_srl_out_odd; @@ -124,1 +132,3 @@ assign rddata_en = (mc_data_sel) ? dfi_rddata_en : phy_rddata_en; + assign rddata_en_even = (mc_data_sel) ? dfi_rddata_en_even : phy_rddata_en; + assign rddata_en_odd = (mc_data_sel) ? dfi_rddata_en_odd : phy_rddata_en; @@ -136,1 +146,21 @@ + SRLC32E u_rddata_en_srl_even + ( + .Q (rddata_en_srl_out_even), + .Q31 (), + .A (rd_active_dly), + .CE (1'b1), + .CLK (clk), + .D (rddata_en_even) + ); + + SRLC32E u_rddata_en_srl_odd + ( + .Q (rddata_en_srl_out_odd), + .Q31 (), + .A (rd_active_dly), + .CE (1'b1), + .CLK (clk), + .D (rddata_en_odd) + ); + @@ -140,1 +170,3 @@ dfi_rddata_valid <= #TCQ rddata_en_srl_out & mc_data_sel; + dfi_rddata_valid_even <= #TCQ rddata_en_srl_out_even & mc_data_sel; + dfi_rddata_valid_odd <= #TCQ rddata_en_srl_out_odd & mc_data_sel; ================================================ FILE: hw/boards/ML605/patches/phy_read.patch ================================================ --- ipcore_dir/xilinx_mig/user_design/rtl/phy/phy_read.v 2017-02-03 15:11:19.000000000 +0100 @@ -129,4 +129,8 @@ input dfi_rddata_en, + input dfi_rddata_en_even, + input dfi_rddata_en_odd, input phy_rddata_en, // Synchronized data/valid back to MC/PHY rdlvl logic output dfi_rddata_valid, + output dfi_rddata_valid_even, + output dfi_rddata_valid_odd, @@ -199,3 +203,7 @@ .dfi_rddata_en (dfi_rddata_en), + .dfi_rddata_en_even (dfi_rddata_en_even), + .dfi_rddata_en_odd (dfi_rddata_en_odd), .phy_rddata_en (phy_rddata_en), .dfi_rddata_valid (dfi_rddata_valid), + .dfi_rddata_valid_even(dfi_rddata_valid_even), + .dfi_rddata_valid_odd (dfi_rddata_valid_odd), ================================================ FILE: hw/boards/ML605/patches/phy_top.patch ================================================ --- ipcore_dir/xilinx_mig/user_design/rtl/phy/phy_top.v 2017-02-03 15:11:19.000000000 +0100 @@ -93,1 +93,1 @@ - parameter BANK_WIDTH = 2, // # of bank bits + parameter BANK_WIDTH = 3, // # of bank bits @@ -103,1 +103,1 @@ - parameter ROW_WIDTH = 14, // DRAM address bus width + parameter ROW_WIDTH = 16, // DRAM address bus width @@ -124,1 +124,1 @@ - parameter REG_CTRL = "ON", // "ON" for registered DIMM + parameter REG_CTRL = "OFF", // "ON" for registered DIMM @@ -194,3 +194,7 @@ input dfi_rddata_en, + input dfi_rddata_en_even, + input dfi_rddata_en_odd, output [4*DQ_WIDTH-1:0] dfi_rddata, output dfi_rddata_valid, + output dfi_rddata_valid_even, + output dfi_rddata_valid_odd, @@ -1100,3 +1104,7 @@ .dfi_rddata_en (dfi_rddata_en), + .dfi_rddata_en_even (dfi_rddata_en_even), + .dfi_rddata_en_odd (dfi_rddata_en_odd), .phy_rddata_en (phy_rddata_en), .dfi_rddata_valid (dfi_rddata_valid), + .dfi_rddata_valid_even(dfi_rddata_valid_even), + .dfi_rddata_valid_odd (dfi_rddata_valid_odd), ================================================ FILE: hw/boards/ML605/pipe_reg.v ================================================ `timescale 1ps / 1ps module pipe_reg #(parameter WIDTH = 8) ( input clk, input rst, input ready_in, input valid_in, input[WIDTH - 1:0] data_in, output valid_out, output[WIDTH - 1:0] data_out, output ready_out ); (* keep = "true" *) reg r_ready, r_valid1, r_valid2; (* keep = "true" *) reg[WIDTH - 1:0] r_data1, r_data2; wire first_buf_ready = ready_in | ~r_valid1; assign data_out = r_data1; assign valid_out = r_valid1; assign ready_out = r_ready; always@(posedge clk) begin if(rst) begin r_data1 <= 0; r_data2 <= 0; r_ready <= 0; r_valid1 <= 0; r_valid2 <= 0; end else begin //data acquisition if(r_ready) begin if(first_buf_ready) begin r_data1 <= data_in; r_valid1 <= valid_in; end else begin r_data2 <= data_in; r_valid2 <= valid_in; end end //r_ready //data shift if(~r_ready & ready_in) begin r_data1 <= r_data2; r_valid1 <= r_valid2; end end //control r_ready <= first_buf_ready; end endmodule ================================================ FILE: hw/boards/ML605/read_capturer.v ================================================ `timescale 1ns / 1ps module read_capturer #(parameter DQ_WIDTH = 64) ( input clk, input rst, //DFI Interface input [4*DQ_WIDTH-1:0] dfi_rddata, input dfi_rddata_valid, input dfi_rddata_valid_even, input dfi_rddata_valid_odd, output dfi_clk_disable, //FIFO interface input rdback_fifo_almost_full, input rdback_fifo_full, output rdback_fifo_wren, output[4*DQ_WIDTH-1:0] rdback_fifo_wrdata ); reg[4*DQ_WIDTH-1:0] rd_data_r, rd_data_r2; reg rd_data_en_r, rd_data_en_even_r, rd_data_en_odd_r; reg rdback_fifo_full_r; always@(posedge clk) begin if(rst) begin rd_data_r <= 0; rd_data_r2 <= 0; rd_data_en_r <= 0; rd_data_en_even_r <= 0; rd_data_en_odd_r <= 0; rdback_fifo_full_r <= 0; end else begin rd_data_r <= dfi_rddata; rd_data_r2 <= rd_data_r; rd_data_en_r <= dfi_rddata_valid; rd_data_en_even_r <= dfi_rddata_valid_even; rd_data_en_odd_r <= dfi_rddata_valid_odd; rdback_fifo_full_r <= rdback_fifo_almost_full | rdback_fifo_full; end end assign rdback_fifo_wren = ~rd_data_en_odd_r & rd_data_en_r; assign rdback_fifo_wrdata = rd_data_en_even_r ? {rd_data_r[DQ_WIDTH*2 - 1:0], rd_data_r2[DQ_WIDTH*2 +: DQ_WIDTH*2]} : rd_data_r; assign dfi_clk_disable = rdback_fifo_full_r; endmodule ================================================ FILE: hw/boards/ML605/softMC.inc ================================================ //uncomment the line below to run a simulation using "tb_softMC_top" //`define SIM `define tCK 2500 // instruction opcodes `define DDR_INSTR 4'b1xxx `define END_ISEQ 4'b0000 `define SET_BUSDIR 4'b0001 `define SET_TREFI 4'b0010 `define SET_TRFC 4'b0011 `define WAIT 4'b0100 `define ROW_OFFSET 16 `define WE_OFFSET 19 `define CAS_OFFSET 20 `define RAS_OFFSET 21 `define CS_OFFSET 22 `define CKE_OFFSET 24 `define BUS_DIR_READ 2'b00 `define BUS_DIR_WRITE 2'b10 //Set accordingly to tCK, (6, 6, 14 if tCK = 2500ps) `define DEF_TRP 15000/`tCK `define DEF_TRCD 15000/`tCK `define DEF_TRAS 35000/`tCK `define DEF_TZQCS 64 //mem_clk cycles ================================================ FILE: hw/boards/ML605/softMC.v ================================================ `timescale 1ps / 1ps `include "softMC.inc" //NOTE: currently accepts only one instruction sequence, need to process it first to receive another module softMC #(parameter TCQ = 100, tCK = 2500, nCK_PER_CLK = 2, RANK_WIDTH = 1, ROW_WIDTH = 15, BANK_WIDTH = 3, CKE_WIDTH = 1, CS_WIDTH = 1, nCS_PER_RANK = 1, DQ_WIDTH = 64) ( input clk, input rst, //App Command Interface input app_en, output app_ack, input[31:0] app_instr, output iq_full, output processing_iseq, // DFI Control/Address output [ROW_WIDTH-1:0] dfi_address0, output [ROW_WIDTH-1:0] dfi_address1, output [BANK_WIDTH-1:0] dfi_bank0, output [BANK_WIDTH-1:0] dfi_bank1, output dfi_cas_n0, output dfi_cas_n1, output [CKE_WIDTH-1:0] dfi_cke0, output [CKE_WIDTH-1:0] dfi_cke1, output [CS_WIDTH*nCS_PER_RANK-1:0] dfi_cs_n0, output [CS_WIDTH*nCS_PER_RANK-1:0] dfi_cs_n1, output [CS_WIDTH*nCS_PER_RANK-1:0] dfi_odt0, output [CS_WIDTH*nCS_PER_RANK-1:0] dfi_odt1, output dfi_ras_n0, output dfi_ras_n1, output dfi_reset_n, output dfi_we_n0, output dfi_we_n1, // DFI Write output dfi_wrdata_en, output [4*DQ_WIDTH-1:0] dfi_wrdata, output [4*(DQ_WIDTH/8)-1:0] dfi_wrdata_mask, // DFI Read output dfi_rddata_en, output dfi_rddata_en_even, output dfi_rddata_en_odd, input [4*DQ_WIDTH-1:0] dfi_rddata, input dfi_rddata_valid, input dfi_rddata_valid_even, input dfi_rddata_valid_odd, // DFI Initialization Status / CLK Disable output dfi_dram_clk_disable, input dfi_init_complete, // sideband signals output io_config_strobe, output [RANK_WIDTH:0] io_config, //Data read back Interface output rdback_fifo_empty, input rdback_fifo_rden, output[DQ_WIDTH*4 - 1:0] rdback_data ); //DFI constants assign dfi_reset_n = 1; wire instr0_fifo_en, instr0_fifo_full, instr0_fifo_empty; wire[31:0] instr0_fifo_data, instr0_fifo_out; wire instr0_fifo_rd_en; wire instr1_fifo_en, instr1_fifo_full, instr1_fifo_empty; wire[31:0] instr1_fifo_data, instr1_fifo_out; wire instr1_fifo_rd_en; wire process_iseq; //MAINTENANCE module localparam MAINT_PRESCALER_PERIOD = 200000; wire pr_rd_req, zq_req, autoref_req; wire pr_rd_ack, zq_ack, autoref_ack; //Auto-refresh signals wire aref_en; wire[27:0] aref_interval; wire[27:0] aref_trfc; wire aref_set_interval, aref_set_trfc; wire[27:0] aref_interval_in; wire[27:0] aref_trfc_in; maint_ctrl_top #(.RANK_WIDTH(RANK_WIDTH), .TCQ (TCQ), .tCK(tCK), .nCK_PER_CLK(nCK_PER_CLK), .MAINT_PRESCALER_PERIOD(MAINT_PRESCALER_PERIOD)) i_maint_ctrl( .clk(clk), .rst(rst), .dfi_init_complete(dfi_init_complete), .periodic_rd_ack(pr_rd_ack), .periodic_rd_req(pr_rd_req), .zq_ack(zq_ack), .zq_req(zq_req), //Auto-refresh .autoref_en(aref_en), .autoref_interval(aref_interval), .autoref_ack(autoref_ack), .autoref_req(autoref_req) ); wire periodic_read_lock; wire maint_en; wire maint_ack; wire[31:0] maint_instr; maint_handler #(.CS_WIDTH(CS_WIDTH)) i_maint_handler( .clk(clk), .rst(rst), .pr_rd_req(pr_rd_req), .zq_req(zq_req), .autoref_req(autoref_req), .cur_bus_dir(dfi_odt0 ? `BUS_DIR_WRITE : `BUS_DIR_READ), .maint_instr_en(maint_en), .maint_ack(maint_ack), .maint_instr(maint_instr), .pr_rd_ack(pr_rd_ack), //comes from the transaction dispatcher .zq_ack(zq_ack), .autoref_ack(autoref_ack), .periodic_read_lock(periodic_read_lock), .trfc(aref_trfc) ); autoref_config i_aref_config( .clk(clk), .rst(rst), .set_interval(aref_set_interval), .interval_in(aref_interval_in), .set_trfc(aref_set_trfc), .trfc_in(aref_trfc_in), .aref_en(aref_en), .aref_interval(aref_interval), .trfc(aref_trfc) ); instr_receiver i_instr_recv( .clk(clk), .rst(rst), .dispatcher_ready(~dispatcher_busy), .app_en(app_en), .app_ack(app_ack), .app_instr(app_instr), .maint_en(maint_en), .maint_ack(maint_ack), .maint_instr(maint_instr), .instr0_fifo_en(instr0_fifo_en), .instr0_fifo_data(instr0_fifo_data), .instr1_fifo_en(instr1_fifo_en), .instr1_fifo_data(instr1_fifo_data), .process_iseq(process_iseq) ); instr_fifo i_instr0_fifo ( .srst(rst), // input rst .clk(clk), // input clk .din(instr0_fifo_data), // input [31 : 0] din .wr_en(instr0_fifo_en), // input wr_en .rd_en(instr0_fifo_rd_en), // input rd_en .dout(instr0_fifo_out), // output [31 : 0] dout .full(instr0_fifo_full), // output full .empty(instr0_fifo_empty) // output empty ); instr_fifo i_instr1_fifo ( .srst(rst), // input rst .clk(clk), // input clk .din(instr1_fifo_data), // input [31 : 0] din .wr_en(instr1_fifo_en), // input wr_en .rd_en(instr1_fifo_rd_en), // input rd_en .dout(instr1_fifo_out), // output [31 : 0] dout .full(instr1_fifo_full), // output full .empty(instr1_fifo_empty) // output empty ); wire dfi_ready; iseq_dispatcher #(.ROW_WIDTH(ROW_WIDTH), .BANK_WIDTH(BANK_WIDTH), .CKE_WIDTH(CKE_WIDTH), .CS_WIDTH(CS_WIDTH), .nCS_PER_RANK(nCS_PER_RANK), .DQ_WIDTH(DQ_WIDTH)) i_iseq_disp ( .clk(clk), .rst(rst), .periodic_read_lock(periodic_read_lock), .process_iseq(process_iseq), .dispatcher_busy(dispatcher_busy), .instr0_fifo_rd(instr0_fifo_rd_en), .instr0_fifo_empty(instr0_fifo_empty), .instr0_fifo_data(instr0_fifo_out), .instr1_fifo_rd(instr1_fifo_rd_en), .instr1_fifo_empty(instr1_fifo_empty), .instr1_fifo_data(instr1_fifo_out), //DFI Interface .dfi_ready(dfi_ready), .dfi_init_complete(dfi_init_complete), .dfi_address0(dfi_address0), .dfi_address1(dfi_address1), .dfi_bank0(dfi_bank0), .dfi_bank1(dfi_bank1), .dfi_cke0(dfi_cke0), .dfi_cke1(dfi_cke1), .dfi_cas_n0(dfi_cas_n0), .dfi_cas_n1(dfi_cas_n1), .dfi_cs_n0(dfi_cs_n0), .dfi_cs_n1(dfi_cs_n1), .dfi_odt0(dfi_odt0), .dfi_odt1(dfi_odt1), .dfi_ras_n0(dfi_ras_n0), .dfi_ras_n1(dfi_ras_n1), .dfi_we_n0(dfi_we_n0), .dfi_we_n1(dfi_we_n1), .dfi_wrdata_en(dfi_wrdata_en), .dfi_wrdata(dfi_wrdata), .dfi_wrdata_mask(dfi_wrdata_mask), .dfi_rddata_en(dfi_rddata_en), .dfi_rddata_en_even(dfi_rddata_en_even), .dfi_rddata_en_odd(dfi_rddata_en_odd), .io_config_strobe(io_config_strobe), .io_config(io_config), .pr_rd_ack(pr_rd_ack), //auto-refresh .aref_set_interval(aref_set_interval), .aref_interval(aref_interval_in), .aref_set_trfc(aref_set_trfc), .aref_trfc(aref_trfc_in) ); assign iq_full = instr0_fifo_full | instr1_fifo_full; assign processing_iseq = dispatcher_busy; wire[DQ_WIDTH*4 - 1: 0] rdback_fifo_wrdata, rdback_fifo_out; wire rdback_fifo_full, rdback_fifo_almost_full; wire rdback_fifo_wren; rdback_fifo i_rdback_fifo ( .clk(clk), // input clk .srst(rst), // input srst .din(rdback_fifo_wrdata), // input [255 : 0] din .wr_en(rdback_fifo_wren), // input wr_en .rd_en(rdback_fifo_rden), // input rd_en .dout(rdback_fifo_out), // output [255 : 0] dout .full(rdback_fifo_full), // output full .almost_full(rdback_fifo_almost_full), .empty(rdback_fifo_empty) // output empty ); assign rdback_data = rdback_fifo_out; wire read_capturer_dfi_clk_disable; read_capturer #(.DQ_WIDTH(DQ_WIDTH)) i_rd_capturer ( .clk(clk), .rst(rst), //DFI Interface .dfi_rddata(dfi_rddata), .dfi_rddata_valid(dfi_rddata_valid), .dfi_rddata_valid_even(dfi_rddata_valid_even), .dfi_rddata_valid_odd(dfi_rddata_valid_odd), .dfi_clk_disable(read_capturer_dfi_clk_disable), //FIFO interface .rdback_fifo_full(rdback_fifo_full), .rdback_fifo_almost_full(rdback_fifo_almost_full), .rdback_fifo_wren(rdback_fifo_wren), .rdback_fifo_wrdata(rdback_fifo_wrdata) ); assign dfi_dram_clk_disable = read_capturer_dfi_clk_disable; assign dfi_ready = ~dfi_dram_clk_disable; endmodule ================================================ FILE: hw/boards/ML605/softMC_constraints.ucf ================================================ ############################################################################ # Timing constraints # # Most of these were inherited from the constraint file which is generated # # after configuring Xilinx MIG IPCore # ############################################################################ #NET "sys_clk_p" TNM_NET = TNM_sys_clk; #TIMESPEC "TS_sys_clk" = PERIOD "TNM_sys_clk" 2.5 ns; NET "clk_ref_p" TNM_NET = "TNM_clk_ref"; TIMESPEC TS_clk_ref = PERIOD "TNM_clk_ref" 5 ns; # Constrain BUFR clocks used to synchronize data from IOB to fabric logic # Note that ISE cannot infer this from other PERIOD constraints because # of the use of OSERDES blocks in the BUFR clock generation path NET "xil_phy/clk_rsync[?]" TNM_NET = "TNM_clk_rsync"; TIMESPEC TS_clk_rsync = PERIOD "TNM_clk_rsync" 5 ns; # Paths between DQ/DQS ISERDES.Q outputs and CLB flops clocked by falling # edge of BUFR will by design only be used if DYNCLKDIVSEL is asserted for # that particular flop. Mark this path as being a full-cycle, rather than # a half cycle path for timing purposes. NOTE: This constraint forces full- # cycle timing to be applied globally for all rising->falling edge paths # in all resynchronizaton clock domains. If the user had modified the logic # in the resync clock domain such that other rising->falling edge paths # exist, then constraint below should be modified to utilize pattern # matching to specific affect only the DQ/DQS ISERDES.Q outputs TIMEGRP TG_clk_rsync_rise = RISING "TNM_clk_rsync"; TIMEGRP TG_clk_rsync_fall = FALLING "TNM_clk_rsync"; TIMESPEC TS_clk_rsync_rise_to_fall = FROM "TG_clk_rsync_rise" TO "TG_clk_rsync_fall" 5 ns; # Signal to select between controller and physical layer signals. Four divided by two clock # cycles (4 memory clock cycles) are provided by design for the signal to settle down. # Used only by the phy modules. INST "xil_phy/u_phy_init/u_ff_phy_init_data_sel" TNM = "TNM_PHY_INIT_SEL"; TIMESPEC TS_MC_PHY_INIT_SEL = FROM "TNM_PHY_INIT_SEL" TO FFS 10 ns; ############################################################################ ######################################################################## # Controller 0 # Memory Device: DDR3_SDRAM->SODIMMs->MT8JSF25664HZ-1G4 # Data Width: 64 # Frequency: 400 # Time Period: 2500 # Data Mask: 0 ######################################################################## ################################################################################ # I/O STANDARDS ################################################################################ NET "ddr_dq[0]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[10]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[11]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[12]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[13]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[14]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[15]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[16]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[17]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[18]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[19]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[1]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[20]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[21]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[22]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[23]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[24]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[25]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[26]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[27]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[28]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[29]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[2]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[30]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[31]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[32]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[33]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[34]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[35]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[36]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[37]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[38]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[39]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[3]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[40]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[41]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[42]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[43]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[44]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[45]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[46]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[47]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[48]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[49]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[4]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[50]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[51]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[52]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[53]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[54]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[55]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[56]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[57]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[58]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[59]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[5]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[60]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[61]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[62]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[63]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[6]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[7]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[8]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_dq[9]" IOSTANDARD = SSTL15_T_DCI; NET "ddr_addr[0]" IOSTANDARD = SSTL15; NET "ddr_addr[10]" IOSTANDARD = SSTL15; NET "ddr_addr[11]" IOSTANDARD = SSTL15; NET "ddr_addr[12]" IOSTANDARD = SSTL15; NET "ddr_addr[13]" IOSTANDARD = SSTL15; NET "ddr_addr[14]" IOSTANDARD = SSTL15; NET "ddr_addr[15]" IOSTANDARD = SSTL15; NET "ddr_addr[1]" IOSTANDARD = SSTL15; NET "ddr_addr[2]" IOSTANDARD = SSTL15; NET "ddr_addr[3]" IOSTANDARD = SSTL15; NET "ddr_addr[4]" IOSTANDARD = SSTL15; NET "ddr_addr[5]" IOSTANDARD = SSTL15; NET "ddr_addr[6]" IOSTANDARD = SSTL15; NET "ddr_addr[7]" IOSTANDARD = SSTL15; NET "ddr_addr[8]" IOSTANDARD = SSTL15; NET "ddr_addr[9]" IOSTANDARD = SSTL15; NET "ddr_ba[0]" IOSTANDARD = SSTL15; NET "ddr_ba[1]" IOSTANDARD = SSTL15; NET "ddr_ba[2]" IOSTANDARD = SSTL15; NET "ddr_ras_n" IOSTANDARD = SSTL15; NET "ddr_cas_n" IOSTANDARD = SSTL15; NET "ddr_we_n" IOSTANDARD = SSTL15; NET "ddr_reset_n" IOSTANDARD = SSTL15; NET "ddr_cke[0]" IOSTANDARD = SSTL15; NET "ddr_odt[0]" IOSTANDARD = SSTL15; NET "ddr_cs_n[0]" IOSTANDARD = SSTL15; #NET "sys_clk_p" IOSTANDARD = LVDS_25; #NET "sys_clk_n" IOSTANDARD = LVDS_25; NET "clk_ref_p" IOSTANDARD = LVDS_25; NET "clk_ref_n" IOSTANDARD = LVDS_25; #NET "sda" IOSTANDARD = LVCMOS25; #NET "scl" IOSTANDARD = LVCMOS25; NET "sys_rst" IOSTANDARD = SSTL15; #NET "dfi_init_complete" IOSTANDARD = LVCMOS25; NET "ddr_dqs_p[0]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_p[1]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_p[2]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_p[3]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_p[4]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_p[5]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_p[6]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_p[7]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_n[0]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_n[1]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_n[2]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_n[3]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_n[4]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_n[5]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_n[6]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_dqs_n[7]" IOSTANDARD = DIFF_SSTL15_T_DCI; NET "ddr_ck_p[0]" IOSTANDARD = DIFF_SSTL15; NET "ddr_ck_p[1]" IOSTANDARD = DIFF_SSTL15; NET "ddr_ck_n[0]" IOSTANDARD = DIFF_SSTL15; NET "ddr_ck_n[1]" IOSTANDARD = DIFF_SSTL15; NET "ddr_dm[0]" IOSTANDARD = SSTL15; NET "ddr_dm[1]" IOSTANDARD = SSTL15; NET "ddr_dm[2]" IOSTANDARD = SSTL15; NET "ddr_dm[3]" IOSTANDARD = SSTL15; NET "ddr_dm[4]" IOSTANDARD = SSTL15; NET "ddr_dm[5]" IOSTANDARD = SSTL15; NET "ddr_dm[6]" IOSTANDARD = SSTL15; NET "ddr_dm[7]" IOSTANDARD = SSTL15; ################################################################################ ##SAVE attributes to reserve the pins ################################################################################ #NET "sda" S; #NET "scl" S; CONFIG DCI_CASCADE = "26 25"; CONFIG DCI_CASCADE = "36 35"; ################################################################################## # Location Constraints ################################################################################## #Bank 26 NET "ddr_dq[0]" LOC = J11; #Bank 26 NET "ddr_dq[1]" LOC = E13; #Bank 26 NET "ddr_dq[2]" LOC = F13; #Bank 26 NET "ddr_dq[3]" LOC = K11; #Bank 26 NET "ddr_dq[4]" LOC = L11; #Bank 26 NET "ddr_dq[5]" LOC = K13; #Bank 26 NET "ddr_dq[6]" LOC = K12; #Bank 26 NET "ddr_dq[7]" LOC = D11; #Bank 26 NET "ddr_dq[8]" LOC = M13; #Bank 26 NET "ddr_dq[9]" LOC = J14; #Bank 26 NET "ddr_dq[10]" LOC = B13; #Bank 26 NET "ddr_dq[11]" LOC = B12; #Bank 26 NET "ddr_dq[12]" LOC = G10; #Bank 26 NET "ddr_dq[13]" LOC = M11; #Bank 26 NET "ddr_dq[14]" LOC = C12; #Bank 26 NET "ddr_dq[15]" LOC = A11; #Bank 26 NET "ddr_dq[16]" LOC = G11; #Bank 26 NET "ddr_dq[17]" LOC = F11; #Bank 26 NET "ddr_dq[18]" LOC = D14; #Bank 26 NET "ddr_dq[19]" LOC = C14; #Bank 26 NET "ddr_dq[20]" LOC = G12; #Bank 26 NET "ddr_dq[21]" LOC = G13; #Bank 26 NET "ddr_dq[22]" LOC = F14; #Bank 26 NET "ddr_dq[23]" LOC = H14; #Bank 36 NET "ddr_dq[24]" LOC = C19; #Bank 36 NET "ddr_dq[25]" LOC = G20; #Bank 36 NET "ddr_dq[26]" LOC = E19; #Bank 36 NET "ddr_dq[27]" LOC = F20; #Bank 36 NET "ddr_dq[28]" LOC = A20; #Bank 36 NET "ddr_dq[29]" LOC = A21; #Bank 36 NET "ddr_dq[30]" LOC = E22; #Bank 36 NET "ddr_dq[31]" LOC = E23; #Bank 36 NET "ddr_dq[32]" LOC = G21; #Bank 36 NET "ddr_dq[33]" LOC = B21; #Bank 36 NET "ddr_dq[34]" LOC = A23; #Bank 36 NET "ddr_dq[35]" LOC = A24; #Bank 36 NET "ddr_dq[36]" LOC = C20; #Bank 36 NET "ddr_dq[37]" LOC = D20; #Bank 36 NET "ddr_dq[38]" LOC = J20; #Bank 36 NET "ddr_dq[39]" LOC = G22; #Bank 36 NET "ddr_dq[40]" LOC = D26; #Bank 36 NET "ddr_dq[41]" LOC = F26; #Bank 36 NET "ddr_dq[42]" LOC = B26; #Bank 36 NET "ddr_dq[43]" LOC = E26; #Bank 36 NET "ddr_dq[44]" LOC = C24; #Bank 36 NET "ddr_dq[45]" LOC = D25; #Bank 36 NET "ddr_dq[46]" LOC = D27; #Bank 36 NET "ddr_dq[47]" LOC = C25; #Bank 35 NET "ddr_dq[48]" LOC = C27; #Bank 35 NET "ddr_dq[49]" LOC = B28; #Bank 35 NET "ddr_dq[50]" LOC = D29; #Bank 35 NET "ddr_dq[51]" LOC = B27; #Bank 35 NET "ddr_dq[52]" LOC = G27; #Bank 35 NET "ddr_dq[53]" LOC = A28; #Bank 35 NET "ddr_dq[54]" LOC = E24; #Bank 35 NET "ddr_dq[55]" LOC = G25; #Bank 35 NET "ddr_dq[56]" LOC = F28; #Bank 35 NET "ddr_dq[57]" LOC = B31; #Bank 35 NET "ddr_dq[58]" LOC = H29; #Bank 35 NET "ddr_dq[59]" LOC = H28; #Bank 35 NET "ddr_dq[60]" LOC = B30; #Bank 35 NET "ddr_dq[61]" LOC = A30; #Bank 35 NET "ddr_dq[62]" LOC = E29; #Bank 35 NET "ddr_dq[63]" LOC = F29; #Bank 25 NET "ddr_addr[15]" LOC = C15; NET "ddr_addr[14]" LOC = D15; #Bank 25 NET "ddr_addr[13]" LOC = J15; #Bank 25 NET "ddr_addr[12]" LOC = H15; #Bank 25 NET "ddr_addr[11]" LOC = M15; #Bank 25 NET "ddr_addr[10]" LOC = M16; #Bank 25 NET "ddr_addr[9]" LOC = F15; #Bank 25 NET "ddr_addr[8]" LOC = G15; #Bank 25 NET "ddr_addr[7]" LOC = B15; #Bank 25 NET "ddr_addr[6]" LOC = A15; #Bank 25 NET "ddr_addr[5]" LOC = J17; #Bank 25 NET "ddr_addr[4]" LOC = D16; #Bank 25 NET "ddr_addr[3]" LOC = E16; #Bank 25 NET "ddr_addr[2]" LOC = B16; #Bank 25 NET "ddr_addr[1]" LOC = A16; #Bank 25 NET "ddr_addr[0]" LOC = L14; #Bank 25 NET "ddr_ba[2]" LOC = L15; #Bank 25 NET "ddr_ba[1]" LOC = J19; #Bank 25 NET "ddr_ba[0]" LOC = K19; #Bank 25 NET "ddr_ras_n" LOC = L19; #Bank 25 NET "ddr_cas_n" LOC = C17; #Bank 25 NET "ddr_we_n" LOC = B17; #Bank 25 NET "ddr_reset_n" LOC = E18; #Bank 25 NET "ddr_cke[0]" LOC = M18; #Bank 25 NET "ddr_odt[0]" LOC = F18; #Bank 25 NET "ddr_cs_n[0]" LOC = K18; #NET "sys_clk_p" LOC = "J9" ; #Bank 34 #NET "sys_clk_n" LOC = "H9" ; #Bank 34 #Bank 34 NET "clk_ref_p" LOC = J9; #Bank 34 NET "clk_ref_n" LOC = H9; #NET "sda" LOC = "F9" ; #Bank 34 #NET "scl" LOC = "F10" ; #Bank 34 #Bank 34 NET "sys_rst" LOC = H10; #Bank 34 NET "dfi_init_complete" LOC = AC22; NET "dfi_init_complete" IOSTANDARD = LVCMOS25; NET "processing_iseq" LOC = AC24; NET "processing_iseq" IOSTANDARD = LVCMOS25; NET "iq_full" LOC = AE22; NET "iq_full" IOSTANDARD = LVCMOS25; NET "rdback_fifo_empty" LOC = AE23; NET "rdback_fifo_empty" IOSTANDARD = LVCMOS25; #Bank 26 NET "ddr_dqs_p[0]" LOC = D12; #Bank 26 NET "ddr_dqs_n[0]" LOC = E12; #Bank 26 NET "ddr_dqs_p[1]" LOC = H12; #Bank 26 NET "ddr_dqs_n[1]" LOC = J12; #Bank 26 NET "ddr_dqs_p[2]" LOC = A13; #Bank 26 NET "ddr_dqs_n[2]" LOC = A14; #Bank 36 NET "ddr_dqs_p[3]" LOC = H19; #Bank 36 NET "ddr_dqs_n[3]" LOC = H20; #Bank 36 NET "ddr_dqs_p[4]" LOC = B23; #Bank 36 NET "ddr_dqs_n[4]" LOC = C23; #Bank 36 NET "ddr_dqs_p[5]" LOC = B25; #Bank 36 NET "ddr_dqs_n[5]" LOC = A25; #Bank 35 NET "ddr_dqs_p[6]" LOC = H27; #Bank 35 NET "ddr_dqs_n[6]" LOC = G28; #Bank 35 NET "ddr_dqs_p[7]" LOC = C30; #Bank 35 NET "ddr_dqs_n[7]" LOC = D30; #Bank 25 NET "ddr_ck_p[0]" LOC = G18; #Bank 25 NET "ddr_ck_n[0]" LOC = H18; #Bank 25 NET "ddr_ck_p[1]" LOC = K16; #Bank 25 NET "ddr_ck_n[1]" LOC = L16; NET "ddr_dm[0]" LOC = E11; #Bank 35 NET "ddr_dm[1]" LOC = B11; #Bank 35 NET "ddr_dm[2]" LOC = E14; #Bank 26 NET "ddr_dm[3]" LOC = D19; #Bank 26 NET "ddr_dm[4]" LOC = B22; #Bank 25 NET "ddr_dm[5]" LOC = A26; #Bank 25 NET "ddr_dm[6]" LOC = A29; #Bank 25 NET "ddr_dm[7]" LOC = A31; #CONFIG INTERNAL_VREF_BANK26=0.75; #CONFIG INTERNAL_VREF_BANK35=0.75; #CONFIG INTERNAL_VREF_BANK36=0.75; ################################################################################################## ##The following locations must be reserved and cannot be used for external I/O because ## ##the I/O elements associated with these sites (IODELAY, OSERDES, and associated routing) ## ##are used to generate and route the clocks necessary for read data capture and synchronization ## ##to the core clock domain. These pins should not be routed out on the user's PCB ## ################################################################################################## ################################################################################################## ##The logic of this pin is used internally to drive a BUFR in the column. This chosen pin must ## ##be a clock pin capable of spanning to all of the banks containing data bytes in the particular## ##column. That is, all byte groups must be within +/- 1 bank of this pin. This pin cannot be ## ##used for other functions and should not be connected externally. If a different pin is chosen,## ##he corresponding LOC constraint must also be changed. ## ################################################################################################## CONFIG PROHIBIT = H22; CONFIG PROHIBIT = F21; CONFIG PROHIBIT = B20; CONFIG PROHIBIT = F19; CONFIG PROHIBIT = C13; CONFIG PROHIBIT = M12; CONFIG PROHIBIT = L13; CONFIG PROHIBIT = K14; CONFIG PROHIBIT = F25; CONFIG PROHIBIT = C29; CONFIG PROHIBIT = C28; CONFIG PROHIBIT = D24; ###################################################################################### ##Place RSYNC OSERDES and IODELAY: ## ###################################################################################### ##Site: D24 -- Bank 25 INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_loop_col0.u_oserdes_rsync" LOC = OLOGIC_X2Y139; INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_loop_col0.u_odelay_rsync" LOC = IODELAY_X2Y139; INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_loop_col0.u_bufr_rsync" LOC = BUFR_X2Y6; ##Site: M12 -- Bank 35 INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_loop_col1.u_oserdes_rsync" LOC = OLOGIC_X1Y139; INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_loop_col1.u_odelay_rsync" LOC = IODELAY_X1Y139; INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_loop_col1.u_bufr_rsync" LOC = BUFR_X1Y6; ################################################################################################## ##The logic of this pin is used internally to drive a BUFIO for the byte group. Any clock ## ##capable pin in the same bank as the data byte group (DQS, DQ, DM if used) can be used for ## ##this pin. This pin cannot be used for other functions and should not be connected externally. ## ##If a different pin is chosen, the corresponding LOC constraint must also be changed. ## ################################################################################################## CONFIG PROHIBIT = B20,C13,C28,D24,F21,F25,K14,L13; ###################################################################################### ##Place CPT OSERDES and IODELAY: ## ###################################################################################### ##Site: B20 -- Bank 26 INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[0].u_oserdes_cpt" LOC = OLOGIC_X2Y137; INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[0].u_odelay_cpt" LOC = IODELAY_X2Y137; ##Site: F21 -- Bank 26 INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[1].u_oserdes_cpt" LOC = OLOGIC_X2Y141; INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[1].u_odelay_cpt" LOC = IODELAY_X2Y141; ##Site: H19 -- Bank 26 INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[2].u_oserdes_cpt" LOC = OLOGIC_X2Y143; INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[2].u_odelay_cpt" LOC = IODELAY_X2Y143; ##Site: K16 -- Bank 36 INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[3].u_oserdes_cpt" LOC = OLOGIC_X1Y179; INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[3].u_odelay_cpt" LOC = IODELAY_X1Y179; ##Site: L15 -- Bank 36 INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[4].u_oserdes_cpt" LOC = OLOGIC_X1Y181; INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[4].u_odelay_cpt" LOC = IODELAY_X1Y181; ##Site: A16 -- Bank 36 INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[5].u_oserdes_cpt" LOC = OLOGIC_X1Y137; INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[5].u_odelay_cpt" LOC = IODELAY_X1Y137; ##Site: K14 -- Bank 35 INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[6].u_oserdes_cpt" LOC = OLOGIC_X1Y141; INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[6].u_odelay_cpt" LOC = IODELAY_X1Y141; ##Site: L13 -- Bank 35 INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[7].u_oserdes_cpt" LOC = OLOGIC_X1Y143; INST "xil_phy/u_phy_read/u_phy_rdclk_gen/gen_ck_cpt[7].u_odelay_cpt" LOC = IODELAY_X1Y143; ###################################################################################### ## MMCM_ADV CONSTRAINTS ## ###################################################################################### #Banks 15, 25, 35 INST "u_infrastructure/u_mmcm_adv" LOC = MMCM_ADV_X0Y8; ########################################## ## PCIE Constraints ########################################## ############################################################################### # Define Device, Package And Speed Grade ############################################################################### CONFIG PART = xc6vlx240t-ff1156-1; ############################################################################### # User Time Names / User Time Groups / Time Specs ############################################################################### ############################################################################### # User Physical Constraints ############################################################################### ############################################################################### # Pinout and Related I/O Constraints ############################################################################### # # SYS reset (input) signal. The sys_reset_n signal should be # obtained from the PCI Express interface if possible. For # slot based form factors, a system reset signal is usually # present on the connector. For cable based form factors, a # system reset signal may not be available. In this case, the # system reset signal must be generated locally by some form of # supervisory circuit. You may change the IOSTANDARD and LOC # to suit your requirements and VCCO voltage banking rules. # NET "sys_reset_n" TIG; NET "sys_reset_n" NODELAY = "TRUE"; NET "sys_reset_n" LOC = AE13; NET "sys_reset_n" IOSTANDARD = LVCMOS25; NET "sys_reset_n" PULLUP; # # # SYS clock 250 MHz (input) signal. The sys_clk_p and sys_clk_n # signals are the PCI Express reference clock. Virtex-6 GT # Transceiver architecture requires the use of a dedicated clock # resources (FPGA input pins) associated with each GT Transceiver. # To use these pins an IBUFDS primitive (refclk_ibuf) is # instantiated in user's design. # Please refer to the Virtex-6 GT Transceiver User Guide # (UG) for guidelines regarding clock resource selection. # #NET "sys_clk_p" LOC = V6; #NET "sys_clk_n" LOC = V5; INST "i_pcie_top/refclk_ibuf" LOC = IBUFDS_GTXE1_X0Y6; # # Transceiver instance placement. This constraint selects the # transceivers to be used, which also dictates the pinout for the # transmit and receive differential pairs. Please refer to the # Virtex-6 GT Transceiver User Guide (UG) for more information. # # PCIe Lane 0 INST "i_pcie_top/core/pcie_2_0_i/pcie_gt_i/gtx_v6_i/no_of_lanes.GTXD[0].GTX" LOC = GTXE1_X0Y15; # PCIe Lane 1 INST "i_pcie_top/core/pcie_2_0_i/pcie_gt_i/gtx_v6_i/no_of_lanes.GTXD[1].GTX" LOC = GTXE1_X0Y14; # PCIe Lane 2 INST "i_pcie_top/core/pcie_2_0_i/pcie_gt_i/gtx_v6_i/no_of_lanes.GTXD[2].GTX" LOC = GTXE1_X0Y13; # PCIe Lane 3 INST "i_pcie_top/core/pcie_2_0_i/pcie_gt_i/gtx_v6_i/no_of_lanes.GTXD[3].GTX" LOC = GTXE1_X0Y12; # PCIe Lane 4 INST "i_pcie_top/core/pcie_2_0_i/pcie_gt_i/gtx_v6_i/no_of_lanes.GTXD[4].GTX" LOC = GTXE1_X0Y11; # PCIe Lane 5 INST "i_pcie_top/core/pcie_2_0_i/pcie_gt_i/gtx_v6_i/no_of_lanes.GTXD[5].GTX" LOC = GTXE1_X0Y10; # PCIe Lane 6 INST "i_pcie_top/core/pcie_2_0_i/pcie_gt_i/gtx_v6_i/no_of_lanes.GTXD[6].GTX" LOC = GTXE1_X0Y9; # PCIe Lane 7 INST "i_pcie_top/core/pcie_2_0_i/pcie_gt_i/gtx_v6_i/no_of_lanes.GTXD[7].GTX" LOC = GTXE1_X0Y8; # # PCI Express Block placement. This constraint selects the PCI Express # Block to be used. # INST "i_pcie_top/core/pcie_2_0_i/pcie_block_i" LOC = PCIE_X0Y1; #NET "led_0" LOC = "AC22" ; #NET "led_1" LOC = "AC24" ; #NET "led_2" LOC = "AE22" ; # # MMCM Placment. This constraint selects the MMCM Placement # INST "i_pcie_top/core/pcie_clocking_i/mmcm_adv_i" LOC = MMCM_ADV_X0Y7; ############################################################################### # Timing Constraints ############################################################################### # # Timing requirements and related constraints. # NET "i_pcie_top/sys_clk_c" TNM_NET = "SYSCLK"; NET "i_pcie_top/core*/pcie_clocking_i/clk_125" TNM_NET = "CLK_125"; NET "i_pcie_top/core*/TxOutClk_bufg" TNM_NET = "TXOUTCLKBUFG"; NET "i_pcie_top/core*/pcie_clocking_i/clk_250" TNM_NET = "CLK_250"; TIMESPEC TS_SYSCLK = PERIOD "SYSCLK" 250 MHz HIGH 50 %; TIMESPEC TS_CLK_125 = PERIOD "CLK_125" TS_SYSCLK / 2 HIGH 50 % PRIORITY 100; TIMESPEC TS_TXOUTCLKBUFG = PERIOD "TXOUTCLKBUFG" 250 MHz HIGH 50 % PRIORITY 100; TIMESPEC TS_CLK_250 = PERIOD "CLK_250" TS_SYSCLK * 1 HIGH 50 % PRIORITY 1; PIN "i_pcie_top/core*/trn_reset_n_int_i.CLR" TIG; PIN "i_pcie_top/core*/trn_reset_n_i.CLR" TIG; PIN "i_pcie_top/core*/pcie_clocking_i/mmcm_adv_i.RST" TIG; TIMESPEC TS_RESETN = FROM FFS TO FFS("i_pcie_top/user_reset_n_i") 8 ns; ############################################################################### # Physical Constraints ############################################################################### ############################################################################### # End ############################################################################### ================================================ FILE: hw/boards/ML605/softMC_pcie_app.v ================================================ `timescale 1ns / 1ps module softMC_pcie_app #( parameter C_PCI_DATA_WIDTH = 9'd32, DQ_WIDTH = 64 )( input clk, input rst, output CHNL_RX_CLK, input CHNL_RX, output reg CHNL_RX_ACK, input CHNL_RX_LAST, input [31:0] CHNL_RX_LEN, input [30:0] CHNL_RX_OFF, input [C_PCI_DATA_WIDTH-1:0] CHNL_RX_DATA, input CHNL_RX_DATA_VALID, output CHNL_RX_DATA_REN, output CHNL_TX_CLK, output reg CHNL_TX, input CHNL_TX_ACK, output CHNL_TX_LAST, output reg [31:0] CHNL_TX_LEN, output [30:0] CHNL_TX_OFF, output [C_PCI_DATA_WIDTH-1:0] CHNL_TX_DATA, output reg CHNL_TX_DATA_VALID, input CHNL_TX_DATA_REN, output app_en, input app_ack, output[31:0] app_instr, //Data read back Interface input rdback_fifo_empty, output rdback_fifo_rden, input[DQ_WIDTH*4 - 1:0] rdback_data ); assign CHNL_RX_CLK = clk; assign CHNL_TX_CLK = clk; assign CHNL_TX_OFF = 0; assign CHNL_TX_LAST = 1'd1; reg app_en_r; reg[C_PCI_DATA_WIDTH-1:0] rx_data_r; reg old_chnl_rx; reg pending_ack = 0; //always acknowledge transaction always@(posedge clk) begin old_chnl_rx <= CHNL_RX; if(~old_chnl_rx & CHNL_RX) pending_ack <= 1'b1; if(CHNL_RX_ACK) CHNL_RX_ACK <= 1'b0; else begin if(pending_ack /*& app_ack*/) begin CHNL_RX_ACK <= 1'b1; pending_ack <= 1'b0; end end end //register incoming data assign CHNL_RX_DATA_REN = ~app_en_r | app_ack; always@(posedge clk) begin if(~app_en_r | app_ack) begin app_en_r <= CHNL_RX_DATA_VALID; rx_data_r <= CHNL_RX_DATA; end end //send to the MC assign app_en = app_en_r; assign app_instr = rx_data_r; //SEND DATA TO HOST localparam RECV_IDLE = 1'b0; localparam RECV_BUSY = 1'b1; reg sender_ack; reg[DQ_WIDTH*4 - 1:0] send_data_r; reg recv_state = RECV_IDLE; assign rdback_fifo_rden = (recv_state == RECV_IDLE); always@(posedge clk) begin if(rst) begin recv_state <= RECV_IDLE; end else begin case(recv_state) RECV_IDLE: begin if(~rdback_fifo_empty) begin send_data_r <= rdback_data; recv_state <= RECV_BUSY; end end //RECV_IDLE RECV_BUSY: begin if(sender_ack) recv_state <= RECV_IDLE; end //RECV_BUSY endcase end end reg[2:0] sender_state = 0; //edit this if DQ_WIDTH or C_PCI_DATA_WIDTH changes reg[2:0] sender_state_ns; always@* begin sender_ack = 1'b0; sender_state_ns = sender_state; CHNL_TX = sender_state[2]; CHNL_TX_LEN = 16; if(recv_state == RECV_BUSY) begin CHNL_TX = 1'b1; CHNL_TX_DATA_VALID = 1'b1; if(CHNL_TX_DATA_REN) begin sender_state_ns = sender_state + 3'd1; if(sender_state[1:0] == 2'b11) sender_ack = 1'b1; end end end always@(posedge clk) begin if(rst) begin sender_state <= 0; end else begin sender_state <= sender_state_ns; end end wire[7:0] offset = {6'd0, sender_state[1:0]} << 6; assign CHNL_TX_DATA = send_data_r[offset +: 64]; endmodule ================================================ FILE: hw/boards/ML605/softMC_top.v ================================================ `timescale 1ps / 1ps `include "softMC.inc" module softMC_top # ( parameter TCQ = 100, parameter tCK = 2500, //ps, TODO: let memory clok be 400 Mhz for now parameter nCK_PER_CLK = 2, // # of memory clocks per CLK parameter REFCLK_FREQ = 200.0, // IODELAY Reference Clock freq (MHz) parameter DRAM_TYPE = "DDR3", // Memory I/F type: "DDR3", "DDR2" parameter RST_ACT_LOW = 0, parameter INPUT_CLK_TYPE = "DIFFERENTIAL", parameter CLKFBOUT_MULT_F =6, parameter DIVCLK_DIVIDE = 1, parameter CLKOUT_DIVIDE = 3, // Slot Conifg parameters parameter [7:0] SLOT_0_CONFIG = 8'b0000_0001, parameter [7:0] SLOT_1_CONFIG = 8'b0000_0000, // DRAM bus widths parameter BANK_WIDTH = 3, // # of bank bits parameter CK_WIDTH = 2, // # of CK/CK# outputs to memory parameter COL_WIDTH = 10, // column address width parameter nCS_PER_RANK = 1, // # of unique CS outputs per rank parameter DQ_CNT_WIDTH = 6, // = ceil(log2(DQ_WIDTH)) parameter DQ_WIDTH = 64, // # of DQ (data) parameter DM_WIDTH = 8, // # of DM (data mask) parameter DQS_CNT_WIDTH = 3, // = ceil(log2(DQS_WIDTH)) parameter DQS_WIDTH = 8, // # of DQS (strobe) parameter DRAM_WIDTH = 8, // # of DQ per DQS parameter ROW_WIDTH = 16, // DRAM address bus width parameter RANK_WIDTH = 1, // log2(CS_WIDTH) parameter CS_WIDTH = 1, // # of DRAM ranks parameter CKE_WIDTH = 1, // # of cke outputs parameter CAL_WIDTH = "HALF", // # of DRAM ranks to be calibrated // CAL_WIDTH = CS_WIDTH when "FULL" // CAL_WIDTH = CS_WIDTH/2 when "HALF" // calibration Address. The address given below will be used for calibration // read and write operations. parameter CALIB_ROW_ADD = 16'h0000,// Calibration row address parameter CALIB_COL_ADD = 12'h000, // Calibration column address parameter CALIB_BA_ADD = 3'h0, // Calibration bank address // DRAM mode settings parameter AL = "0", // Additive Latency option parameter BURST_MODE = "8", // Burst length parameter BURST_TYPE = "SEQ", // Burst type parameter nAL = 0, // Additive latency (in clk cyc) parameter nCL = 5, // Read CAS latency (in clk cyc) parameter nCWL = 5, // Write CAS latency (in clk cyc) parameter tRFC = 110000, // Refresh-to-command delay parameter OUTPUT_DRV = "HIGH", // DRAM reduced output drive option parameter REG_CTRL = "OFF", // "ON" for registered DIMM parameter RTT_NOM = "60", // ODT Nominal termination value parameter RTT_WR = "OFF", // ODT Write termination value parameter WRLVL = "ON", // Enable write leveling // Phase Detector/Read Leveling options parameter PHASE_DETECT = "ON", // Enable read phase detector parameter PD_TAP_REQ = 0, // # of IODELAY taps reserved for PD parameter PD_MSB_SEL = 8, // # of bits in PD response cntr parameter PD_DQS0_ONLY = "ON", // Enable use of DQS[0] only for // phase detector parameter PD_LHC_WIDTH = 16, // sampling averaging cntr widths parameter PD_CALIB_MODE = "PARALLEL", // parallel/seq PD calibration // IODELAY/BUFFER options parameter IBUF_LPWR_MODE = "OFF", // Input buffer low power mode parameter IODELAY_HP_MODE = "ON", // IODELAY High Performance Mode parameter IODELAY_GRP = "IODELAY_MIG", // May be assigned unique name // when mult IP cores in design // Pin-out related parameters parameter nDQS_COL0 = 3, // # DQS groups in I/O column #1 parameter nDQS_COL1 = 5, // # DQS groups in I/O column #2 parameter nDQS_COL2 = 0, // # DQS groups in I/O column #3 parameter nDQS_COL3 = 0, // # DQS groups in I/O column #4 parameter DQS_LOC_COL0 = 24'h020100, // DQS grps in col #1 parameter DQS_LOC_COL1 = 40'h0706050403, // DQS grps in col #2 parameter DQS_LOC_COL2 = 0, // DQS grps in col #3 parameter DQS_LOC_COL3 = 0, // DQS grps in col #4 parameter USE_DM_PORT = 0, // DM instantation enable // Simulation /debug options parameter SIM_BYPASS_INIT_CAL = "NONE", // Parameter used to force skipping // or abbreviation of initialization // and calibration. Overrides // SIM_INIT_OPTION, SIM_CAL_OPTION, // and disables various other blocks parameter SIM_INIT_OPTION = "NONE", // Skip various initialization steps parameter SIM_CAL_OPTION = "NONE", // Skip various calibration steps parameter DEBUG_PORT = "OFF", // Enable debug port parameter SIMULATION = "OFF" )( input sys_clk_p, input sys_clk_n, input clk_ref_p, input clk_ref_n, input sys_rst, input sys_reset_n, // DDRx Output Interface output [CK_WIDTH-1:0] ddr_ck_p, output [CK_WIDTH-1:0] ddr_ck_n, output [ROW_WIDTH-1:0] ddr_addr, output [BANK_WIDTH-1:0] ddr_ba, output ddr_ras_n, output ddr_cas_n, output ddr_we_n, output [CS_WIDTH*nCS_PER_RANK-1:0] ddr_cs_n, output [CKE_WIDTH-1:0] ddr_cke, output [CS_WIDTH*nCS_PER_RANK-1:0] ddr_odt, output ddr_reset_n, //output ddr_parity, output [DM_WIDTH-1:0] ddr_dm, inout [DQS_WIDTH-1:0] ddr_dqs_p, inout [DQS_WIDTH-1:0] ddr_dqs_n, inout [DQ_WIDTH-1:0] ddr_dq, output dfi_init_complete, //led 0 output processing_iseq, //led 1 output iq_full, //led 2 output rdback_fifo_empty, //led 3 //PCIE `ifndef SIM //we dont want to simulate PCIe core output [7:0] pci_exp_txp, output [7:0] pci_exp_txn, input [7:0] pci_exp_rxp, input [7:0] pci_exp_rxn `else input app_en, output app_ack, input[31:0] app_instr, //Data read back Interface //output rdback_fifo_empty, input rdback_fifo_rden, output[DQ_WIDTH*4 - 1:0] rdback_data `endif //SIM ); assign ddr_dm = {DM_WIDTH{1'b0}}; /*** CLOCK MANAGEMENT ***/ localparam SYSCLK_PERIOD = tCK * nCK_PER_CLK; localparam MMCM_ADV_BANDWIDTH = "OPTIMIZED"; wire clk_mem, clk, clk_rd_base; wire clk_ref = 0; wire rst; wire pd_PSDONE, pd_PSEN, pd_PSINCDEC; //phase detector interface wire iodelay_ctrl_rdy; wire mmcm_clk; wire sys_clk = 0; //use 200MHZ refrence clock to generate mmcm_clk iodelay_ctrl # ( .TCQ (TCQ), .IODELAY_GRP (IODELAY_GRP), .INPUT_CLK_TYPE (INPUT_CLK_TYPE), .RST_ACT_LOW (RST_ACT_LOW) ) u_iodelay_ctrl ( .clk_ref_p (clk_ref_p), //input .clk_ref_n (clk_ref_n), //input .clk_ref (clk_ref), //input .sys_rst (sys_rst), //input .clk_200 (mmcm_clk), .iodelay_ctrl_rdy (iodelay_ctrl_rdy) //output ); infrastructure # ( .TCQ (TCQ), .CLK_PERIOD (SYSCLK_PERIOD), .nCK_PER_CLK (nCK_PER_CLK), .MMCM_ADV_BANDWIDTH (MMCM_ADV_BANDWIDTH), .CLKFBOUT_MULT_F (CLKFBOUT_MULT_F), .DIVCLK_DIVIDE (DIVCLK_DIVIDE), .CLKOUT_DIVIDE (CLKOUT_DIVIDE), .RST_ACT_LOW (RST_ACT_LOW) ) u_infrastructure ( .clk_mem (clk_mem), //output .clk (clk), //output .clk_rd_base (clk_rd_base), //output .rstdiv0 (rst), //output .mmcm_clk (mmcm_clk), //input .sys_rst (sys_rst), //input .iodelay_ctrl_rdy (iodelay_ctrl_rdy), //input .PSDONE (pd_PSDONE), //output .PSEN (pd_PSEN), //input .PSINCDEC (pd_PSINCDEC) //input ); wire [ROW_WIDTH-1:0] dfi_address0; wire [ROW_WIDTH-1:0] dfi_address1; wire [BANK_WIDTH-1:0] dfi_bank0; wire [BANK_WIDTH-1:0] dfi_bank1; wire dfi_cas_n0; wire dfi_cas_n1; wire [CKE_WIDTH-1:0] dfi_cke0; wire [CKE_WIDTH-1:0] dfi_cke1; wire [CS_WIDTH*nCS_PER_RANK-1:0] dfi_cs_n0; wire [CS_WIDTH*nCS_PER_RANK-1:0] dfi_cs_n1; wire [CS_WIDTH*nCS_PER_RANK-1:0] dfi_odt0; wire [CS_WIDTH*nCS_PER_RANK-1:0] dfi_odt1; wire dfi_ras_n0; wire dfi_ras_n1; wire dfi_reset_n; assign dfi_reset_n = 1; wire dfi_we_n0; wire dfi_we_n1; // DFI Write wire dfi_wrdata_en; wire [4*DQ_WIDTH-1:0] dfi_wrdata; wire [4*(DQ_WIDTH/8)-1:0] dfi_wrdata_mask; // DFI Read wire dfi_rddata_en; wire dfi_rddata_en_even; wire dfi_rddata_en_odd; wire [4*DQ_WIDTH-1:0] dfi_rddata; wire dfi_rddata_valid; wire dfi_rddata_valid_even; wire dfi_rddata_valid_odd; // DFI Initialization Status / CLK Disable wire dfi_dram_clk_disable; // sideband signals wire io_config_strobe; wire [RANK_WIDTH:0] io_config; localparam CLK_PERIOD = tCK * nCK_PER_CLK; phy_top #( .TCQ (TCQ), .REFCLK_FREQ (REFCLK_FREQ), .nCS_PER_RANK (nCS_PER_RANK), .CAL_WIDTH (CAL_WIDTH), .CALIB_ROW_ADD (CALIB_ROW_ADD), .CALIB_COL_ADD (CALIB_COL_ADD), .CALIB_BA_ADD (CALIB_BA_ADD), .CS_WIDTH (CS_WIDTH), .nCK_PER_CLK (nCK_PER_CLK), .CKE_WIDTH (CKE_WIDTH), .DRAM_TYPE (DRAM_TYPE), .SLOT_0_CONFIG (SLOT_0_CONFIG), .SLOT_1_CONFIG (SLOT_1_CONFIG), .CLK_PERIOD (CLK_PERIOD), .BANK_WIDTH (BANK_WIDTH), .CK_WIDTH (CK_WIDTH), .COL_WIDTH (COL_WIDTH), .DM_WIDTH (DM_WIDTH), .DQ_CNT_WIDTH (DQ_CNT_WIDTH), .DQ_WIDTH (DQ_WIDTH), .DQS_CNT_WIDTH (DQS_CNT_WIDTH), .DQS_WIDTH (DQS_WIDTH), .DRAM_WIDTH (DRAM_WIDTH), .ROW_WIDTH (ROW_WIDTH), .RANK_WIDTH (RANK_WIDTH), .AL (AL), .BURST_MODE (BURST_MODE), .BURST_TYPE (BURST_TYPE), .nAL (nAL), .nCL (nCL), .nCWL (nCWL), .tRFC (tRFC), .OUTPUT_DRV (OUTPUT_DRV), .REG_CTRL (REG_CTRL), .RTT_NOM (RTT_NOM), .RTT_WR (RTT_WR), .WRLVL (WRLVL), .PHASE_DETECT (PHASE_DETECT), .IODELAY_HP_MODE (IODELAY_HP_MODE), .IODELAY_GRP (IODELAY_GRP), // Prevent the following simulation-related parameters from // being overridden for synthesis - for synthesis only the // default values of these parameters should be used // synthesis translate_off .SIM_BYPASS_INIT_CAL (SIM_BYPASS_INIT_CAL), .SIM_INIT_OPTION(SIM_INIT_OPTION), .SIM_CAL_OPTION(SIM_CAL_OPTION), // synthesis translate_on .nDQS_COL0 (nDQS_COL0), .nDQS_COL1 (nDQS_COL1), .nDQS_COL2 (nDQS_COL2), .nDQS_COL3 (nDQS_COL3), .DQS_LOC_COL0 (DQS_LOC_COL0), .DQS_LOC_COL1 (DQS_LOC_COL1), .DQS_LOC_COL2 (DQS_LOC_COL2), .DQS_LOC_COL3 (DQS_LOC_COL3), .USE_DM_PORT (USE_DM_PORT), .DEBUG_PORT (DEBUG_PORT) ) xil_phy ( .clk_mem(clk_mem), //input .clk(clk), //input .clk_rd_base(clk_rd_base), //input .rst(rst), //input .slot_0_present(SLOT_0_CONFIG), //input .slot_1_present(SLOT_1_CONFIG), //input .dfi_address0(dfi_address0), //Note: '0' versions are used for row commands, '1' versions for column commands .dfi_address1(dfi_address1), .dfi_bank0(dfi_bank0), .dfi_bank1(dfi_bank1), .dfi_cas_n0(dfi_cas_n0), .dfi_cas_n1(dfi_cas_n1), .dfi_cke0(dfi_cke0), .dfi_cke1(dfi_cke1), .dfi_cs_n0(dfi_cs_n0), .dfi_cs_n1(dfi_cs_n1), .dfi_odt0(dfi_odt0), .dfi_odt1(dfi_odt1), .dfi_ras_n0(dfi_ras_n0), .dfi_ras_n1(dfi_ras_n1), .dfi_reset_n(dfi_reset_n), .dfi_we_n0(dfi_we_n0), .dfi_we_n1(dfi_we_n1), .dfi_wrdata_en(dfi_wrdata_en), .dfi_wrdata(dfi_wrdata), .dfi_wrdata_mask(dfi_wrdata_mask), .dfi_rddata_en(dfi_rddata_en), .dfi_rddata_en_even(dfi_rddata_en_even), .dfi_rddata_en_odd(dfi_rddata_en_odd), .dfi_rddata(dfi_rddata), .dfi_rddata_valid(dfi_rddata_valid), .dfi_rddata_valid_even(dfi_rddata_valid_even), .dfi_rddata_valid_odd(dfi_rddata_valid_odd), .dfi_dram_clk_disable(dfi_dram_clk_disable), .dfi_init_complete(dfi_init_complete), //sideband signals .io_config_strobe(io_config_strobe), //input .io_config(io_config), //input [RANK_WIDTH:0] //DRAM signals .ddr_ck_p(ddr_ck_p), .ddr_ck_n(ddr_ck_n), .ddr_addr(ddr_addr), .ddr_ba(ddr_ba), .ddr_ras_n(ddr_ras_n), .ddr_cas_n(ddr_cas_n), .ddr_we_n(ddr_we_n), .ddr_cs_n(ddr_cs_n), .ddr_cke(ddr_cke), .ddr_odt(ddr_odt), .ddr_reset_n(ddr_reset_n), //.ddr_parity(ddr_parity), .ddr_dm(ddr_dm), .ddr_dqs_p(ddr_dqs_p), .ddr_dqs_n(ddr_dqs_n), .ddr_dq(ddr_dq), //phase detection signals .pd_PSDONE(pd_PSDONE), .pd_PSEN(pd_PSEN), .pd_PSINCDEC(pd_PSINCDEC) ); //App Command Interface `ifndef SIM wire app_en; wire app_ack; wire[31:0] app_instr; //Data read back Interface wire rdback_fifo_rden; wire[DQ_WIDTH*4 - 1:0] rdback_data; `endif //SIM softMC #(.TCQ(TCQ), .tCK(tCK), .nCK_PER_CLK(nCK_PER_CLK), .RANK_WIDTH(RANK_WIDTH), .ROW_WIDTH(ROW_WIDTH), .BANK_WIDTH(BANK_WIDTH), .CKE_WIDTH(CKE_WIDTH), .CS_WIDTH(CS_WIDTH), .nCS_PER_RANK(nCS_PER_RANK), .DQ_WIDTH(DQ_WIDTH)) i_softmc( .clk(clk), .rst(rst), //App Command Interface .app_en(app_en), .app_ack(app_ack), .app_instr(app_instr), .iq_full(iq_full), .processing_iseq(processing_iseq), // DFI Control/Address .dfi_address0(dfi_address0), .dfi_address1(dfi_address1), .dfi_bank0(dfi_bank0), .dfi_bank1(dfi_bank1), .dfi_cas_n0(dfi_cas_n0), .dfi_cas_n1(dfi_cas_n1), .dfi_cke0(dfi_cke0), .dfi_cke1(dfi_cke1), .dfi_cs_n0(dfi_cs_n0), .dfi_cs_n1(dfi_cs_n1), .dfi_odt0(dfi_odt0), .dfi_odt1(dfi_odt1), .dfi_ras_n0(dfi_ras_n0), .dfi_ras_n1(dfi_ras_n1), .dfi_reset_n(dfi_reset_n), .dfi_we_n0(dfi_we_n0), .dfi_we_n1(dfi_we_n1), // DFI Write .dfi_wrdata_en(dfi_wrdata_en), .dfi_wrdata(dfi_wrdata), .dfi_wrdata_mask(dfi_wrdata_mask), // DFI Read .dfi_rddata_en(dfi_rddata_en), .dfi_rddata_en_even(dfi_rddata_en_even), .dfi_rddata_en_odd(dfi_rddata_en_odd), .dfi_rddata(dfi_rddata), .dfi_rddata_valid(dfi_rddata_valid), .dfi_rddata_valid_even(dfi_rddata_valid_even), .dfi_rddata_valid_odd(dfi_rddata_valid_odd), // DFI Initialization Status / CLK Disable .dfi_dram_clk_disable(dfi_dram_clk_disable), .dfi_init_complete(dfi_init_complete), // sideband signals .io_config_strobe(io_config_strobe), .io_config(io_config), //Data read back Interface .rdback_fifo_empty(rdback_fifo_empty), .rdback_fifo_rden(rdback_fifo_rden), .rdback_data(rdback_data) ); `ifndef SIM riffa_top_v6_pcie_v2_5 #( .C_DATA_WIDTH(64), // RX/TX interface data width .DQ_WIDTH(DQ_WIDTH) ) i_pcie_top ( .pci_exp_txp(pci_exp_txp), .pci_exp_txn(pci_exp_txn), .pci_exp_rxp(pci_exp_rxp), .pci_exp_rxn(pci_exp_rxn), .sys_clk_p(sys_clk_p), .sys_clk_n(sys_clk_n), .sys_reset_n(sys_reset_n), .app_clk(clk), .app_en(app_en), .app_ack(app_ack), .app_instr(app_instr), //Data read back Interface .rdback_fifo_empty(rdback_fifo_empty), .rdback_fifo_rden(rdback_fifo_rden), .rdback_data(rdback_data) ); `endif //SIM endmodule ================================================ FILE: hw/boards/ML605/tb_softMC_top.v ================================================ `timescale 1ps / 1ps `include "softMC.inc" module tb_softMC_top; parameter REFCLK_FREQ = 200; // # = 200 for all design frequencies of // -1 speed grade devices // = 200 when design frequency < 480 MHz // for -2 and -3 speed grade devices. // = 300 when design frequency >= 480 MHz // for -2 and -3 speed grade devices. parameter SIM_BYPASS_INIT_CAL = "FAST"; // # = "OFF" - Complete memory init & // calibration sequence // # = "SKIP" - Skip memory init & // calibration sequence // # = "FAST" - Skip memory init & use // abbreviated calib sequence parameter RST_ACT_LOW = 0; // =1 for active low reset, // =0 for active fhigh. parameter IODELAY_GRP = "IODELAY_MIG"; //to phy_top parameter nCK_PER_CLK = 2; // # of memory CKs per fabric clock. // # = 2, 1. parameter nCS_PER_RANK = 1; // # of unique CS outputs per Rank for // phy. parameter DQS_CNT_WIDTH = 3; // # = ceil(log2(DQS_WIDTH)). parameter RANK_WIDTH = 1; // # = ceil(log2(RANKS)). parameter BANK_WIDTH = 3; // # of memory Bank Address bits. parameter CK_WIDTH = 2; // # of CK/CK# outputs to memory. parameter CKE_WIDTH = 1; // # of CKE outputs to memory. parameter COL_WIDTH = 10; // # of memory Column Address bits. parameter CS_WIDTH = 1; // # of unique CS outputs to memory. parameter DM_WIDTH = 8; // # of Data Mask bits. parameter DQ_WIDTH = 64; // # of Data (DQ) bits. parameter DQS_WIDTH = 8; // # of DQS/DQS# bits. parameter ROW_WIDTH = 15; // # of memory Row Address bits. parameter BURST_MODE = "8"; // Burst Length (Mode Register 0). // # = "8", "4", "OTF". parameter INPUT_CLK_TYPE = "DIFFERENTIAL"; // input clock type DIFFERENTIAL or SINGLE_ENDED parameter BM_CNT_WIDTH = 2; // # = ceil(log2(nBANK_MACHS)). parameter ADDR_CMD_MODE = "1T" ; // # = "2T", "1T". parameter ORDERING = "STRICT"; // # = "NORM", "STRICT". parameter RTT_NOM = "60"; // RTT_NOM (ODT) (Mode Register 1). // # = "DISABLED" - RTT_NOM disabled, // = "120" - RZQ/2, // = "60" - RZQ/4, // = "40" - RZQ/6. parameter RTT_WR = "OFF"; // RTT_WR (ODT) (Mode Register 2). // # = "OFF" - Dynamic ODT off, // = "120" - RZQ/2, // = "60" - RZQ/4, parameter OUTPUT_DRV = "HIGH"; // Output Driver Impedance Control (Mode Register 1). // # = "HIGH" - RZQ/7, // = "LOW" - RZQ/6. parameter REG_CTRL = "OFF"; // # = "ON" - RDIMMs, // = "OFF" - Components, SODIMMs, UDIMMs. parameter CLKFBOUT_MULT_F = 6; // write PLL VCO multiplier. parameter DIVCLK_DIVIDE = 1; // write PLL VCO divisor. parameter CLKOUT_DIVIDE = 3; // VCO output divisor for fast (memory) clocks. parameter tCK = 2500; // memory tCK paramter. // # = Clock Period. parameter DEBUG_PORT = "OFF"; // # = "ON" Enable debug signals/controls. // = "OFF" Disable debug signals/controls. parameter tPRDI = 1_000_000; // memory tPRDI paramter. parameter tREFI = 7800000; // memory tREFI paramter. parameter tZQI = 128_000_000; // memory tZQI paramter. parameter ADDR_WIDTH = 29; // # = RANK_WIDTH + BANK_WIDTH // + ROW_WIDTH + COL_WIDTH; parameter STARVE_LIMIT = 2; // # = 2,3,4. parameter TCQ = 100; parameter ECC = "OFF"; parameter ECC_TEST = "OFF"; parameter DATA_WIDTH = 64; parameter PAYLOAD_WIDTH = (ECC_TEST == "OFF") ? DATA_WIDTH : DQ_WIDTH; //***********************************************************************// // Traffic Gen related parameters //***********************************************************************// parameter EYE_TEST = "FALSE"; // set EYE_TEST = "TRUE" to probe memory // signals. Traffic Generator will only // write to one single location and no // read transactions will be generated. parameter SIMULATION = "TRUE"; // PRBS_DATA_MODE can only be used together with either PRBS_ADDR or SEQUENTIAL_ADDR // FIXED_DATA_MODE is designed to work with FIXED_ADDR parameter ADDR_MODE = 3; //FIXED_ADDR = 2'b01; //PRBS_ADDR = 2'b10; //SEQUENTIAL_ADDR = 2'b11; parameter DATA_MODE = 2; // To change simulation data pattern // FIXED_DATA_MODE = 4'b0001; // ADDR_DATA_MODE = 4'b0010; // HAMMER_DATA_MODE = 4'b0011; // NEIGHBOR_DATA_MODE = 4'b0100; // WALKING1_DATA_MODE = 4'b0101; // WALKING0_DATA_MODE = 4'b0110; // PRBS_DATA_MODE = 4'b0111; parameter TST_MEM_INSTR_MODE = "R_W_INSTR_MODE"; // available instruction modes: //"FIXED_INSTR_R_MODE" // "FIXED_INSTR_W_MODE" // "R_W_INSTR_MODE" parameter DATA_PATTERN = "DGEN_ALL"; // DATA_PATTERN shoule be set to "DGEN_ALL" // unless it is targeted for S6 small device. // "DGEN_HAMMER", "DGEN_WALKING1", // "DGEN_WALKING0","DGEN_ADDR"," // "DGEN_NEIGHBOR","DGEN_PRBS","DGEN_ALL" parameter CMD_PATTERN = "CGEN_ALL"; // CMD_PATTERN shoule be set to "CGEN_ALL" // unless it is targeted for S6 small device. // "CGEN_RPBS","CGEN_FIXED","CGEN_BRAM", // "CGEN_SEQUENTIAL", "CGEN_ALL" parameter BEGIN_ADDRESS = 32'h00000000; parameter PRBS_SADDR_MASK_POS = 32'h00000000; parameter END_ADDRESS = 32'h000003ff; parameter PRBS_EADDR_MASK_POS = 32'hfffffc00; parameter SEL_VICTIM_LINE = 11; //**************************************************************************// // Local parameters Declarations //**************************************************************************// localparam real TPROP_DQS = 0.00; // Delay for DQS signal during Write Operation localparam real TPROP_DQS_RD = 0.00; // Delay for DQS signal during Read Operation localparam real TPROP_PCB_CTRL = 0.00; // Delay for Address and Ctrl signals localparam real TPROP_PCB_DATA = 0.00; // Delay for data signal during Write operation localparam real TPROP_PCB_DATA_RD = 0.00; // Delay for data signal during Read operation localparam MEMORY_WIDTH = 8; localparam NUM_COMP = DQ_WIDTH/MEMORY_WIDTH; localparam real CLK_PERIOD = tCK; localparam real REFCLK_PERIOD = (1000000.0/(2*REFCLK_FREQ)); localparam DRAM_DEVICE = "SODIMM"; // DRAM_TYPE: "UDIMM", "RDIMM", "COMPS" // VT delay change options/settings localparam VT_ENABLE = "OFF"; // Enable VT delay var's localparam VT_RATE = CLK_PERIOD/500; // Size of each VT step localparam VT_UPDATE_INTERVAL = CLK_PERIOD*50; // Update interval localparam VT_MAX = CLK_PERIOD/40; // Maximum VT shift function integer STR_TO_INT; input [7:0] in; begin if(in == "8") STR_TO_INT = 8; else if(in == "4") STR_TO_INT = 4; else STR_TO_INT = 0; end endfunction localparam APP_DATA_WIDTH = PAYLOAD_WIDTH * 4; localparam APP_MASK_WIDTH = APP_DATA_WIDTH / 8; localparam BURST_LENGTH = STR_TO_INT(BURST_MODE); //**************************************************************************// // Wire Declarations //**************************************************************************// reg app_en; wire app_ack; reg[31:0] app_instr; wire iq_full; wire processing_iseq; //Data read back Interface wire rdback_fifo_empty; reg rdback_fifo_rden; wire[255:0] rdback_data; reg sys_clk; reg clk_ref; reg sys_rst_n; wire sys_clk_p; wire sys_clk_n; wire clk_ref_p; wire clk_ref_n; reg [DM_WIDTH-1:0] ddr3_dm_sdram_tmp; wire sys_rst; wire error; wire phy_init_done; wire ddr3_parity; wire ddr3_reset_n; wire sda; wire scl; wire [DQ_WIDTH-1:0] ddr3_dq_fpga; wire [ROW_WIDTH-1:0] ddr3_addr_fpga; wire [BANK_WIDTH-1:0] ddr3_ba_fpga; wire ddr3_ras_n_fpga; wire ddr3_cas_n_fpga; wire ddr3_we_n_fpga; wire [(CS_WIDTH*nCS_PER_RANK)-1:0] ddr3_cs_n_fpga; wire [(CS_WIDTH*nCS_PER_RANK)-1:0] ddr3_odt_fpga; wire [CKE_WIDTH-1:0] ddr3_cke_fpga; wire [DM_WIDTH-1:0] ddr3_dm_fpga; wire [DQS_WIDTH-1:0] ddr3_dqs_p_fpga; wire [DQS_WIDTH-1:0] ddr3_dqs_n_fpga; wire [CK_WIDTH-1:0] ddr3_ck_p_fpga; wire [CK_WIDTH-1:0] ddr3_ck_n_fpga; wire [DQ_WIDTH-1:0] ddr3_dq_sdram; reg [ROW_WIDTH-1:0] ddr3_addr_sdram; reg [BANK_WIDTH-1:0] ddr3_ba_sdram; reg ddr3_ras_n_sdram; reg ddr3_cas_n_sdram; reg ddr3_we_n_sdram; reg [(CS_WIDTH*nCS_PER_RANK)-1:0] ddr3_cs_n_sdram; reg [(CS_WIDTH*nCS_PER_RANK)-1:0] ddr3_odt_sdram; reg [CKE_WIDTH-1:0] ddr3_cke_sdram; wire [DM_WIDTH-1:0] ddr3_dm_sdram; wire [DQS_WIDTH-1:0] ddr3_dqs_p_sdram; wire [DQS_WIDTH-1:0] ddr3_dqs_n_sdram; reg [CK_WIDTH-1:0] ddr3_ck_p_sdram; reg [CK_WIDTH-1:0] ddr3_ck_n_sdram; reg [ROW_WIDTH-1:0] ddr3_addr_r; reg [BANK_WIDTH-1:0] ddr3_ba_r; reg ddr3_ras_n_r; reg ddr3_cas_n_r; reg ddr3_we_n_r; reg [(CS_WIDTH*nCS_PER_RANK)-1:0] ddr3_cs_n_r; reg [(CS_WIDTH*nCS_PER_RANK)-1:0] ddr3_odt_r; reg [CKE_WIDTH-1:0] ddr3_cke_r; wire clk; wire rst; wire app_sz; wire [ADDR_WIDTH-1:0] app_addr; wire app_wdf_wren; wire [APP_DATA_WIDTH-1:0] app_wdf_data; wire [APP_MASK_WIDTH-1:0] app_wdf_mask; wire app_wdf_end; wire app_rd_data_end; wire app_rd_data_valid; wire [6:0] tg_wr_fifo_counts; wire [6:0] tg_rd_fifo_counts; wire tg_rd_en; wire [APP_DATA_WIDTH-1:0] app_rd_data; wire [31:0] tpt_hdata; wire t_gen_run_traffic; wire [31:0] t_gen_start_addr; wire [31:0] t_gen_end_addr; wire [31:0] t_gen_cmd_seed; wire [31:0] t_gen_data_seed; wire t_gen_load_seed; wire [2:0] t_gen_addr_mode; wire [3:0] t_gen_instr_mode; wire [1:0] t_gen_bl_mode; wire [3:0] t_gen_data_mode; wire t_gen_mode_load; wire [5:0] t_gen_fixed_bl; wire [2:0] t_gen_fixed_instr; wire [31:0] t_gen_fixed_addr; wire manual_clear_error; wire modify_enable_sel; wire [2:0] vio_data_mode; wire [2:0] vio_addr_mode; //**************************************************************************// // Clock generation and reset //**************************************************************************// initial begin sys_clk = 1'b0; clk_ref = 1'b1; sys_rst_n = 1'b0; #120000 sys_rst_n = 1'b1; end assign sys_rst = RST_ACT_LOW ? sys_rst_n : ~sys_rst_n; // Generate system clock = twice rate of CLK always sys_clk = #(CLK_PERIOD/2.0) ~sys_clk; // Generate IDELAYCTRL reference clock (200MHz) always clk_ref = #REFCLK_PERIOD ~clk_ref; assign sys_clk_p = sys_clk; assign sys_clk_n = ~sys_clk; assign clk_ref_p = clk_ref; assign clk_ref_n = ~clk_ref; //**************************************************************************// always @( * ) begin ddr3_ck_p_sdram <= #(TPROP_PCB_CTRL) ddr3_ck_p_fpga; ddr3_ck_n_sdram <= #(TPROP_PCB_CTRL) ddr3_ck_n_fpga; ddr3_addr_sdram <= #(TPROP_PCB_CTRL) ddr3_addr_fpga; ddr3_ba_sdram <= #(TPROP_PCB_CTRL) ddr3_ba_fpga; ddr3_ras_n_sdram <= #(TPROP_PCB_CTRL) ddr3_ras_n_fpga; ddr3_cas_n_sdram <= #(TPROP_PCB_CTRL) ddr3_cas_n_fpga; ddr3_we_n_sdram <= #(TPROP_PCB_CTRL) ddr3_we_n_fpga; ddr3_cs_n_sdram <= #(TPROP_PCB_CTRL) ddr3_cs_n_fpga; ddr3_cke_sdram <= #(TPROP_PCB_CTRL) ddr3_cke_fpga; ddr3_odt_sdram <= #(TPROP_PCB_CTRL) ddr3_odt_fpga; ddr3_dm_sdram_tmp <= #(TPROP_PCB_DATA) ddr3_dm_fpga;//DM signal generation end assign ddr3_dm_sdram = {DM_WIDTH{1'b0}}; // Controlling the bi-directional BUS genvar dqwd; generate for (dqwd = 1;dqwd < DQ_WIDTH;dqwd = dqwd+1) begin : dq_delay WireDelay # ( .Delay_g (TPROP_PCB_DATA), .Delay_rd (TPROP_PCB_DATA_RD), .ERR_INSERT ("OFF") ) u_delay_dq ( .A (ddr3_dq_fpga[dqwd]), .B (ddr3_dq_sdram[dqwd]), .reset (sys_rst_n), .phy_init_done (phy_init_done) ); end WireDelay # ( .Delay_g (TPROP_PCB_DATA), .Delay_rd (TPROP_PCB_DATA_RD), .ERR_INSERT (ECC) ) u_delay_dq_0 ( .A (ddr3_dq_fpga[0]), .B (ddr3_dq_sdram[0]), .reset (sys_rst_n), .phy_init_done (phy_init_done) ); endgenerate genvar dqswd; generate for (dqswd = 0;dqswd < DQS_WIDTH;dqswd = dqswd+1) begin : dqs_delay WireDelay # ( .Delay_g (TPROP_DQS), .Delay_rd (TPROP_DQS_RD), .ERR_INSERT ("OFF") ) u_delay_dqs_p ( .A (ddr3_dqs_p_fpga[dqswd]), .B (ddr3_dqs_p_sdram[dqswd]), .reset (sys_rst_n), .phy_init_done (phy_init_done) ); WireDelay # ( .Delay_g (TPROP_DQS), .Delay_rd (TPROP_DQS_RD), .ERR_INSERT ("OFF") ) u_delay_dqs_n ( .A (ddr3_dqs_n_fpga[dqswd]), .B (ddr3_dqs_n_sdram[dqswd]), .reset (sys_rst_n), .phy_init_done (phy_init_done) ); end endgenerate assign sda = 1'b1; assign scl = 1'b1; // Instantiate the Unit Under Test (UUT) softMC_top # ( .nCK_PER_CLK (nCK_PER_CLK), .tCK (tCK), .RST_ACT_LOW (RST_ACT_LOW), .REFCLK_FREQ (REFCLK_FREQ), .IODELAY_GRP (IODELAY_GRP), .INPUT_CLK_TYPE (INPUT_CLK_TYPE), .BANK_WIDTH (BANK_WIDTH), .CK_WIDTH (CK_WIDTH), .CKE_WIDTH (CKE_WIDTH), .COL_WIDTH (COL_WIDTH), .nCS_PER_RANK (nCS_PER_RANK), .DQ_WIDTH (DQ_WIDTH), .DQS_CNT_WIDTH (DQS_CNT_WIDTH), .DQS_WIDTH (DQS_WIDTH), .ROW_WIDTH (ROW_WIDTH), .RANK_WIDTH (RANK_WIDTH), .CS_WIDTH (CS_WIDTH), .BURST_MODE (BURST_MODE), .BM_CNT_WIDTH (BM_CNT_WIDTH), .CLKFBOUT_MULT_F (CLKFBOUT_MULT_F), .DIVCLK_DIVIDE (DIVCLK_DIVIDE), .CLKOUT_DIVIDE (CLKOUT_DIVIDE), .OUTPUT_DRV (OUTPUT_DRV), .REG_CTRL (REG_CTRL), .RTT_NOM (RTT_NOM), .RTT_WR (RTT_WR), .SIM_BYPASS_INIT_CAL (SIM_BYPASS_INIT_CAL), .DEBUG_PORT (DEBUG_PORT), .tPRDI (tPRDI), .tREFI (tREFI), .tZQI (tZQI), .ADDR_CMD_MODE (ADDR_CMD_MODE), .ORDERING (ORDERING), .STARVE_LIMIT (STARVE_LIMIT), .ADDR_WIDTH (ADDR_WIDTH), .ECC (ECC), .ECC_TEST (ECC_TEST), .TCQ (TCQ), .DATA_WIDTH (DATA_WIDTH), .PAYLOAD_WIDTH (PAYLOAD_WIDTH) ) uut ( .sys_clk_p(sys_clk_p), .sys_clk_n(sys_clk_n), .clk_ref_p(clk_ref_p), .clk_ref_n(clk_ref_n), .sys_rst(sys_rst), .sys_reset_n(1'b1), .ddr_ck_p(ddr3_ck_p_fpga), .ddr_ck_n(ddr3_ck_n_fpga), .ddr_addr(ddr3_addr_fpga), .ddr_ba(ddr3_ba_fpga), .ddr_ras_n(ddr3_ras_n_fpga), .ddr_cas_n(ddr3_cas_n_fpga), .ddr_we_n(ddr3_we_n_fpga), .ddr_cs_n(ddr3_cs_n_fpga), .ddr_cke(ddr3_cke_fpga), .ddr_odt(ddr3_odt_fpga), .ddr_reset_n(ddr3_reset_n), //.ddr_parity(), .ddr_dm(), .ddr_dqs_p(ddr3_dqs_p_fpga), .ddr_dqs_n(ddr3_dqs_n_fpga), .ddr_dq(ddr3_dq_fpga), .dfi_init_complete(phy_init_done), .iq_full(iq_full), .processing_iseq(processing_iseq), .app_en(app_en), .app_ack(app_ack), .app_instr(app_instr), .rdback_fifo_rden(rdback_fifo_rden), .rdback_data(rdback_data), .rdback_fifo_empty(rdback_fifo_empty) ); // Extra one clock pipelining for RDIMM address and // control signals is implemented here (Implemented external to memory model) always @( posedge ddr3_ck_p_sdram[0] ) begin if ( ddr3_reset_n == 1'b0 ) begin ddr3_ras_n_r <= 1'b1; ddr3_cas_n_r <= 1'b1; ddr3_we_n_r <= 1'b1; ddr3_cs_n_r <= {(CS_WIDTH*nCS_PER_RANK){1'b1}}; ddr3_odt_r <= 1'b0; end else begin ddr3_addr_r <= #(CLK_PERIOD/2) ddr3_addr_sdram; ddr3_ba_r <= #(CLK_PERIOD/2) ddr3_ba_sdram; ddr3_ras_n_r <= #(CLK_PERIOD/2) ddr3_ras_n_sdram; ddr3_cas_n_r <= #(CLK_PERIOD/2) ddr3_cas_n_sdram; ddr3_we_n_r <= #(CLK_PERIOD/2) ddr3_we_n_sdram; if (~(ddr3_cs_n_sdram[0] | ddr3_cs_n_sdram[1]) & ~phy_init_done) ddr3_cs_n_r <= #(CLK_PERIOD/2) {(CS_WIDTH*nCS_PER_RANK){1'b1}}; else ddr3_cs_n_r <= #(CLK_PERIOD/2) ddr3_cs_n_sdram; ddr3_odt_r <= #(CLK_PERIOD/2) ddr3_odt_sdram; end end // to avoid tIS violations on CKE when reset is deasserted always @( posedge ddr3_ck_n_sdram[0] ) if ( ddr3_reset_n == 1'b0 ) ddr3_cke_r <= 1'b0; else ddr3_cke_r <= #(CLK_PERIOD) ddr3_cke_sdram; //*************************************************************************** // Instantiate memories //*************************************************************************** genvar r,i,dqs_x; generate if(DRAM_DEVICE == "COMP") begin : comp_inst for (r = 0; r < CS_WIDTH; r = r+1) begin: mem_rnk if(MEMORY_WIDTH == 16) begin: mem_16 if(DQ_WIDTH/16) begin: gen_mem for (i = 0; i < NUM_COMP; i = i + 1) begin: gen_mem ddr3_model u_comp_ddr3 ( .rst_n (ddr3_reset_n), .ck (ddr3_ck_p_sdram), .ck_n (ddr3_ck_n_sdram), .cke (ddr3_cke_sdram[r]), .cs_n (ddr3_cs_n_sdram[r]), .ras_n (ddr3_ras_n_sdram), .cas_n (ddr3_cas_n_sdram), .we_n (ddr3_we_n_sdram), .dm_tdqs (ddr3_dm_sdram[(2*(i+1)-1):(2*i)]), .ba (ddr3_ba_sdram), .addr (ddr3_addr_sdram), .dq (ddr3_dq_sdram[16*(i+1)-1:16*(i)]), .dqs (ddr3_dqs_p_sdram[(2*(i+1)-1):(2*i)]), .dqs_n (ddr3_dqs_n_sdram[(2*(i+1)-1):(2*i)]), .tdqs_n (), .odt (ddr3_odt_sdram[r]) ); end end if (DQ_WIDTH%16) begin: gen_mem_extrabits ddr3_model u_comp_ddr3 ( .rst_n (ddr3_reset_n), .ck (ddr3_ck_p_sdram), .ck_n (ddr3_ck_n_sdram), .cke (ddr3_cke_sdram[r]), .cs_n (ddr3_cs_n_sdram[r]), .ras_n (ddr3_ras_n_sdram), .cas_n (ddr3_cas_n_sdram), .we_n (ddr3_we_n_sdram), .dm_tdqs ({ddr3_dm_sdram[DM_WIDTH-1],ddr3_dm_sdram[DM_WIDTH-1]}), .ba (ddr3_ba_sdram), .addr (ddr3_addr_sdram), .dq ({ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)], ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)]}), .dqs ({ddr3_dqs_p_sdram[DQS_WIDTH-1], ddr3_dqs_p_sdram[DQS_WIDTH-1]}), .dqs_n ({ddr3_dqs_n_sdram[DQS_WIDTH-1], ddr3_dqs_n_sdram[DQS_WIDTH-1]}), .tdqs_n (), .odt (ddr3_odt_sdram[r]) ); end end else if((MEMORY_WIDTH == 8) || (MEMORY_WIDTH == 4)) begin: mem_8_4 for (i = 0; i < NUM_COMP; i = i + 1) begin: gen_mem ddr3_model u_comp_ddr3 ( .rst_n (ddr3_reset_n), .ck (ddr3_ck_p_sdram), .ck_n (ddr3_ck_n_sdram), .cke (ddr3_cke_sdram[r]), .cs_n (ddr3_cs_n_sdram[r]), .ras_n (ddr3_ras_n_sdram), .cas_n (ddr3_cas_n_sdram), .we_n (ddr3_we_n_sdram), .dm_tdqs (ddr3_dm_sdram[i]), .ba (ddr3_ba_sdram), .addr (ddr3_addr_sdram), .dq (ddr3_dq_sdram[MEMORY_WIDTH*(i+1)-1:MEMORY_WIDTH*(i)]), .dqs (ddr3_dqs_p_sdram[i]), .dqs_n (ddr3_dqs_n_sdram[i]), .tdqs_n (), .odt (ddr3_odt_sdram[r]) ); end end end end else if(DRAM_DEVICE == "RDIMM") begin: rdimm_inst for (r = 0; r < CS_WIDTH; r = r+1) begin: mem_rnk if((MEMORY_WIDTH == 8) || (MEMORY_WIDTH == 4)) begin: mem_8_4 for (i = 0; i < NUM_COMP; i = i + 1) begin: gen_mem ddr3_model u_comp_ddr3 ( .rst_n (ddr3_reset_n), .ck (ddr3_ck_p_sdram[(i*MEMORY_WIDTH)/72]), .ck_n (ddr3_ck_n_sdram[(i*MEMORY_WIDTH)/72]), .cke (ddr3_cke_r[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]), .cs_n (ddr3_cs_n_r[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]), .ras_n (ddr3_ras_n_r), .cas_n (ddr3_cas_n_r), .we_n (ddr3_we_n_r), .dm_tdqs (ddr3_dm_sdram[i]), .ba (ddr3_ba_r), .addr (ddr3_addr_r), .dq (ddr3_dq_sdram[MEMORY_WIDTH*(i+1)-1:MEMORY_WIDTH*(i)]), .dqs (ddr3_dqs_p_sdram[i]), .dqs_n (ddr3_dqs_n_sdram[i]), .tdqs_n (), .odt (ddr3_odt_r[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]) ); end end end end else if(DRAM_DEVICE == "UDIMM") begin: udimm_inst for (r = 0; r < CS_WIDTH; r = r+1) begin: mem_rnk if(MEMORY_WIDTH == 16) begin: mem_16 if(DQ_WIDTH/16) begin: gen_mem for (i = 0; i < NUM_COMP; i = i + 1) begin: gen_mem ddr3_model u_comp_ddr3 ( .rst_n (ddr3_reset_n), .ck (ddr3_ck_p_sdram[(i*MEMORY_WIDTH)/72]), .ck_n (ddr3_ck_n_sdram[(i*MEMORY_WIDTH)/72]), .cke (ddr3_cke_sdram[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]), .cs_n (ddr3_cs_n_sdram[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]), .ras_n (ddr3_ras_n_sdram), .cas_n (ddr3_cas_n_sdram), .we_n (ddr3_we_n_sdram), .dm_tdqs (ddr3_dm_sdram[(2*(i+1)-1):(2*i)]), .ba (ddr3_ba_sdram), .addr (ddr3_addr_sdram), .dq (ddr3_dq_sdram[MEMORY_WIDTH*(i+1)-1:MEMORY_WIDTH*(i)]), .dqs (ddr3_dqs_p_sdram[(2*(i+1)-1):(2*i)]), .dqs_n (ddr3_dqs_n_sdram[(2*(i+1)-1):(2*i)]), .tdqs_n (), .odt (ddr3_odt_sdram[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]) ); end end if (DQ_WIDTH%16) begin: gen_mem_extrabits ddr3_model u_comp_ddr3 ( .rst_n (ddr3_reset_n), .ck (ddr3_ck_p_sdram[(DQ_WIDTH-1)/72]), .ck_n (ddr3_ck_n_sdram[(DQ_WIDTH-1)/72]), .cke (ddr3_cke_sdram[((DQ_WIDTH-1)/72)+(nCS_PER_RANK*r)]), .cs_n (ddr3_cs_n_sdram[((DQ_WIDTH-1)/72)+(nCS_PER_RANK*r)]), .ras_n (ddr3_ras_n_sdram), .cas_n (ddr3_cas_n_sdram), .we_n (ddr3_we_n_sdram), .dm_tdqs ({ddr3_dm_sdram[DM_WIDTH-1],ddr3_dm_sdram[DM_WIDTH-1]}), .ba (ddr3_ba_sdram), .addr (ddr3_addr_sdram), .dq ({ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)], ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)]}), .dqs ({ddr3_dqs_p_sdram[DQS_WIDTH-1], ddr3_dqs_p_sdram[DQS_WIDTH-1]}), .dqs_n ({ddr3_dqs_n_sdram[DQS_WIDTH-1], ddr3_dqs_n_sdram[DQS_WIDTH-1]}), .tdqs_n (), .odt (ddr3_odt_sdram[((DQ_WIDTH-1)/72)+(nCS_PER_RANK*r)]) ); end end else if((MEMORY_WIDTH == 8) || (MEMORY_WIDTH == 4)) begin: mem_8_4 for (i = 0; i < NUM_COMP; i = i + 1) begin: gen_mem ddr3_model u_comp_ddr3 ( .rst_n (ddr3_reset_n), .ck (ddr3_ck_p_sdram[(i*MEMORY_WIDTH)/72]), .ck_n (ddr3_ck_n_sdram[(i*MEMORY_WIDTH)/72]), .cke (ddr3_cke_sdram[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]), .cs_n (ddr3_cs_n_sdram[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]), .ras_n (ddr3_ras_n_sdram), .cas_n (ddr3_cas_n_sdram), .we_n (ddr3_we_n_sdram), .dm_tdqs (ddr3_dm_sdram[i]), .ba (ddr3_ba_sdram), .addr (ddr3_addr_sdram), .dq (ddr3_dq_sdram[MEMORY_WIDTH*(i+1)-1:MEMORY_WIDTH*(i)]), .dqs (ddr3_dqs_p_sdram[i]), .dqs_n (ddr3_dqs_n_sdram[i]), .tdqs_n (), .odt (ddr3_odt_sdram[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]) ); end end end end else if(DRAM_DEVICE == "SODIMM") begin: sodimm_inst for (r = 0; r < CS_WIDTH; r = r+1) begin: mem_rnk if(MEMORY_WIDTH == 16) begin: mem_16 if(DQ_WIDTH/16) begin: gen_mem for (i = 0; i < NUM_COMP; i = i + 1) begin: gen_mem ddr3_model u_comp_ddr3 ( .rst_n (ddr3_reset_n), .ck (ddr3_ck_p_sdram[(i*MEMORY_WIDTH)/72]), .ck_n (ddr3_ck_n_sdram[(i*MEMORY_WIDTH)/72]), .cke (ddr3_cke_sdram[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]), .cs_n (ddr3_cs_n_sdram[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]), .ras_n (ddr3_ras_n_sdram), .cas_n (ddr3_cas_n_sdram), .we_n (ddr3_we_n_sdram), .dm_tdqs (ddr3_dm_sdram[(2*(i+1)-1):(2*i)]), .ba (ddr3_ba_sdram), .addr (ddr3_addr_sdram), .dq (ddr3_dq_sdram[MEMORY_WIDTH*(i+1)-1:MEMORY_WIDTH*(i)]), .dqs (ddr3_dqs_p_sdram[(2*(i+1)-1):(2*i)]), .dqs_n (ddr3_dqs_n_sdram[(2*(i+1)-1):(2*i)]), .tdqs_n (), .odt (ddr3_odt_sdram[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]) ); end end if (DQ_WIDTH%16) begin: gen_mem_extrabits ddr3_model u_comp_ddr3 ( .rst_n (ddr3_reset_n), .ck (ddr3_ck_p_sdram[(DQ_WIDTH-1)/72]), .ck_n (ddr3_ck_n_sdram[(DQ_WIDTH-1)/72]), .cke (ddr3_cke_sdram[((DQ_WIDTH-1)/72)+(nCS_PER_RANK*r)]), .cs_n (ddr3_cs_n_sdram[((DQ_WIDTH-1)/72)+(nCS_PER_RANK*r)]), .ras_n (ddr3_ras_n_sdram), .cas_n (ddr3_cas_n_sdram), .we_n (ddr3_we_n_sdram), .dm_tdqs ({ddr3_dm_sdram[DM_WIDTH-1],ddr3_dm_sdram[DM_WIDTH-1]}), .ba (ddr3_ba_sdram), .addr (ddr3_addr_sdram), .dq ({ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)], ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)]}), .dqs ({ddr3_dqs_p_sdram[DQS_WIDTH-1], ddr3_dqs_p_sdram[DQS_WIDTH-1]}), .dqs_n ({ddr3_dqs_n_sdram[DQS_WIDTH-1], ddr3_dqs_n_sdram[DQS_WIDTH-1]}), .tdqs_n (), .odt (ddr3_odt_sdram[((DQ_WIDTH-1)/72)+(nCS_PER_RANK*r)]) ); end end if((MEMORY_WIDTH == 8) || (MEMORY_WIDTH == 4)) begin: mem_8_4 for (i = 0; i < NUM_COMP; i = i + 1) begin: gen_mem ddr3_model u_comp_ddr3 ( .rst_n (ddr3_reset_n), .ck (ddr3_ck_p_sdram[(i*MEMORY_WIDTH)/72]), .ck_n (ddr3_ck_n_sdram[(i*MEMORY_WIDTH)/72]), .cke (ddr3_cke_sdram[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]), .cs_n (ddr3_cs_n_sdram[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]), .ras_n (ddr3_ras_n_sdram), .cas_n (ddr3_cas_n_sdram), .we_n (ddr3_we_n_sdram), .dm_tdqs (ddr3_dm_sdram[i]), .ba (ddr3_ba_sdram), .addr (ddr3_addr_sdram), .dq (ddr3_dq_sdram[MEMORY_WIDTH*(i+1)-1:MEMORY_WIDTH*(i)]), .dqs (ddr3_dqs_p_sdram[i]), .dqs_n (ddr3_dqs_n_sdram[i]), .tdqs_n (), .odt (ddr3_odt_sdram[((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)]) ); end end end end endgenerate //*************************************************************************** // Reporting the test case status //*************************************************************************** localparam APP_CLK_PERIOD = tCK * nCK_PER_CLK; initial begin : Logging app_en = 0; rdback_fifo_rden = 0; begin : calibration_done wait (phy_init_done); $display("Calibration Done"); #1000000; app_en = 0; #(APP_CLK_PERIOD*1000); #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b00010000000000000000000000000010; //busdir #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b01000000000000000000000000000101; //wait #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b10010001000100110000000000000000; //act #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b01000000000000000000000000000110; //wait #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b10010001000110110000000010110010; //read #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b01000000000000000000000000000101; //wait #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b10101101001000111000000000001110; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b01000000000000000000000000000110; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b11010011001000110100000000001000; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b01000000000000000000000000001010; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b10010001000100110000000000000000; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b01000000000000000000000000000101; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b00010000000000000000000000000000; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b01000000000000000000000000000101; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b10010001000110110000000010110010; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b01000000000000000000000000000101; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b10000001001010110000000000001000; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b01000000000000000000000000001010; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b01000000000000000000000000000011; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b10010001000100110000000000000000; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b01000000000000000000000000000101; #APP_CLK_PERIOD; app_en = 1; app_instr = 32'b00000000000000000000000000000000; #APP_CLK_PERIOD; app_en = 0; end end endmodule ================================================ FILE: sw/RetentionTest/Makefile ================================================ program_NAME := SoftMC_RetentionTest program_CXX_SRCS := $(wildcard *.cpp) $(wildcard ../SoftMC_API/*.cpp) program_CXX_OBJS := ${program_CXX_SRCS:.cpp=.o} program_OBJS := $(program_CXX_OBJS) program_INCLUDE_DIRS := ../SoftMC_API program_LIBRARY_DIRS := program_LIBRARIES := riffa CPPFLAGS += -g -std=c++11 CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir)) LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library)) CC=g++ .PHONY: all clean distclean all: $(program_NAME) $(program_NAME): $(program_OBJS) $(CC) $(CPPFLAGS) $(program_OBJS) -o $(program_NAME) $(LDFLAGS) clean: @- $(RM) $(program_NAME) @- $(RM) $(program_OBJS) distclean: clean ================================================ FILE: sw/RetentionTest/RetentionTest.cpp ================================================ #include #include #include #include #include #include #include "softmc.h" using namespace std; //Note that capacity of the instruction buffer is 8192 instructions void writeRow(fpga_t* fpga, uint row, uint bank, uint8_t pattern, InstructionSequence*& iseq){ if(iseq == nullptr) iseq = new InstructionSequence(); else iseq->size = 0;//reuse the provided InstructionSequence to avoid dynamic allocation on each call //Precharge target bank (just in case if its left activated) iseq->insert(genPRE(bank, PRE_TYPE::SINGLE)); //Wait for tRP iseq->insert(genWAIT(5));//2.5ns have already been passed as we issue in next cycle. So, 5 means 6 cycles latency, 15 ns //Activate target row iseq->insert(genACT(bank, row)); //Wait for tRCD iseq->insert(genWAIT(5)); //Write to the entire row for(int i = 0; i < NUM_COLS; i+=8){ //we use 8x burst mode iseq->insert(genWR(bank, i, pattern)); //We need to wait for tCL and 4 cycles burst (double data-rate) iseq->insert(genWAIT(6 + 4)); } //Wait some more in any case iseq->insert(genWAIT(3)); //Precharge target bank iseq->insert(genPRE(bank, PRE_TYPE::SINGLE)); //Wait for tRP iseq->insert(genWAIT(5));//we have already 2.5ns passed as we issue in next cycle. So, 5 means 6 cycles latency, 15 ns //START Transaction iseq->insert(genEND()); iseq->execute(fpga); } void readAndCompareRow(fpga_t* fpga, const uint row, const uint bank, const uint8_t pattern, InstructionSequence*& iseq){ if(iseq == nullptr) iseq = new InstructionSequence(); else iseq->size = 0;//reuse the provided InstructionSequence to avoid dynamic allocation for each call //Precharge target bank (just in case if its left activated) iseq->insert(genPRE(bank, PRE_TYPE::SINGLE)); //Wait for tRP iseq->insert(genWAIT(5));//2.5ns have already been passed as we issue in next cycle. So, 5 means 6 cycles latency, 15 ns //Activate target row iseq->insert(genACT(bank, row)); //Wait for tRCD iseq->insert(genWAIT(5)); //Read the entire row for(int i = 0; i < NUM_COLS; i+=8){ //we use 8x burst mode iseq->insert(genRD(bank, i)); //We need to wait for tCL and 4 cycles burst (double data-rate) iseq->insert(genWAIT(6 + 4)); } //Wait some more in any case iseq->insert(genWAIT(3)); //Precharge target bank iseq->insert(genPRE(bank, PRE_TYPE::SINGLE)); //pre 1 -> precharge all, pre 0 precharge bank //Wait for tRP iseq->insert(genWAIT(5));//we have already 2.5ns passed as we issue in next cycle. So, 5 means 6 cycles latency, 15 ns //START Transaction iseq->insert(genEND()); iseq->execute(fpga); //Receive the data uint rbuf[16]; for(int i = 0; i < NUM_COLS; i+=8){ //we receive a single burst at two times (32 bytes each) fpga_recv(fpga, 0, (void*)rbuf, 16, 0); //compare with the pattern uint8_t* rbuf8 = (uint8_t *) rbuf; for(int j = 0; j < 64; j++){ if(rbuf8[j] != pattern) fprintf(stderr, "Error at Col: %d, Row: %u, Bank: %u, DATA: %x \n", i, row, bank, rbuf8[j]); } } } void turnBus(fpga_t* fpga, BUSDIR b, InstructionSequence* iseq = nullptr){ if(iseq == nullptr) iseq = new InstructionSequence(); else iseq->size = 0;//reuse the provided InstructionSequence to avoid dynamic allocation for each call iseq->insert(genBUSDIR(b)); //WAIT iseq->insert(genWAIT(5)); //START Transaction iseq->insert(genEND()); iseq->execute(fpga); } //! Runs a test to check the DRAM cells against the given retention time. /*! \param \e fpga is a pointer to the RIFFA FPGA device. \param \e retention is the retention time in milliseconds to test. */ void testRetention(fpga_t* fpga, const int retention){ uint8_t pattern = 0xff; //the data pattern that we write to the DRAM bool dimm_done = false; InstructionSequence* iseq = nullptr; // we temporarily store (before sending them to the FPGA) the generated instructions here GET_TIME_INIT(2); //writing the entire row takes approximately 5 ms uint group_size = ceil(retention/5.0f); //number of rows to be written in a single iteration uint cur_row_write = 0; uint cur_bank_write = 0; uint cur_row_read = 0; uint cur_bank_read = 0; printf("\n"); while(!dimm_done){ //continue until we cover the entire DRAM //print the number of the row that we are about to test printf("%c[2K\r", 27); printf("Current Bank: %d, Row: %d", cur_bank_write, cur_row_write); fflush(stdout); // Switch the memory bus to write mode turnBus(fpga, BUSDIR::WRITE, iseq); GET_TIME_VAL(0); // We write to a chunk of rows (group_size) successively for(int i = 0; i < group_size; i++){ // write the data pattern to the entire row writeRow(fpga, cur_row_write, cur_bank_write, pattern, iseq); cur_row_write++; // when we complete testing all of the rows in a bank, we move to the next bank if(cur_row_write == NUM_ROWS){ cur_row_write = 0; cur_bank_write++; } // the entire DIMM is covered when we complete testing all of the bank if(cur_bank_write == NUM_BANKS){ // we are done with the entire DIMM dimm_done = true; break; } } // Switch the memory bus to read mode turnBus(fpga, BUSDIR::READ, iseq); // wait for the specified retention time (retention) do{ GET_TIME_VAL(1); } while((TIME_VAL_TO_MS(1) - TIME_VAL_TO_MS(0)) < retention); // Read the data back and compare for(int i = 0; i < group_size; i++){ readAndCompareRow(fpga, cur_row_read, cur_bank_read, pattern, iseq); cur_row_read++; if(cur_row_read == NUM_ROWS){ //NUM_ROWS cur_row_read = 0; cur_bank_read++; } if(cur_bank_read == NUM_BANKS){ //NUM_BANKS //we are done with the entire DIMM break; } } } printf("\n"); delete iseq; } // provide trefi = 0 to disable auto-refresh // auto-refresh is disabled by default (disabled after FPGA boots, disables on pushing reset button) void setRefreshConfig(fpga_t* fpga, uint trefi, uint trfc){ InstructionSequence* iseq = new InstructionSequence; iseq->insert(genREF_CONFIG(trfc, REGISTER::TRFC)); iseq->insert(genREF_CONFIG(trefi, REGISTER::TREFI)); //START Transaction iseq->insert(genEND()); iseq->execute(fpga); delete iseq; } void printHelp(char* argv[]){ cout << "A sample application that tests retention time of DRAM cells using SoftMC" << endl; cout << "Usage:" << argv[0] << " [REFRESH INTERVAL]" << endl; cout << "The Refresh Interval should be a positive integer, indicating the target retention time in milliseconds." << endl; } int main(int argc, char* argv[]){ fpga_t* fpga; fpga_info_list info; int fid = 0; //fpga id int ch = 0; //channel id if(argc != 2 || strcmp(argv[1], "--help") == 0){ printHelp(argv); return -2; } string s_ref(argv[1]); int refresh_interval = 0; try{ refresh_interval = stoi(s_ref); }catch(...){ printHelp(argv); return -3; } if(refresh_interval <= 0){ printHelp(argv); return -4; } // Get the list of FPGA's attached to the system if (fpga_list(&info) != 0) { printf("Error populating fpga_info_list\n"); return -1; } printf("Number of devices: %d\n", info.num_fpgas); for (int i = 0; i < info.num_fpgas; i++) { printf("%d: id:%d\n", i, info.id[i]); printf("%d: num_chnls:%d\n", i, info.num_chnls[i]); printf("%d: name:%s\n", i, info.name[i]); printf("%d: vendor id:%04X\n", i, info.vendor_id[i]); printf("%d: device id:%04X\n", i, info.device_id[i]); } // Open an FPGA device, so we can read/write from/to it fpga = fpga_open(fid); if(!fpga){ printf("Problem on opening the fpga \n"); return -1; } printf("The FPGA has been opened successfully! \n"); // send a reset signal to the FPGA fpga_reset(fpga); //keep this, recovers FPGA from some unwanted state //uint trefi = 7800/200; //7.8us (divide by 200ns as the HW counts with that period) //uint trfc = 104; //default trfc for 4Gb device //printf("Activating AutoRefresh. tREFI: %d, tRFC: %d \n", trefi, trfc); //setRefreshConfig(fpga, trefi, trfc); printf("Starting Retention Time Test @ %d ms! \n", refresh_interval); testRetention(fpga, refresh_interval); printf("The test has been completed! \n"); fpga_close(fpga); return 0; } ================================================ FILE: sw/SoftMC_API/softmc.cpp ================================================ #include "softmc.h" #include #include #include using namespace std; InstructionSequence::InstructionSequence() : InstructionSequence(init_cap){ } InstructionSequence::InstructionSequence(const uint capacity){ instrs = new Instruction[capacity]; size = 0; this->capacity = capacity; } InstructionSequence::~InstructionSequence(){ delete[] instrs; } void InstructionSequence::insert(const Instruction c){ if(size == capacity){ Instruction* tmp = new Instruction[capacity*2]; for(int i = 0; i < size; i++) tmp[i] = instrs[i]; delete[] instrs; capacity *=2; instrs = tmp; } instrs[size++] = c; } void InstructionSequence::execute(fpga_t* fpga){ fpga_send(fpga, 0, (void*)instrs, INSTR_SIZE*size, 0, 1, 0); } //! Generates an instruction to \b activate the row at the given address. /*! \param \e bank is the bank number. \param \e row is the row number. \return The generated activate instruction */ Instruction genACT(uint bank, uint row){ Instruction instr = (uint)INSTR_TYPE::DDR; instr <<= 32 - CMD_OFFSET - BANK_OFFSET - ROW_OFFSET; instr |= 0x23; //sets CKE(1) CS(0) RAS(0) CAS(1) WE_ACT(1) instr <<= BANK_OFFSET; instr |= bank; instr <<= ROW_OFFSET; instr |= row; return instr; } //! Generates an instruction to \b precharge the given bank. /*! \param \e bank is the bank number. \param \e pc is the precharge type with default value PRE_TYPE.SINGLE. Can be \e PRE_TYPE.SINGLE for a single-bank precharge, or \e PRE_TYPE.ALL for an all-banks precharge). \return The generated precharge instruction */ Instruction genPRE(uint bank, PRE_TYPE pc){ Instruction instr = (uint)INSTR_TYPE::DDR; instr <<= 32 - CMD_OFFSET - BANK_OFFSET - ROW_OFFSET; instr |= 0x22; //to set CKE(1) CS(0) RAS(0) CAS(1) WE_PRE(0) if(pc == PRE_TYPE::ALL){ instr <<= BANK_OFFSET + ROW_OFFSET - COL_OFFSET; instr |= 0x1; instr <<= COL_OFFSET; } else{ instr <<= BANK_OFFSET; instr |= bank; instr <<= ROW_OFFSET; } return instr; } //! Generates an instruction to \b write a single byte pattern to the given bank/column address. /*! \param \e col is the column number. \param \e bank is the bank number. \param \e pattern is the byte that will be written to the entire column. \param \e ap is the auto-precharge option with default value AUTO_PRECHARGE.NO_AP. Can be \e AUTO_PRECHARGE.AP to perform precharge right after the write, or \e AUTO_PRECHARGE.NO_AP for to disable auto-precharge). \param \e bl is the burst length with default value BURST_LENGTH.FIXED. Can be \e BURST_LENGTH.FIXED to set burst length to 8, or BURST_LENGTH.CHOP to set 4. Do not forget to set MR0 appropriately to enable setting the burst length on-the-fly \return The generated write instruction */ Instruction genWR(uint bank, uint col, uint8_t pattern, AUTO_PRECHARGE ap, BURST_LENGTH bl){ Instruction instr = (uint)INSTR_TYPE::DDR; instr <<= 32 - SIGNAL_OFFSET - BANK_OFFSET - ROW_OFFSET - CMD_OFFSET; instr |= pattern >> 2; //most significant 6 bits of the pattern instr <<= SIGNAL_OFFSET; instr |= 0x24; //to set CKE(1) CS(0)[assumed it should be Low] //RAS(1) CAS(0) WE(0) instr <<= BANK_OFFSET; instr |= bank; instr <<= 2; instr |= pattern & 0x3; //least significant 2 bits of the pattern instr <<= 2; if(bl == BURST_LENGTH::FIXED) instr |= 0x1; // to set cmd[12] to 1 (burst length 8) instr <<= 2; if(ap == AUTO_PRECHARGE::AP) instr |= 0x1; // to set cmd[10] to 1 instr <<= COL_OFFSET; instr |= col; return instr; } //! Generates an instruction to \b read from the given bank/column address. /*! \param \e col is the column number. \param \e bank is the bank number. \param \e ap is the auto-precharge option with default value AUTO_PRECHARGE.NO_AP. Can be \e AUTO_PRECHARGE.AP to perform precharge right after the read, or \e AUTO_PRECHARGE.NO_AP for to disable auto-precharge). \param \e bl is the burst length with default value BURST_LENGTH.FIXED. Can be \e BURST_LENGTH.FIXED to set burst length to 8, or BURST_LENGTH.CHOP to set burst length to 4. Do not forget to set MR0 appropriately to enable setting the burst length on-the-fly. \return The generated read instruction */ Instruction genRD(uint bank, uint col, AUTO_PRECHARGE ap, BURST_LENGTH bl){ Instruction instr = 0x25; //to set CKE(1) CS(0)[assumed it should be Low] RAS(1) CAS(0) WE(1) instr <<= BANK_OFFSET; instr |= bank; instr <<= 4; if(bl == BURST_LENGTH::FIXED) instr |= 0x1; // to set cmd[12] to 1 (burst length 8) instr <<= 2; if(ap == AUTO_PRECHARGE::AP) instr |= 0x1; // to set cmd[10] to 1 instr <<= COL_OFFSET; instr |= col; Instruction instr2 = (uint)INSTR_TYPE::DDR; instr2 <<= 28; instr2 |= instr; return instr2; } //! Generates a \b wait instruction to pause issuing commands for the given //cycle count. /*! \param \e cycles is the column number. \return The generated wait instruction */ Instruction genWAIT(uint cycles){ //min 1, max 1023 assert(cycles >= 1); assert(cycles <= 1023 && "Could not wait for more than 1023 cycles since the current hardware implementation has a 10 bit counter for this purpose."); Instruction instr = (uint)INSTR_TYPE::WAIT; instr <<= 28; instr |= cycles; return instr; } //! Generates an instruction to change bus which switches DQ //pins between read or write modes. /*! \param \e dir is the new bus mode to be set. Can be BUSDIR.READ to switch to read mode, or BUSDIR.WRITE to switch to write mode. \return The generated change bus direction instruction */ Instruction genBUSDIR(BUSDIR dir){ Instruction instr = (uint)INSTR_TYPE::SET_BUS_DIR; instr <<= 28; instr |= (uint)dir; return instr; } //! Generates an instruction to indicate the end of the instruction sequence . /*! \return Instruction used to indicate the end of the instruction sequence */ Instruction genEND(){ return (Instruction)((uint)INSTR_TYPE::END_OF_INSTRS << 28); } //! Generates an instruction to initiate DDR3 \b short-ZQ calibration. /*! \return The generated short-ZQ instruction */ Instruction genZQ(){ Instruction instr = (uint)INSTR_TYPE::DDR; instr <<= 32 - CMD_OFFSET - BANK_OFFSET - ROW_OFFSET; instr |= 0x26; //to set CKE(1) CS(0) RAS(1) CAS(1) WE(0) instr <<= BANK_OFFSET + ROW_OFFSET; return instr; } //! Generates a DDR3 \b refresh instruction. /*! \return The generated refresh instruction */ Instruction genREF(){ Instruction instr = (uint)INSTR_TYPE::DDR; instr <<= 32 - CMD_OFFSET - BANK_OFFSET - ROW_OFFSET; instr |= 0x21; //to set CKE(1) CS(0) RAS(0) CAS(0) WE(1) instr <<= BANK_OFFSET + ROW_OFFSET; return instr; } //! Generates an instruction for configuring the auto-refresh mechanism. /*! \param \e val is the value to be set. \param \e r is the parameter to be configured. Can be \e MC_CMD.SET_TREFI or MC_CMD.SET_TRFC. See DDR3 datasheet for the definition of tREFI and tRFC. Set tREFI to 0 to disable auto-refresh (disabled by default). \return The generated command for auto-refresh configuration */ Instruction genREF_CONFIG(uint val, REGISTER r){ assert(val < 0x10000000); Instruction instr = (uint) r; instr <<= 28; instr |= val; return instr; } ================================================ FILE: sw/SoftMC_API/softmc.h ================================================ #ifndef SOFTMC_H #define SOFTMC_H #include #include #include #include #include #include #define GET_TIME_INIT(num) struct timeval _timers[num] #define GET_TIME_VAL(num) gettimeofday(&_timers[num], NULL) #define TIME_VAL_TO_MS(num) (((double)_timers[num].tv_sec*1000.0) + ((double)_timers[num].tv_usec/1000.0)) #define BANK_OFFSET 3 #define ROW_OFFSET 16 #define CMD_OFFSET 4 #define COL_OFFSET 10 #define SIGNAL_OFFSET 6 // The current instruction format is 32 bits wide. But we allocate // 64 bits (2 words) for each instruction to keep the hardware simple. // Having C_PCI_DATA_WIDTH of 64 performs better than 32 when sending // data that we read from the DRAM back to the host machine. // TODO: modify the hardware to support 32-bit instructions. #define INSTR_SIZE 2 //2 words #define NUM_ROWS 32768 #define NUM_COLS 1024 #define NUM_BANKS 8 typedef uint64_t Instruction; typedef uint32_t uint; //DO NOT EDIT (unless you change the verilog code) enum class INSTR_TYPE { END_OF_INSTRS = 0, SET_BUS_DIR = 1, WAIT = 4, DDR = 8 }; //END - DO NOT EDIT enum class BUSDIR { READ = 0, WRITE = 2 }; enum class AUTO_PRECHARGE { NO_AP = 0, AP = 1 }; enum class PRE_TYPE { SINGLE = 0, ALL = 1 }; enum class BURST_LENGTH { CHOP = 0, FIXED = 1 }; enum class REGISTER { TREFI = 2, TRFC = 3 }; class InstructionSequence{ public: InstructionSequence(); InstructionSequence(const uint capacity); virtual ~InstructionSequence(); void insert(const Instruction c); void execute(fpga_t* fpga); uint size; Instruction* instrs; private: uint capacity; const static uint init_cap = 256; }; class DramAddr{ public: uint row; uint bank; DramAddr() : DramAddr(0, 0){} DramAddr(uint row, uint bank){ this->row = row; this->bank = bank;} }; Instruction genACT(uint bank, uint row); Instruction genPRE(uint bank, PRE_TYPE pt = PRE_TYPE::SINGLE); Instruction genWR(uint bank, uint col, uint8_t pattern, AUTO_PRECHARGE ap = AUTO_PRECHARGE::NO_AP, BURST_LENGTH bl = BURST_LENGTH::FIXED); Instruction genRD(uint bank, uint col, AUTO_PRECHARGE ap = AUTO_PRECHARGE::NO_AP, BURST_LENGTH bl = BURST_LENGTH::FIXED); Instruction genWAIT(uint cycles); Instruction genBUSDIR(BUSDIR dir); Instruction genEND(); Instruction genZQ(); Instruction genREF(); Instruction genREF_CONFIG(uint val, REGISTER r); #endif //SOFTMC_H ================================================ FILE: sw/riffa_2.1/LICENSE ================================================ ---------------------------------------------------------------------- Copyright (c) 2016, The Regents of the University of California 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 The Regents of the University of California 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 REGENTS OF THE UNIVERSITY OF CALIFORNIA 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. ---------------------------------------------------------------------- ================================================ FILE: sw/riffa_2.1/README.txt ================================================ To install RIFFA 2.0, find the instructions in the install directory for your os. The source directory contains all the source code for the drivers, sample applications, etc. You can get started with your HDL design using a sample from the FPGA directory. It contains example HDL designs with corresponding example software. For further details, see the RIFFA 2.0 website at: http://cseweb.ucsd.edu/~mdjacobs Release notes: Version 2.0.2 ------------- - Fixed: Bug in Windows and Linux drivers that could report data sent/received before such data was confirmed. - Fixed: Updated common functions to avoid assigning input values. - Fixed: FIFO overflow error causing data corruption in tx_engine_upper and breaking the Xilinx Endpoint. - Fixed: Missing default cases in rx_port_reader, sg_list_requester, tx_engine_upper, and tx_port_writer. - Fixed: Bug in tx_engine_lower_128 corrupting s_axis_tx_tkeep, causing Xilinx PCIe endpoint core to shut down. - Fixed: Bug in tx_engine_upper_128 causing incomplete TX data timeouts. - Changed rx_engine to not block on non-posted TLPs. They're added to a FIFO and serviced in order. - Reset rx_port FIFOs before a receive transaction to avoid data corruption from replayed TLPs. Version 2.0.1 ------------- - RIFFA 2.0.1 is a general release. This means we've tested it in a number of ways. Please let us know if you encounter a bug. - Neither the HDL nor the drivers from RIFFA 2.0.1 are backwards compatible with the components of any previous release of RIFFA. - RIFFA 2.0.1 consumes more resources than 2.0 beta. This is because 2.0.1 was rewritten to support scatter gather DMA, higher bandwidth, and appreciably more signal registering. The additional registering was included to help meet timing constraints. - The Windows driver is supported on Windows 7 32/64. Other Windows versions can be supported. The driver simply needs to be built for that target. - Debugging on Windows is difficult because there exists no system log file. Driver log messages are visible only to an attached kernel debugger. So to see any messages you'll need the Windows Development Kit debugger (WinDbg) or a small utility called DbgView. DbgView is a standalone kernel debug viewer that can be downloaded from Microsoft here: http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx Run DbgView with administrator privileges and be sure to enable the following capture options: Capture Kernel, Capture Events, and Capture Verbose Kernel Output. - The Linux driver is supported on kernel version 2.6.27+. - The Java bindings make use of a native library (in order to connect Java JNI to the native library). Libraries for Linux and Windows for both 32/64 bit platforms have been compiled and included in the riffa.jar. - Removed the CHNL_RX_ERR signal from the channel interface. Error handling now ends the transaction gracefully. Errors can be easily detected by comparing the number of words received to the CHNL_RX_LEN amount. An error will cause CHNL_RX will go low prematurely and not provide the advertised amount of data. - Fixed: Bug in sg_list_requester which could cause an unbounded TLP request. - Fixed: Bug in tx_port_buffer_128 which could stall the TX transaction. ================================================ FILE: sw/riffa_2.1/driver/linux/Makefile ================================================ # This software is Copyright © 2012 The Regents of the University of # California. All Rights Reserved. # # Permission to copy, modify, and distribute this software and its # documentation for educational, research and non-profit purposes, without fee, # and without a written agreement is hereby granted, provided that the above # copyright notice, this paragraph and the following three paragraphs appear in # all copies. # # Permission to make commercial use of this software may be obtained by # contacting: # Technology Transfer Office # 9500 Gilman Drive, Mail Code 0910 # University of California # La Jolla, CA 92093-0910 # (858) 534-5815 # invent@ucsd.edu # # This software program and documentation are copyrighted by The Regents of the # University of California. The software program and documentation are supplied # "as is", without any accompanying services from The Regents. The Regents does # not warrant that the operation of the program will be uninterrupted or error- # free. The end-user understands that the program was developed for research # purposes and is advised not to rely exclusively on the program for any # reason. # # IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO # ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR # CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING # OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, # EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF # THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF # CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, # AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO # PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR # MODIFICATIONS. # Filename: Makefile # Version: 2.0 # Description: Makefile for Linux PCIe device driver for RIFFA. # Author: Matthew Jacobsen # History: @mattj: Initial release. Version 2.0. # You must specify the following variables. You can leave the defaults if you # like, but make sure they will work in your system. # The VENDOR_ID _must_ match what is configured on your FPGA's PCIe endpoint # header. Xilinx has a VENDOR_ID = 10EE. NAME := riffa VENDOR_ID0 := 10EE VENDOR_ID1 := 1172 MAJNUM := 100 # Build variables KVER := $(shell uname -r) KDIR := /lib/modules/`uname -r`/build RHR := /etc/redhat-release LIB_SRCS := riffa.c LIB_OBJS := $(patsubst %.c,%.o,$(LIB_SRCS)) LIB_HDR := riffa.h LIB_VER_MAJ := 1 LIB_VER_MIN := 0 LIB_VER := $(LIB_VER_MAJ).$(LIB_VER_MIN) DRVR_HDR := riffa_driver.h DBUGVAL := DBUG obj-m += $(NAME).o $(NAME)-y := riffa_driver.o circ_queue.o # Helper functions define assert $(if $1,,$(error Assertion failed: $2)) endef define assert-not-null $(call assert,$($1),The variable "$1" is null, please specify it.) endef define assert-variables $(call assert-not-null,NAME) $(call assert-not-null,MAJNUM) $(call assert-not-null,VENDOR_ID0) $(call assert-not-null,VENDOR_ID1) @printf "Compiling driver for kernel: %s with the following values\n" $(KVER) @printf " NAME: '%s'\n" $(NAME) @printf " MAJNUM: '%s'\n" $(MAJNUM) @printf "VENDOR_ID0: '%s'\n" $(VENDOR_ID0) @printf "VENDOR_ID1: '%s'\n" $(VENDOR_ID1) @printf "\n" endef all: builddvr debug: CC += -DDEBUG -g -Wno-error-implicit-function-declaration debug: DBUGVAL = DEBUG debug: builddvr builddvr: $(NAME).ko $(NAME).so.$(LIB_VER) $(NAME).ko: *.c *.h $(call assert-variables) sed -i 's/#define MAJOR_NUM [^\n]*/#define MAJOR_NUM $(MAJNUM)/g' $(DRVR_HDR) sed -i 's/#define DEVICE_NAME [^\n]*/#define DEVICE_NAME "$(NAME)"/g' $(DRVR_HDR) sed -i 's/#define VENDOR_ID0 [^\n]*/#define VENDOR_ID0 0x$(VENDOR_ID0)/g' $(DRVR_HDR) sed -i 's/#define VENDOR_ID1 [^\n]*/#define VENDOR_ID1 0x$(VENDOR_ID1)/g' $(DRVR_HDR) sed -i 's/#define DEBUG [^\n]*/#define DBUG 1/g' $(DRVR_HDR) sed -i 's/#define DBUG [^\n]*/#define $(DBUGVAL) 1/g' $(DRVR_HDR) make -C $(KDIR) SUBDIRS=`pwd` modules rm -rf $(LIB_OBJS) $(NAME).so.$(LIB_VER): $(LIB_OBJS) $(CC) -shared -Wno-error-implicit-function-declaration,-soname,lib$(NAME).so.$(LIB_VER_MAJ) -o lib$@ $^ $(LIB_OBJS): $(LIB_SRCS) $(CC) -g -Wall -fPIC -c $^ load: $(NAME).ko insmod $(NAME).ko unload: rmmod $(NAME) clean: rm -Rf *.ko *.cmd *.o *.so *.so.* .*.cmd Module.symvers Module.markers modules.order *.mod.c .tmp_versions setup: if [ -f "$(RHR)" ]; then yum install kernel-devel-`uname -r`;\ else apt-get install linux-headers-`uname -r`; fi install: $(NAME).so.$(LIB_VER) $(NAME).ko mkdir -p /lib/modules/$(KVER)/kernel/drivers/$(NAME) cp $(NAME).ko /lib/modules/$(KVER)/kernel/drivers/$(NAME)/ if [ -f "$(RHR)" ]; then\ printf "%b\n" "#!/bin/sh\nexec /sbin/modprobe $(NAME) >/dev/null 2>&1" > /etc/sysconfig/modules/$(NAME).modules;\ chmod 755 /etc/sysconfig/modules/$(NAME).modules;\ else\ if ! grep -Fxq "$(NAME)" /etc/modules; then echo "$(NAME)" >> /etc/modules; fi;\ fi printf "%b\n" "KERNEL==\"$(NAME)\", MODE=\"777\", GROUP=\"root\"" > /etc/udev/rules.d/99-$(NAME).rules printf "/usr/local/lib\n" > $(NAME).conf mv $(NAME).conf /etc/ld.so.conf.d/ cp $(DRVR_HDR) /usr/local/include/ cp $(LIB_HDR) /usr/local/include/ mv lib$(NAME).so.1.0 /usr/local/lib ln -sf /usr/local/lib/lib$(NAME).so.$(LIB_VER) /usr/local/lib/lib$(NAME).so.$(LIB_VER_MAJ) ln -sf /usr/local/lib/lib$(NAME).so.$(LIB_VER) /usr/local/lib/lib$(NAME).so ldconfig depmod uninstall: rm -f /usr/local/lib/lib$(NAME).so* rm -f /usr/local/include/$(LIB_HDR) rm -f /usr/local/include/$(DRVR_HDR) rm -f /etc/ld.so.conf.d/$(NAME).conf rm -rf /lib/modules/$(KVER)/kernel/drivers/$(NAME) rm -f /etc/udev/rules.d/99-$(NAME).rules if [ -f "$(RHR)" ]; then rm -f /etc/sysconfig/modules/$(NAME).modules;\ else cp /etc/modules ./etc.modules.bak; sed -i '/$(NAME)/d' /etc/modules; fi ldconfig depmod ================================================ FILE: sw/riffa_2.1/driver/linux/README.txt ================================================ You must build the Linux driver against the version of the Linux kernel you have installed. This will require the Linux kernel headers. After you've built the driver you can install it in your system so that it loads at boot time. If the driver is installed and there is a RIFFA 2.0.1 capable FPGA installed as well, the driver will detect it. Output in the system log will provide additional information. This makefile will also build and install the C/C++ native library. Ensure you have the kernel headers installed: sudo make setup This will attempt to install the kernel headers using your system's package manager. You can skip this step if you've already installed the kernel headers. Compile the driver and C/C++ library: make or make debug Using make debug will compile in code to output debug messages to the system log at runtime. These messages are useful when developing your design. However they pollute your system log and incur some overhead. So you may want to install the non-debug version after you've completed development. Install the driver and library: sudo make install The system will be configured to load the driver at boot time. The C/C++ library will be installed in the default library path. The header files will be placed in the default include path. You will want to reboot after you've installed for the driver to be (re)loaded. When compiling an application you should only need to include the header file and link with -lriffa. ================================================ FILE: sw/riffa_2.1/driver/linux/circ_queue.c ================================================ /******************************************************************************* * This software is Copyright © 2012 The Regents of the University of * California. All Rights Reserved. * * Permission to copy, modify, and distribute this software and its * documentation for educational, research and non-profit purposes, without fee, * and without a written agreement is hereby granted, provided that the above * copyright notice, this paragraph and the following three paragraphs appear in * all copies. * * Permission to make commercial use of this software may be obtained by * contacting: * Technology Transfer Office * 9500 Gilman Drive, Mail Code 0910 * University of California * La Jolla, CA 92093-0910 * (858) 534-5815 * invent@ucsd.edu * * This software program and documentation are copyrighted by The Regents of the * University of California. The software program and documentation are supplied * "as is", without any accompanying services from The Regents. The Regents does * not warrant that the operation of the program will be uninterrupted or error- * free. The end-user understands that the program was developed for research * purposes and is advised not to rely exclusively on the program for any * reason. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR * CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, * EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF * CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, * AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ /* * Filename: circ_queue.c * Version: 1.0 * Description: A lock-free single-producer circular queue implementation * modeled after the more elaborate C++ version from Faustino Frechilla at: * http://www.codeproject.com/Articles/153898/Yet-another-implementation-of-a-lock-free-circular * Author: Matthew Jacobsen * History: @mattj: Initial release. Version 1.0. */ #include #include "circ_queue.h" circ_queue * init_circ_queue(int len) { int i; circ_queue * q; q = kzalloc(sizeof(circ_queue), GFP_KERNEL); if (q == NULL) { printk(KERN_ERR "Not enough memory to allocate circ_queue"); return NULL; } atomic_set(&q->writeIndex, 0); atomic_set(&q->readIndex, 0); q->len = len; q->vals = (unsigned int**) kzalloc(len*sizeof(unsigned int*), GFP_KERNEL); if (q->vals == NULL) { printk(KERN_ERR "Not enough memory to allocate circ_queue array"); return NULL; } for (i = 0; i < len; i++) { q->vals[i] = (unsigned int*) kzalloc(2*sizeof(unsigned int), GFP_KERNEL); if (q->vals[i] == NULL) { printk(KERN_ERR "Not enough memory to allocate circ_queue array position"); return NULL; } } return q; } /** * Internal function to help count. Returns the queue size normalized position. */ unsigned int queue_count_to_index(unsigned int count, unsigned int len) { return (count % len); } int push_circ_queue(circ_queue * q, unsigned int val1, unsigned int val2) { unsigned int currReadIndex; unsigned int currWriteIndex; currWriteIndex = atomic_read(&q->writeIndex); currReadIndex = atomic_read(&q->readIndex); if (queue_count_to_index(currWriteIndex+1, q->len) == queue_count_to_index(currReadIndex, q->len)) { // The queue is full return 1; } // Save the data into the queue q->vals[queue_count_to_index(currWriteIndex, q->len)][0] = val1; q->vals[queue_count_to_index(currWriteIndex, q->len)][1] = val2; // Increment atomically write index. Now a consumer thread can read // the piece of data that was just stored. atomic_inc(&q->writeIndex); return 0; } int pop_circ_queue(circ_queue * q, unsigned int * val1, unsigned int * val2) { unsigned int currReadIndex; unsigned int currMaxReadIndex; do { currReadIndex = atomic_read(&q->readIndex); currMaxReadIndex = atomic_read(&q->writeIndex); if (queue_count_to_index(currReadIndex, q->len) == queue_count_to_index(currMaxReadIndex, q->len)) { // The queue is empty or a producer thread has allocate space in the queue // but is waiting to commit the data into it return 1; } // Retrieve the data from the queue *val1 = q->vals[queue_count_to_index(currReadIndex, q->len)][0]; *val2 = q->vals[queue_count_to_index(currReadIndex, q->len)][1]; // Try to perfrom now the CAS operation on the read index. If we succeed // label & val already contain what q->readIndex pointed to before we // increased it. if (atomic_cmpxchg(&q->readIndex, currReadIndex, currReadIndex+1) == currReadIndex) { // The lable & val were retrieved from the queue. Note that the // data inside the label or value arrays are not deleted. return 0; } // Failed to retrieve the elements off the queue. Someone else must // have read the element stored at countToIndex(currReadIndex) // before we could perform the CAS operation. } while(1); // keep looping to try again! return 1; } int circ_queue_empty(circ_queue * q) { unsigned int currReadIndex; unsigned int currMaxReadIndex; currReadIndex = atomic_read(&q->readIndex); currMaxReadIndex = atomic_read(&q->writeIndex); if (queue_count_to_index(currReadIndex, q->len) == queue_count_to_index(currMaxReadIndex, q->len)) { // The queue is empty or a producer thread has allocate space in the queue // but is waiting to commit the data into it return 1; } return 0; } int circ_queue_full(circ_queue * q) { unsigned int currReadIndex; unsigned int currWriteIndex; currWriteIndex = atomic_read(&q->writeIndex); currReadIndex = atomic_read(&q->readIndex); if (queue_count_to_index(currWriteIndex+1, q->len) == queue_count_to_index(currReadIndex, q->len)) { // The queue is full return 1; } return 0; } void free_circ_queue(circ_queue * q) { int i; if (q == NULL) return; for (i = 0; i < q->len; i++) { kfree(q->vals[i]); } kfree(q->vals); kfree(q); } ================================================ FILE: sw/riffa_2.1/driver/linux/circ_queue.h ================================================ /******************************************************************************* * This software is Copyright © 2012 The Regents of the University of * California. All Rights Reserved. * * Permission to copy, modify, and distribute this software and its * documentation for educational, research and non-profit purposes, without fee, * and without a written agreement is hereby granted, provided that the above * copyright notice, this paragraph and the following three paragraphs appear in * all copies. * * Permission to make commercial use of this software may be obtained by * contacting: * Technology Transfer Office * 9500 Gilman Drive, Mail Code 0910 * University of California * La Jolla, CA 92093-0910 * (858) 534-5815 * invent@ucsd.edu * * This software program and documentation are copyrighted by The Regents of the * University of California. The software program and documentation are supplied * "as is", without any accompanying services from The Regents. The Regents does * not warrant that the operation of the program will be uninterrupted or error- * free. The end-user understands that the program was developed for research * purposes and is advised not to rely exclusively on the program for any * reason. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR * CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, * EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF * CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, * AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ /* * Filename: circ_queue.h * Version: 1.0 * Description: A lock-free single-producer circular queue implementation * modeled after the more elaborate C++ version from Faustino Frechilla at: * http://www.codeproject.com/Articles/153898/Yet-another-implementation-of-a-lock-free-circular * Author: Matthew Jacobsen * History: @mattj: Initial release. Version 1.0. */ #ifndef CIRC_QUEUE_H #define CIRC_QUEUE_H #include /* Struct for the circular queue. */ struct circ_queue { atomic_t writeIndex; atomic_t readIndex; unsigned int ** vals; unsigned int len; }; typedef struct circ_queue circ_queue; /** * Initializes a circ_queue with depth/length len. Returns non-NULL on success, * NULL if there was a problem creating the queue. */ circ_queue * init_circ_queue(int len); /** * Pushes a pair of unsigned int values into the specified queue at the head. * Returns 0 on success, non-zero if there is no more space in the queue. */ int push_circ_queue(circ_queue * q, unsigned int val1, unsigned int val2); /** * Pops a pair of unsigned int values out of the specified queue from the tail. * Returns 0 on success, non-zero if the queue is empty. */ int pop_circ_queue(circ_queue * q, unsigned int * val1, unsigned int * val2); /** * Returns 1 if the circ_queue is empty, 0 otherwise. Note, this is not a * synchronized function. If another thread is accessing this circ_queue, the * return value may not be valid. */ int circ_queue_empty(circ_queue * q); /** * Returns 1 if the circ_queue is full, 0 otherwise. Note, this is not a * synchronized function. If another thread is accessing this circ_queue, the * return value may not be valid. */ int circ_queue_full(circ_queue * q); /** * Frees the resources associated with the specified circ_queue. */ void free_circ_queue(circ_queue * q); #endif ================================================ FILE: sw/riffa_2.1/driver/linux/riffa.c ================================================ /******************************************************************************* * This software is Copyright © 2012 The Regents of the University of * California. All Rights Reserved. * * Permission to copy, modify, and distribute this software and its * documentation for educational, research and non-profit purposes, without fee, * and without a written agreement is hereby granted, provided that the above * copyright notice, this paragraph and the following three paragraphs appear in * all copies. * * Permission to make commercial use of this software may be obtained by * contacting: * Technology Transfer Office * 9500 Gilman Drive, Mail Code 0910 * University of California * La Jolla, CA 92093-0910 * (858) 534-5815 * invent@ucsd.edu * * This software program and documentation are copyrighted by The Regents of the * University of California. The software program and documentation are supplied * "as is", without any accompanying services from The Regents. The Regents does * not warrant that the operation of the program will be uninterrupted or error- * free. The end-user understands that the program was developed for research * purposes and is advised not to rely exclusively on the program for any * reason. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR * CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, * EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF * CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, * AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ /* * Filename: riffa.c * Version: 2.0 * Description: Linux PCIe communications API for RIFFA. * Author: Matthew Jacobsen * History: @mattj: Initial release. Version 2.0. */ #include #include #include #include #include #include "riffa.h" struct fpga_t { int fd; int id; }; fpga_t * fpga_open(int id) { fpga_t * fpga; // Allocate space for the fpga_dev fpga = (fpga_t *)malloc(sizeof(fpga_t)); if (fpga == NULL) return NULL; fpga->id = id; // Open the device file. fpga->fd = open("/dev/" DEVICE_NAME, O_RDWR | O_SYNC); if (fpga->fd < 0) { free(fpga); return NULL; } return fpga; } void fpga_close(fpga_t * fpga) { // Close the device file. close(fpga->fd); free(fpga); } int fpga_send(fpga_t * fpga, int chnl, void * data, int len, int destoff, int last, long long timeout) { fpga_chnl_io io; io.id = fpga->id; io.chnl = chnl; io.len = len; io.offset = destoff; io.last = last; io.timeout = timeout; io.data = (char *)data; return ioctl(fpga->fd, IOCTL_SEND, &io); } int fpga_recv(fpga_t * fpga, int chnl, void * data, int len, long long timeout) { fpga_chnl_io io; io.id = fpga->id; io.chnl = chnl; io.len = len; io.timeout = timeout; io.data = (char *)data; return ioctl(fpga->fd, IOCTL_RECV, &io); } void fpga_reset(fpga_t * fpga) { ioctl(fpga->fd, IOCTL_RESET, fpga->id); } int fpga_list(fpga_info_list * list) { int fd; int rc; fd = open("/dev/" DEVICE_NAME, O_RDWR | O_SYNC); if (fd < 0) return fd; rc = ioctl(fd, IOCTL_LIST, list); close(fd); return rc; } ================================================ FILE: sw/riffa_2.1/driver/linux/riffa.h ================================================ /******************************************************************************* * This software is Copyright © 2012 The Regents of the University of * California. All Rights Reserved. * * Permission to copy, modify, and distribute this software and its * documentation for educational, research and non-profit purposes, without fee, * and without a written agreement is hereby granted, provided that the above * copyright notice, this paragraph and the following three paragraphs appear in * all copies. * * Permission to make commercial use of this software may be obtained by * contacting: * Technology Transfer Office * 9500 Gilman Drive, Mail Code 0910 * University of California * La Jolla, CA 92093-0910 * (858) 534-5815 * invent@ucsd.edu * * This software program and documentation are copyrighted by The Regents of the * University of California. The software program and documentation are supplied * "as is", without any accompanying services from The Regents. The Regents does * not warrant that the operation of the program will be uninterrupted or error- * free. The end-user understands that the program was developed for research * purposes and is advised not to rely exclusively on the program for any * reason. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR * CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, * EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF * CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, * AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ /* * Filename: riffa.h * Version: 2.0 * Description: Linux PCIe communications API for RIFFA. * Author: Matthew Jacobsen * History: @mattj: Initial release. Version 2.0. */ #ifndef RIFFA_H #define RIFFA_H #include "riffa_driver.h" #ifdef __cplusplus extern "C" { #endif struct fpga_t; typedef struct fpga_t fpga_t; /** * Populates the fpga_info_list pointer with all FPGAs registered in the system. * Returns 0 on success, a negative value on error. */ int fpga_list(fpga_info_list * list); /** * Initializes the FPGA specified by id. On success, returns a pointer to a * fpga_t struct. On error, returns NULL. Each FPGA must be opened before any * channels can be accessed. Once opened, any number of threads can use the * fpga_t struct. */ fpga_t * fpga_open(int id); /** * Cleans up memory/resources for the FPGA specified by the fd descriptor. */ void fpga_close(fpga_t * fpga); /** * Sends len words (4 byte words) from data to FPGA channel chnl using the * fpga_t struct. The FPGA channel will be sent len, destoff, and last. If last * is 1, the channel should interpret the end of this send as the end of a * transaction. If last is 0, the channel should wait for additional sends * before the end of the transaction. If timeout is non-zero, this call will * send data and wait up to timeout ms for the FPGA to respond (between * packets) before timing out. If timeout is zero, this call may block * indefinitely. Multiple threads sending on the same channel may result in * corrupt data or error. This function is thread safe across channels. * On success, returns the number of words sent. On error returns a negative * value. */ int fpga_send(fpga_t * fpga, int chnl, void * data, int len, int destoff, int last, long long timeout); /** * Receives data from the FPGA channel chnl to the data pointer, using the * fpga_t struct. The FPGA channel can send any amount of data, so the data * array should be large enough to accommodate. The len parameter specifies the * actual size of the data buffer in words (4 byte words). The FPGA channel will * specify an offset which will determine where in the data array the data will * start being written. If the amount of data (plus offset) exceed the size of * the data array (len), then that data will be discarded. If timeout is * non-zero, this call will wait up to timeout ms for the FPGA to respond * (between packets) before timing out. If timeout is zero, this call may block * indefinitely. Multiple threads receiving on the same channel may result in * corrupt data or error. This function is thread safe across channels. * On success, returns the number of words written to the data array. On error * returns a negative value. */ int fpga_recv(fpga_t * fpga, int chnl, void * data, int len, long long timeout); /** * Resets the state of the FPGA and all transfers across all channels. This is * meant to be used as an alternative to rebooting if an error occurs while * sending/receiving. Calling this function while other threads are sending or * receiving will result in unexpected behavior. */ void fpga_reset(fpga_t * fpga); #ifdef __cplusplus } #endif #endif ================================================ FILE: sw/riffa_2.1/driver/linux/riffa_driver.c ================================================ /******************************************************************************* * This software is Copyright © 2012 The Regents of the University of * California. All Rights Reserved. * * Permission to copy, modify, and distribute this software and its * documentation for educational, research and non-profit purposes, without fee, * and without a written agreement is hereby granted, provided that the above * copyright notice, this paragraph and the following three paragraphs appear in * all copies. * * Permission to make commercial use of this software may be obtained by * contacting: * Technology Transfer Office * 9500 Gilman Drive, Mail Code 0910 * University of California * La Jolla, CA 92093-0910 * (858) 534-5815 * invent@ucsd.edu * * This software program and documentation are copyrighted by The Regents of the * University of California. The software program and documentation are supplied * "as is", without any accompanying services from The Regents. The Regents does * not warrant that the operation of the program will be uninterrupted or error- * free. The end-user understands that the program was developed for research * purposes and is advised not to rely exclusively on the program for any * reason. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR * CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, * EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF * CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, * AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ /* * Filename: riffa_driver.c * Version: 2.0 * Description: Linux PCIe device driver for RIFFA. Uses Linux kernel APIs in * version 2.6.27+ (tested on version 2.6.32 - 3.3.0). * Author: Matthew Jacobsen * History: @mattj: Initial release. Version 2.0. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "riffa_driver.h" #include "circ_queue.h" MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("PCIe driver for RIFFA, Linux (2.6.27+)"); MODULE_AUTHOR("Matt Jacobsen, Patrick Lai"); #ifndef __devinit #define __devinit #define __devexit #define __devexit_p #endif #define CHNL_REG(c, o) ((c<<4) + o) #if !defined(__LP64__) && !defined(_LP64) #define BUILD_32 1 #endif struct sg_mapping { struct page ** pages; struct scatterlist * sgl; enum dma_data_direction direction; int num_sg; unsigned long num_pages; unsigned long long length; unsigned long long overflow; }; struct chnl_dir { wait_queue_head_t waitq; struct circ_queue * msgs; void * buf_addr; dma_addr_t buf_hw_addr; struct sg_mapping * sg_map_0; struct sg_mapping * sg_map_1; }; struct fpga_state { struct pci_dev * dev; unsigned long long irq; void __iomem *bar0; unsigned long long bar0_addr; unsigned long long bar0_len; unsigned long long bar0_flags; atomic_t intr_disabled; void * spill_buf_addr; dma_addr_t spill_buf_hw_addr; int num_sg; int sg_buf_size; int id; char name[16]; int vendor_id; int device_id; int num_chnls; struct chnl_dir ** recv; struct chnl_dir ** send; }; // Global variables (to this file only) static struct class * mymodule_class; static dev_t devt; static atomic_t used_fpgas[NUM_FPGAS]; static struct fpga_state * fpgas[NUM_FPGAS]; /////////////////////////////////////////////////////// // MEMORY ALLOCATION & HELPER FUNCTIONS /////////////////////////////////////////////////////// /** * Returns the value at the specified address. */ static inline unsigned int read_reg(struct fpga_state * sc, int offset) { return readl(sc->bar0 + (offset<<2)); } /** * Writes the value to the specified address. */ static inline void write_reg(struct fpga_state * sc, int offset, unsigned int val) { writel(val, sc->bar0 + (offset<<2)); } #ifdef BUILD_32 /** * Needed for 32 bit OS because dma_map_sg macro eventually does some 64 bit * division. */ unsigned long long __udivdi3(unsigned long long num, unsigned long long den) { do_div(num, den); return num; } #endif /////////////////////////////////////////////////////// // INTERRUPT HANDLER /////////////////////////////////////////////////////// /** * Reads the interrupt vector and processes it. If processing VECT0, off will * be 0. If processing VECT1, off will be 6. */ static inline void process_intr_vector(struct fpga_state * sc, int off, unsigned int vect) { // VECT_0/VECT_1 are organized from right to left (LSB to MSB) as: // [ 0] TX_TXN for channel 0 in VECT_0, channel 6 in VECT_1 // [ 1] TX_SG_BUF_RECVD for channel 0 in VECT_0, channel 6 in VECT_1 // [ 2] TX_TXN_DONE for channel 0 in VECT_0, channel 6 in VECT_1 // [ 3] RX_SG_BUF_RECVD for channel 0 in VECT_0, channel 6 in VECT_1 // [ 4] RX_TXN_DONE for channel 0 in VECT_0, channel 6 in VECT_1 // ... // [25] TX_TXN for channel 5 in VECT_0, channel 11 in VECT_1 // [26] TX_SG_BUF_RECVD for channel 5 in VECT_0, channel 11 in VECT_1 // [27] TX_TXN_DONE for channel 5 in VECT_0, channel 11 in VECT_1 // [28] RX_SG_BUF_RECVD for channel 5 in VECT_0, channel 11 in VECT_1 // [29] RX_TXN_DONE for channel 5 in VECT_0, channel 11 in VECT_1 // Positions 30 - 31 in both VECT_0 and VECT_1 are zero. unsigned int offlast; unsigned int len; int recv; int send; int chnl; int i; //printk(KERN_INFO "riffa: intrpt_handler received:%08x\n", vect); if (vect & 0xC0000000) { printk(KERN_ERR "riffa: fpga:%d, received bad interrupt vector:%08x\n", sc->id, vect); return; } for (i = 0; i < 6 && (i+off) < sc->num_chnls; ++i) { chnl = i + off; recv = 0; send = 0; // TX (PC receive) scatter gather buffer is read. if (vect & (1<<((5*i)+1))) { recv = 1; // Keep track so the thread can handle this. if (push_circ_queue(sc->recv[chnl]->msgs, EVENT_SG_BUF_READ, 0)) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv sg buf read msg queue full\n", sc->id, chnl); } DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, recv sg buf read\n", sc->id, chnl); } // TX (PC receive) transaction done. if (vect & (1<<((5*i)+2))) { recv = 1; // Read the transferred amount. len = read_reg(sc, CHNL_REG(chnl, TX_TNFR_LEN_REG_OFF)); // Notify the thread. if (push_circ_queue(sc->recv[chnl]->msgs, EVENT_TXN_DONE, len)) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv txn done msg queue full\n", sc->id, chnl); } DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, recv txn done\n", sc->id, chnl); } // New TX (PC receive) transaction. if (vect & (1<<((5*i)+0))) { recv = 1; // Read the offset/last and length offlast = read_reg(sc, CHNL_REG(chnl, TX_OFFLAST_REG_OFF)); len = read_reg(sc, CHNL_REG(chnl, TX_LEN_REG_OFF)); // Keep track of this transaction if (push_circ_queue(sc->recv[chnl]->msgs, EVENT_TXN_OFFLAST, offlast)) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv txn offlast msg queue full\n", sc->id, chnl); } if (push_circ_queue(sc->recv[chnl]->msgs, EVENT_TXN_LEN, len)) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv txn len msg queue full\n", sc->id, chnl); } DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, recv txn (len:%d off:%d last:%d)\n", sc->id, chnl, len, (offlast>>1), (offlast & 0x1)); } // RX (PC send) scatter gather buffer is read. if (vect & (1<<((5*i)+3))) { send = 1; // Keep track so the thread can handle this. if (push_circ_queue(sc->send[chnl]->msgs, EVENT_SG_BUF_READ, 0)) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, send sg buf read msg queue full\n", sc->id, chnl); } DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, send sg buf read\n", sc->id, chnl); } // RX (PC send) transaction done. if (vect & (1<<((5*i)+4))) { send = 1; // Read the transferred amount. len = read_reg(sc, CHNL_REG(chnl, RX_TNFR_LEN_REG_OFF)); // Notify the thread. if (push_circ_queue(sc->send[chnl]->msgs, EVENT_TXN_DONE, len)) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, send txn done msg queue full\n", sc->id, chnl); } DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, send txn done\n", sc->id, chnl); } // Wake up the thread? if (recv) wake_up(&sc->recv[chnl]->waitq); if (send) wake_up(&sc->send[chnl]->waitq); } } /** * Interrupt handler for all interrupts on all files. Reads data/values * from FPGA and wakes up waiting threads to process the data. Always returns * IRQ_HANDLED. */ static irqreturn_t intrpt_handler(int irq, void *dev_id) { unsigned int vect0; unsigned int vect1; struct fpga_state * sc; sc = (struct fpga_state *)dev_id; vect0 = 0; vect1 = 0; if (sc == NULL) { printk(KERN_ERR "riffa: invalid fpga_state pointer\n"); return IRQ_HANDLED; } if (!atomic_read(&sc->intr_disabled)) { // Read the interrupt vector(s): vect0 = read_reg(sc, IRQ_REG0_OFF); if (sc->num_chnls > 6) vect1 = read_reg(sc, IRQ_REG1_OFF); // Process the vector(s) process_intr_vector(sc, 0, vect0); if (sc->num_chnls > 6) process_intr_vector(sc, 6, vect1); } return IRQ_HANDLED; } /////////////////////////////////////////////////////// // FILE OPERATION HANDLERS /////////////////////////////////////////////////////// /** * Creates and returns a struct_sg_mapping that holds all the data for the user * pages that have been mapped into a scatterlist array. Assumes the user data * is 32 bit word aligned. Up to length bytes from the udata pointer will be * mapped. After all length bytes are mapped, up to overflow bytes will be * mapped using the common spill buffer for the channel. The overflow is used * if we run out of space in the supplied udata pointer. */ static inline struct sg_mapping * fill_sg_buf(struct fpga_state * sc, int chnl, void * sg_buf, unsigned long udata, unsigned long long length, unsigned long long overflow, enum dma_data_direction direction) { const char * dir = (direction == DMA_TO_DEVICE ? "send" : "recv"); struct sg_mapping * sg_map; struct page ** pages = NULL; struct scatterlist * sgl = NULL; struct scatterlist * sg; unsigned long num_pages_reqd = 0; long num_pages = 0; unsigned int fp_offset; unsigned int len; unsigned int hw_len; dma_addr_t hw_addr; unsigned long long len_rem = length; unsigned long long overflow_rem = overflow; unsigned int * sg_buf_ptr = (unsigned int *)sg_buf; int num_sg = 0; int i; // Create the sg_mapping struct. if ((sg_map = (struct sg_mapping *)kmalloc(sizeof(*sg_map), GFP_KERNEL)) == NULL) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, %s could not allocate memory for sg_mapping struct\n", sc->id, chnl, dir); return NULL; } if (length > 0) { // Create the pages array. num_pages_reqd = ((udata + length - 1)>>PAGE_SHIFT) - (udata>>PAGE_SHIFT) + 1; num_pages_reqd = (num_pages_reqd > sc->num_sg ? sc->num_sg : num_pages_reqd); if ((pages = kmalloc(num_pages_reqd * sizeof(*pages), GFP_KERNEL)) == NULL) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, %s could not allocate memory for pages array\n", sc->id, chnl, dir); kfree(sg_map); return NULL; } // Page in the user pages. down_read(¤t->mm->mmap_sem); num_pages = get_user_pages(current, current->mm, udata, num_pages_reqd, 1, 0, pages, NULL); up_read(¤t->mm->mmap_sem); if (num_pages <= 0) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, %s unable to pin any pages in memory\n", sc->id, chnl, dir); kfree(pages); kfree(sg_map); return NULL; } // Create the scatterlist array. if ((sgl = kcalloc(num_pages, sizeof(*sgl), GFP_KERNEL)) == NULL) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, %s could not allocate memory for scatterlist array\n", sc->id, chnl, dir); for (i = 0; i < num_pages; ++i) page_cache_release(pages[i]); kfree(pages); kfree(sg_map); return NULL; } // Set the scatterlist values fp_offset = (udata & (~PAGE_MASK)); sg_init_table(sgl, num_pages); for (i = 0; i < num_pages; ++i) { len = ((fp_offset + len_rem) > PAGE_SIZE ? (PAGE_SIZE - fp_offset) : len_rem); sg_set_page(&sgl[i], pages[i], len, fp_offset); len_rem -= len; fp_offset = 0; } // Map the scatterlist values and write to the common buffer area num_sg = dma_map_sg(&sc->dev->dev, sgl, num_pages, direction); for_each_sg(sgl, sg, num_sg, i) { hw_addr = sg_dma_address(sg); hw_len = sg_dma_len(sg); sg_buf_ptr[(i*4)+0] = (hw_addr & 0xFFFFFFFF); sg_buf_ptr[(i*4)+1] = ((hw_addr>>32) & 0xFFFFFFFF); sg_buf_ptr[(i*4)+2] = hw_len>>2; // Words! } } // Provide scatter gather mappings for overflow data (all in spill common buffer) while (len_rem == 0 && overflow_rem > 0 && num_sg < sc->num_sg) { sg_buf_ptr[(num_sg*4)+0] = (sc->spill_buf_hw_addr & 0xFFFFFFFF); sg_buf_ptr[(num_sg*4)+1] = ((sc->spill_buf_hw_addr>>32) & 0xFFFFFFFF); sg_buf_ptr[(num_sg*4)+2] = SPILL_BUF_SIZE>>2; // Words! num_sg++; overflow_rem -= (SPILL_BUF_SIZE > overflow ? overflow : SPILL_BUF_SIZE); } // Populate the number of bytes mapped and other sg data sg_map->direction = direction; sg_map->num_pages = num_pages; sg_map->num_sg = num_sg; sg_map->length = (length - len_rem); sg_map->overflow = (overflow - overflow_rem); sg_map->pages = pages; sg_map->sgl = sgl; return sg_map; } /** * Frees the scatterlist mappings in the struct sg_mapping pointer and frees all * corresponding structs. */ static inline void free_sg_buf(struct fpga_state * sc, struct sg_mapping * sg_map) { int i; if (sg_map == NULL) return; // Unmap the pages. if (sg_map->sgl != NULL) dma_unmap_sg(&sc->dev->dev, sg_map->sgl, sg_map->num_pages, sg_map->direction); // Free the pages (mark dirty if necessary). if (sg_map->pages != NULL) { if (sg_map->direction == DMA_FROM_DEVICE) { for (i = 0; i < sg_map->num_pages; ++i) { if (!PageReserved(sg_map->pages[i])) SetPageDirty(sg_map->pages[i]); page_cache_release(sg_map->pages[i]); } } else { for (i = 0; i < sg_map->num_pages; ++i) { page_cache_release(sg_map->pages[i]); } } } // Free the structures. if (sg_map->pages != NULL) kfree(sg_map->pages); if (sg_map->sgl != NULL) kfree(sg_map->sgl); kfree(sg_map); } /** * Reads data from the FPGA. Will block until all the data is received from the * FPGA unless timeout is non-zero. If timeout is non-zero, the function will * block until all the data is received or until the timeout expires. Received * data will be written directly into the user buffer, bufp, by the DMA process * (using scatter gather). Up to len words (each word == 32 bits) will be * written. On success, the number of words received are returned. On error, * returns a negative value. */ static inline unsigned int chnl_recv(struct fpga_state * sc, int chnl, char __user * bufp, unsigned int len, unsigned long long timeout) { struct sg_mapping * sg_map; long tymeouto; long tymeout; int nomsg; unsigned int msg_type; unsigned int msg; int last = -1; unsigned long long offset = 0; unsigned long long length = 0; unsigned long long overflow = 0; unsigned long long capacity = (((unsigned long long)len)<<2); unsigned long long recvd = 0; unsigned long udata = (unsigned long)bufp; unsigned long max_ptr; DEFINE_WAIT(wait); // Validate the parameters. if (chnl >= sc->num_chnls || chnl < 0) { printk(KERN_INFO "riffa: fpga:%d chnl:%d, recv channel invalid!\n", sc->id, chnl); return 0; } if (udata & 0x3) { printk(KERN_INFO "riffa: fpga:%d chnl:%d, recv user buffer must be 32 bit word aligned!\n", sc->id, chnl); return -EINVAL; } // Convert timeout to jiffies. tymeout = (timeout == 0 ? MAX_SCHEDULE_TIMEOUT : (timeout * HZ/1000 > LONG_MAX ? LONG_MAX : timeout * HZ/1000)); tymeouto = tymeout; // Initialize the sg_maps sc->recv[chnl]->sg_map_0 = NULL; sc->recv[chnl]->sg_map_1 = NULL; // Continue until we get a message or timeout. while (1) { while ((nomsg = pop_circ_queue(sc->recv[chnl]->msgs, &msg_type, &msg))) { prepare_to_wait(&sc->recv[chnl]->waitq, &wait, TASK_INTERRUPTIBLE); // Another check before we schedule. if ((nomsg = pop_circ_queue(sc->recv[chnl]->msgs, &msg_type, &msg))) tymeout = schedule_timeout(tymeout); finish_wait(&sc->recv[chnl]->waitq, &wait); if (signal_pending(current)) { free_sg_buf(sc, sc->recv[chnl]->sg_map_0); free_sg_buf(sc, sc->recv[chnl]->sg_map_1); return -ERESTARTSYS; } if (!nomsg) break; if (tymeout == 0) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv timed out\n", sc->id, chnl); free_sg_buf(sc, sc->recv[chnl]->sg_map_0); free_sg_buf(sc, sc->recv[chnl]->sg_map_1); return (unsigned int)(recvd>>2); } } tymeout = tymeouto; // Process the message. switch (msg_type) { case EVENT_TXN_OFFLAST: // Read the offset and last flags (always before reading length) offset = (((unsigned long long)(msg>>1))<<2); last = (msg & 0x1); break; case EVENT_TXN_LEN: // Read the length length = (((unsigned long long)msg)<<2); recvd = 0; overflow = 0; // Check for address overflow max_ptr = (unsigned long)(udata + offset + length - 1); if (max_ptr < udata) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv pointer address overflow\n", sc->id, chnl); overflow = length; length = 0; } // Check for capacity overflow if ((offset + length) > capacity) { if (offset > capacity) { overflow = length; length = 0; } else { overflow = length + offset - capacity; length = capacity - offset; } } // Use the recv common buffer to share the scatter gather elements. if (length > 0 || overflow > 0) { udata = udata + offset; sg_map = fill_sg_buf(sc, chnl, sc->recv[chnl]->buf_addr, udata, length, overflow, DMA_FROM_DEVICE); if (sg_map == NULL || sg_map->num_sg == 0) return (unsigned int)(recvd>>2); // Update based on the sg_mapping udata += sg_map->length; length -= sg_map->length; overflow -= sg_map->overflow; sc->recv[chnl]->sg_map_1 = sg_map; // Let FPGA know about the scatter gather buffer. write_reg(sc, CHNL_REG(chnl, TX_SG_ADDR_LO_REG_OFF), (sc->recv[chnl]->buf_hw_addr & 0xFFFFFFFF)); write_reg(sc, CHNL_REG(chnl, TX_SG_ADDR_HI_REG_OFF), ((sc->recv[chnl]->buf_hw_addr>>32) & 0xFFFFFFFF)); write_reg(sc, CHNL_REG(chnl, TX_SG_LEN_REG_OFF), 4 * sg_map->num_sg); DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, recv sg buf populated, %d sent\n", sc->id, chnl, sg_map->num_sg); } break; case EVENT_SG_BUF_READ: // Ignore if we haven't received offlast/len. if (last == -1) break; // Release the previous scatter gather data. if (sc->recv[chnl]->sg_map_0 != NULL) recvd += sc->recv[chnl]->sg_map_0->length; free_sg_buf(sc, sc->recv[chnl]->sg_map_0); sc->recv[chnl]->sg_map_0 = NULL; // Populate the common buffer with more scatter gather data? if (length > 0 || overflow > 0) { sg_map = fill_sg_buf(sc, chnl, sc->recv[chnl]->buf_addr, udata, length, overflow, DMA_FROM_DEVICE); if (sg_map == NULL || sg_map->num_sg == 0) { free_sg_buf(sc, sc->recv[chnl]->sg_map_0); free_sg_buf(sc, sc->recv[chnl]->sg_map_1); return (unsigned int)(recvd>>2); } // Update based on the sg_mapping udata += sg_map->length; length -= sg_map->length; overflow -= sg_map->overflow; sc->recv[chnl]->sg_map_0 = sc->recv[chnl]->sg_map_1; sc->recv[chnl]->sg_map_1 = sg_map; write_reg(sc, CHNL_REG(chnl, TX_SG_ADDR_LO_REG_OFF), (sc->recv[chnl]->buf_hw_addr & 0xFFFFFFFF)); write_reg(sc, CHNL_REG(chnl, TX_SG_ADDR_HI_REG_OFF), ((sc->recv[chnl]->buf_hw_addr>>32) & 0xFFFFFFFF)); write_reg(sc, CHNL_REG(chnl, TX_SG_LEN_REG_OFF), 4 * sg_map->num_sg); DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, recv sg buf populated, %d sent\n", sc->id, chnl, sg_map->num_sg); } break; case EVENT_TXN_DONE: // Ignore if we haven't received offlast/len. if (last == -1) break; // Update with the true value of words transferred. recvd = (((unsigned long long)msg)<<2); // Return if this was the last transaction. free_sg_buf(sc, sc->recv[chnl]->sg_map_0); free_sg_buf(sc, sc->recv[chnl]->sg_map_1); sc->recv[chnl]->sg_map_0 = NULL; sc->recv[chnl]->sg_map_1 = NULL; DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, received %d words\n", sc->id, chnl, (unsigned int)(recvd>>2)); if (last) return (unsigned int)(recvd>>2); break; default: printk(KERN_ERR "riffa: fpga:%d chnl:%d, received unknown msg: %08x\n", sc->id, chnl, msg); break; } } return 0; } /** * Writes data to the FPGA channel specified. Will block until all the data is * sent to the FPGA unless a non-zero timeout is configured. If timeout is non- * zero, then the function will block until all data is sent or when the timeout * ms elapses. User data from the bufp pointer will be sent, up to len words * (each word == 32 bits). The channel will be told how much data to expect and * at what offset. If last == 1, the FPGA channel will recognize this * transaction as complete after sending. If last == 0, the FPGA channel will * expect additional transactions. On success, returns the number of words sent. * On error, returns a negative value. */ static inline unsigned int chnl_send(struct fpga_state * sc, int chnl, const char __user * bufp, unsigned int len, unsigned int offset, unsigned int last, unsigned long long timeout) { struct sg_mapping * sg_map; long tymeouto; long tymeout; int nomsg; unsigned int msg_type; unsigned int msg; unsigned long long sent = 0; unsigned long long length = (((unsigned long long)len)<<2); unsigned long udata = (unsigned long)bufp; unsigned long max_ptr; DEFINE_WAIT(wait); // Validate the parameters. if (chnl >= sc->num_chnls || chnl < 0) { printk(KERN_INFO "riffa: fpga:%d chnl:%d, send channel invalid!\n", sc->id, chnl); return 0; } max_ptr = (unsigned long)(udata + length - 1); if (max_ptr < udata) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, send pointer address overflow\n", sc->id, chnl); return -EINVAL; } if (udata & 0x3) { printk(KERN_INFO "riffa: fpga:%d chnl:%d, send user buffer must be 32 bit word aligned!\n", sc->id, chnl); return -EINVAL; } // Convert timeout to jiffies. tymeout = (timeout == 0 ? MAX_SCHEDULE_TIMEOUT : (timeout * HZ/1000 > LONG_MAX ? LONG_MAX : timeout * HZ/1000)); tymeouto = tymeout; // Clear the message queue. while (!pop_circ_queue(sc->send[chnl]->msgs, &msg_type, &msg)); // Initialize the sg_maps sc->send[chnl]->sg_map_0 = NULL; sc->send[chnl]->sg_map_1 = NULL; // Let FPGA know about transfer. DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, send (len:%d off:%d last:%d)\n", sc->id, chnl, len, offset, last); write_reg(sc, CHNL_REG(chnl, RX_OFFLAST_REG_OFF), ((offset<<1) | last)); write_reg(sc, CHNL_REG(chnl, RX_LEN_REG_OFF), len); if (len == 0) return 0; // Use the send common buffer to share the scatter gather data sg_map = fill_sg_buf(sc, chnl, sc->send[chnl]->buf_addr, udata, length, 0, DMA_TO_DEVICE); if (sg_map == NULL || sg_map->num_sg == 0) return (unsigned int)(sent>>2); // Update based on the sg_mapping udata += sg_map->length; length -= sg_map->length; sc->send[chnl]->sg_map_1 = sg_map; // Let FPGA know about the scatter gather buffer. write_reg(sc, CHNL_REG(chnl, RX_SG_ADDR_LO_REG_OFF), (sc->send[chnl]->buf_hw_addr & 0xFFFFFFFF)); write_reg(sc, CHNL_REG(chnl, RX_SG_ADDR_HI_REG_OFF), ((sc->send[chnl]->buf_hw_addr>>32) & 0xFFFFFFFF)); write_reg(sc, CHNL_REG(chnl, RX_SG_LEN_REG_OFF), 4 * sg_map->num_sg); DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, send sg buf populated, %d sent\n", sc->id, chnl, sg_map->num_sg); // Continue until we get a message or timeout. while (1) { while ((nomsg = pop_circ_queue(sc->send[chnl]->msgs, &msg_type, &msg))) { prepare_to_wait(&sc->send[chnl]->waitq, &wait, TASK_INTERRUPTIBLE); // Another check before we schedule. if ((nomsg = pop_circ_queue(sc->send[chnl]->msgs, &msg_type, &msg))) tymeout = schedule_timeout(tymeout); finish_wait(&sc->send[chnl]->waitq, &wait); if (signal_pending(current)) { free_sg_buf(sc, sc->send[chnl]->sg_map_0); free_sg_buf(sc, sc->send[chnl]->sg_map_1); return -ERESTARTSYS; } if (!nomsg) break; if (tymeout == 0) { printk(KERN_ERR "riffa: fpga:%d chnl:%d, send timed out\n", sc->id, chnl); free_sg_buf(sc, sc->send[chnl]->sg_map_0); free_sg_buf(sc, sc->send[chnl]->sg_map_1); return (unsigned int)(sent>>2); } } tymeout = tymeouto; // Process the message. switch (msg_type) { case EVENT_SG_BUF_READ: // Release the previous scatter gather data? if (sc->send[chnl]->sg_map_0 != NULL) sent += sc->send[chnl]->sg_map_0->length; free_sg_buf(sc, sc->send[chnl]->sg_map_0); sc->send[chnl]->sg_map_0 = NULL; // Populate the common buffer with more scatter gather data? if (length > 0) { sg_map = fill_sg_buf(sc, chnl, sc->send[chnl]->buf_addr, udata, length, 0, DMA_TO_DEVICE); if (sg_map == NULL || sg_map->num_sg == 0) { free_sg_buf(sc, sc->send[chnl]->sg_map_0); free_sg_buf(sc, sc->send[chnl]->sg_map_1); return (unsigned int)(sent>>2); } // Update based on the sg_mapping udata += sg_map->length; length -= sg_map->length; sc->send[chnl]->sg_map_0 = sc->send[chnl]->sg_map_1; sc->send[chnl]->sg_map_1 = sg_map; write_reg(sc, CHNL_REG(chnl, RX_SG_ADDR_LO_REG_OFF), (sc->send[chnl]->buf_hw_addr & 0xFFFFFFFF)); write_reg(sc, CHNL_REG(chnl, RX_SG_ADDR_HI_REG_OFF), ((sc->send[chnl]->buf_hw_addr>>32) & 0xFFFFFFFF)); write_reg(sc, CHNL_REG(chnl, RX_SG_LEN_REG_OFF), 4 * sg_map->num_sg); DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, send sg buf populated, %d sent\n", sc->id, chnl, sg_map->num_sg); } break; case EVENT_TXN_DONE: // Update with the true value of words transferred. sent = (((unsigned long long)msg)<<2); // Return as this is the end of the transaction. free_sg_buf(sc, sc->send[chnl]->sg_map_0); free_sg_buf(sc, sc->send[chnl]->sg_map_1); DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, sent %d words\n", sc->id, chnl, (unsigned int)(sent>>2)); return (unsigned int)(sent>>2); break; default: printk(KERN_ERR "riffa: fpga:%d chnl:%d, received unknown msg: %08x\n", sc->id, chnl, msg); break; } } return 0; } /** * Populates the fpga_info struct with the current FPGA state information. On * success, returns 0. On error, returns a negative value. */ static inline int list_fpgas(fpga_info_list * list) { int i; int num_fpgas = 0; struct fpga_state * sc; for (i = 0; i < NUM_FPGAS; ++i) { if (atomic_read(&used_fpgas[i])) { sc = fpgas[i]; list->id[num_fpgas] = sc->id; list->num_chnls[num_fpgas] = sc->num_chnls; list->vendor_id[num_fpgas] = sc->vendor_id; list->device_id[num_fpgas] = sc->device_id; memcpy(list->name[num_fpgas], sc->name, 16*sizeof(char)); num_fpgas++; } } // Zero out the rest for (i = num_fpgas; i < NUM_FPGAS; ++i) { list->id[i] = -1; list->num_chnls[i] = 0; list->vendor_id[i] = 0; list->device_id[i] = 0; memset(list->name[i], 0, 16*sizeof(char)); } list->num_fpgas = num_fpgas; return 0; } /** * Resets the driver for the specified FPGA. The fpga_state struct for all * channels will be reset as will the FPGA itself. */ static inline void reset(int id) { int i; unsigned int dummy0; unsigned int dummy1; struct fpga_state * sc; if (atomic_read(&used_fpgas[id])) { sc = fpgas[id]; // Disable interrupts atomic_set(&sc->intr_disabled, 1); // Reset the FPGA read_reg(sc, INFO_REG_OFF); // Reset all the channels for (i = 0; i < sc->num_chnls; ++i) { while (!pop_circ_queue(sc->send[i]->msgs, &dummy0, &dummy1)); while (!pop_circ_queue(sc->recv[i]->msgs, &dummy0, &dummy1)); wake_up(&sc->send[i]->waitq); wake_up(&sc->recv[i]->waitq); } // Enable interrupts atomic_set(&sc->intr_disabled, 0); } } /** * Main entry point for reading and writing on the device. Return value depends * on ioctlnum and expected behavior. See code for details. */ static long fpga_ioctl(struct file *filp, unsigned int ioctlnum, unsigned long ioctlparam) { int rc; fpga_chnl_io io; fpga_info_list list; switch (ioctlnum) { case IOCTL_SEND: if ((rc = copy_from_user(&io, (void *)ioctlparam, sizeof(fpga_chnl_io)))) { printk(KERN_ERR "riffa: cannot read ioctl user parameter.\n"); return rc; } if (io.id < 0 || io.id >= NUM_FPGAS || !atomic_read(&used_fpgas[io.id])) return 0; return chnl_send(fpgas[io.id], io.chnl, io.data, io.len, io.offset, io.last, io.timeout); case IOCTL_RECV: if ((rc = copy_from_user(&io, (void *)ioctlparam, sizeof(fpga_chnl_io)))) { printk(KERN_ERR "riffa: cannot read ioctl user parameter.\n"); return rc; } if (io.id < 0 || io.id >= NUM_FPGAS || !atomic_read(&used_fpgas[io.id])) return 0; return chnl_recv(fpgas[io.id], io.chnl, io.data, io.len, io.timeout); case IOCTL_LIST: list_fpgas(&list); if ((rc = copy_to_user((void *)ioctlparam, &list, sizeof(fpga_info_list)))) printk(KERN_ERR "riffa: cannot write ioctl user parameter.\n"); return rc; case IOCTL_RESET: reset((int)ioctlparam); break; default: break; } return 0; } /////////////////////////////////////////////////////// // PCI DRIVER HANDLERS /////////////////////////////////////////////////////// /** * Allocates and initializes chnl_dir structs for each channel. Returns the * number of chnl_dir structs allocated. */ static inline int __devinit allocate_chnls(struct pci_dev *dev, struct fpga_state * sc) { int i; dma_addr_t hw_addr; for (i = 0; i < sc->num_chnls; ++i) { // Allocate the recv struct sc->recv[i] = (struct chnl_dir *) kzalloc(sizeof(struct chnl_dir), GFP_KERNEL); if (sc->recv[i] == NULL) return i; init_waitqueue_head(&sc->recv[i]->waitq); if ((sc->recv[i]->msgs = init_circ_queue(5)) == NULL) { kfree(sc->recv[i]); return i; } sc->recv[i]->buf_addr = pci_alloc_consistent(dev, sc->sg_buf_size, &hw_addr); sc->recv[i]->buf_hw_addr = hw_addr; if (sc->recv[i]->buf_addr == NULL) { free_circ_queue(sc->recv[i]->msgs); kfree(sc->recv[i]); return i; } // Allocate the send struct sc->send[i] = (struct chnl_dir *) kzalloc(sizeof(struct chnl_dir), GFP_KERNEL); if (sc->send[i] == NULL) { pci_free_consistent(dev, sc->sg_buf_size, sc->recv[i]->buf_addr, (dma_addr_t)sc->recv[i]->buf_hw_addr); free_circ_queue(sc->recv[i]->msgs); kfree(sc->recv[i]); return i; } init_waitqueue_head(&sc->send[i]->waitq); if ((sc->send[i]->msgs = init_circ_queue(4)) == NULL) { kfree(sc->send[i]); pci_free_consistent(dev, sc->sg_buf_size, sc->recv[i]->buf_addr, (dma_addr_t)sc->recv[i]->buf_hw_addr); free_circ_queue(sc->recv[i]->msgs); kfree(sc->recv[i]); return i; } sc->send[i]->buf_addr = pci_alloc_consistent(dev, sc->sg_buf_size, &hw_addr); sc->send[i]->buf_hw_addr = hw_addr; if (sc->send[i]->buf_addr == NULL) { free_circ_queue(sc->send[i]->msgs); kfree(sc->send[i]); pci_free_consistent(dev, sc->sg_buf_size, sc->recv[i]->buf_addr, (dma_addr_t)sc->recv[i]->buf_hw_addr); free_circ_queue(sc->recv[i]->msgs); kfree(sc->recv[i]); return i; } } return i; } /** * Called by the OS when the device is ready for access. Returns 0 on success, * negative value on failure. */ static int __devinit fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) { int i; int j; int error; struct fpga_state * sc; dma_addr_t hw_addr; unsigned int reg; u32 lnkctl_result; u32 devctl_result; // Setup the PCIe device. error = pci_enable_device(dev); if (error < 0) { printk(KERN_ERR "riffa: pci_enable_device returned %d\n", error); return (-ENODEV); } // Enable bus master pci_set_master(dev); // Set the mask size error = pci_set_dma_mask(dev, DMA_BIT_MASK(64)); if (!error) error = pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64)); if (error) { printk(KERN_ERR "riffa: cannot set 64 bit DMA mode\n"); pci_disable_device(dev); return error; } // Allocate device structure. sc = kzalloc(sizeof(*sc), GFP_KERNEL); if (sc == NULL) { printk(KERN_ERR "riffa: not enough memory to allocate sc\n"); pci_disable_device(dev); return (-ENOMEM); } atomic_set(&sc->intr_disabled, 0); snprintf(sc->name, sizeof(sc->name), "%s%d", pci_name(dev), 0); sc->vendor_id = dev->vendor; sc->device_id = dev->device; printk(KERN_INFO "riffa: found FPGA with name: %s\n", sc->name); printk(KERN_INFO "riffa: vendor id: 0x%04X\n", sc->vendor_id); printk(KERN_INFO "riffa: device id: 0x%04X\n", sc->device_id); // Setup the BAR memory regions error = pci_request_regions(dev, sc->name); if (error < 0) { printk(KERN_ERR "riffa: pci_request_regions returned error: %d\n", error); pci_disable_device(dev); kfree(sc); return (-ENODEV); } // PCI BAR 0 sc->bar0_addr = pci_resource_start(dev, 0); sc->bar0_len = pci_resource_len(dev, 0); sc->bar0_flags = pci_resource_flags(dev, 0); printk(KERN_INFO "riffa: BAR 0 address: %llx\n", sc->bar0_addr); printk(KERN_INFO "riffa: BAR 0 length: %lld bytes\n", sc->bar0_len); if (sc->bar0_len != 1024) { printk(KERN_ERR "riffa: BAR 0 incorrect length\n"); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return (-ENODEV); } sc->bar0 = ioremap(sc->bar0_addr, sc->bar0_len); if (!sc->bar0) { printk(KERN_ERR "riffa: could not ioremap BAR 0\n"); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return (-ENODEV); } // Setup MSI interrupts error = pci_enable_msi(dev); if (error != 0) { printk(KERN_ERR "riffa: pci_enable_msi returned error: %d\n", error); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return error; } // Request an interrupt error = request_irq(dev->irq, intrpt_handler, IRQF_SHARED, sc->name, sc); if (error != 0) { printk(KERN_ERR "riffa: request_irq(%d) returned error: %d\n", dev->irq, error); pci_disable_msi(dev); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return error; } sc->irq = dev->irq; printk(KERN_INFO "riffa: MSI setup on irq %d\n", dev->irq); // Set extended tag bit error = pcie_capability_read_dword(dev,PCI_EXP_DEVCTL,&devctl_result); if (error != 0) { printk(KERN_ERR "riffa: pcie_capability_read_dword returned error: %d\n", error); free_irq(dev->irq, sc); pci_disable_msi(dev); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return error; } printk(KERN_INFO "riffa: PCIE_EXP_DEVCTL register: %x\n",devctl_result); error = pcie_capability_write_dword(dev,PCI_EXP_DEVCTL,(devctl_result|PCI_EXP_DEVCTL_EXT_TAG)); if (error != 0) { printk(KERN_ERR "riffa: pcie_capability_write_dword returned error: %d\n", error); free_irq(dev->irq, sc); pci_disable_msi(dev); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return error; } // Set RCB to 128 error = pcie_capability_read_dword(dev,PCI_EXP_LNKCTL,&lnkctl_result); if (error != 0) { printk(KERN_ERR "riffa: pcie_capability_read_dword returned error: %d\n", error); free_irq(dev->irq, sc); pci_disable_msi(dev); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return error; } printk(KERN_INFO "riffa: PCIE_EXP_LNKCTL register: %x\n",lnkctl_result); error = pcie_capability_write_dword(dev,PCI_EXP_LNKCTL,(lnkctl_result|PCI_EXP_LNKCTL_RCB)); if (error != 0) { printk(KERN_ERR "riffa: pcie_capability_write_dword returned error: %d\n", error); pcie_capability_write_dword(dev,PCI_EXP_DEVCTL,devctl_result); free_irq(dev->irq, sc); pci_disable_msi(dev); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return error; } // Read device configuration reg = read_reg(sc, INFO_REG_OFF); sc->num_chnls = ((reg>>0) & 0xF); sc->num_sg = SG_ELEMS*((reg>>19) & 0xF); sc->sg_buf_size = SG_BUF_SIZE*((reg>>19) & 0xF); printk(KERN_INFO "riffa: number of channels: %d\n", ((reg>>0) & 0xF)); printk(KERN_INFO "riffa: bus interface width: %d\n", ((reg>>19) & 0xF)<<5); printk(KERN_INFO "riffa: bus master enabled: %d\n", ((reg>>4) & 0x1)); printk(KERN_INFO "riffa: negotiated link width: %d\n", ((reg>>5) & 0x3F)); printk(KERN_INFO "riffa: negotiated link rate: %d MTs\n", ((reg>>11) & 0x3)*2500); printk(KERN_INFO "riffa: max downstream payload: %d bytes\n", 128<<((reg>>13) & 0x7) ); printk(KERN_INFO "riffa: max upstream payload: %d bytes\n", 128<<((reg>>16) & 0x7) ); if (((reg>>4) & 0x1) != 1) { printk(KERN_ERR "riffa: bus master not enabled!\n"); pcie_capability_write_dword(dev,PCI_EXP_LNKCTL,lnkctl_result); pcie_capability_write_dword(dev,PCI_EXP_DEVCTL,devctl_result); free_irq(dev->irq, sc); pci_disable_msi(dev); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return (-ENODEV); } if (((reg>>5) & 0x3F) == 0 || ((reg>>11) & 0x3) == 0) { printk(KERN_ERR "riffa: bad link parameters!\n"); pcie_capability_write_dword(dev,PCI_EXP_LNKCTL,lnkctl_result); pcie_capability_write_dword(dev,PCI_EXP_DEVCTL,devctl_result); free_irq(dev->irq, sc); pci_disable_msi(dev); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return (-ENODEV); } if ((reg & 0xF) == 0 || (reg & 0xF) > MAX_CHNLS) { printk(KERN_ERR "riffa: bad number of channels!\n"); pcie_capability_write_dword(dev,PCI_EXP_LNKCTL,lnkctl_result); pcie_capability_write_dword(dev,PCI_EXP_DEVCTL,devctl_result); free_irq(dev->irq, sc); pci_disable_msi(dev); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return (-ENODEV); } if (((reg>>19) & 0xF) == 0 || ((reg>>19) & 0xF) > MAX_BUS_WIDTH_PARAM) { printk(KERN_ERR "riffa: bad bus width!\n"); pcie_capability_write_dword(dev,PCI_EXP_LNKCTL,lnkctl_result); pcie_capability_write_dword(dev,PCI_EXP_DEVCTL,devctl_result); free_irq(dev->irq, sc); pci_disable_msi(dev); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return (-ENODEV); } // Create chnl_dir structs. sc->recv = (struct chnl_dir **) kzalloc(sc->num_chnls*sizeof(struct chnl_dir*), GFP_KERNEL); sc->send = (struct chnl_dir **) kzalloc(sc->num_chnls*sizeof(struct chnl_dir*), GFP_KERNEL); if (sc->recv == NULL || sc->send == NULL) { printk(KERN_ERR "riffa: not enough memory to allocate chnl_dir arrays\n"); if (sc->recv != NULL) kfree(sc->recv); if (sc->send != NULL) kfree(sc->send); pcie_capability_write_dword(dev,PCI_EXP_LNKCTL,lnkctl_result); pcie_capability_write_dword(dev,PCI_EXP_DEVCTL,devctl_result); free_irq(dev->irq, sc); pci_disable_msi(dev); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return (-ENOMEM); } j = allocate_chnls(dev, sc); if (j < sc->num_chnls) { sc->num_chnls = j; printk(KERN_ERR "riffa: not enough memory to allocate chnl_dir structs\n"); for (i = 0; i < sc->num_chnls; ++i) { pci_free_consistent(dev, sc->sg_buf_size, sc->send[i]->buf_addr, (dma_addr_t)sc->send[i]->buf_hw_addr); pci_free_consistent(dev, sc->sg_buf_size, sc->recv[i]->buf_addr, (dma_addr_t)sc->recv[i]->buf_hw_addr); free_circ_queue(sc->send[i]->msgs); free_circ_queue(sc->recv[i]->msgs); kfree(sc->send[i]); kfree(sc->recv[i]); } kfree(sc->recv); kfree(sc->send); pcie_capability_write_dword(dev,PCI_EXP_LNKCTL,lnkctl_result); pcie_capability_write_dword(dev,PCI_EXP_DEVCTL,devctl_result); free_irq(dev->irq, sc); pci_disable_msi(dev); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return (-ENOMEM); } // Create spill buffer (for overflow on receive). sc->spill_buf_addr = pci_alloc_consistent(dev, SPILL_BUF_SIZE, &hw_addr); sc->spill_buf_hw_addr = hw_addr; if (sc->spill_buf_addr == NULL) { printk(KERN_ERR "riffa: not enough memory to allocate spill buffer\n"); for (i = 0; i < sc->num_chnls; ++i) { pci_free_consistent(dev, sc->sg_buf_size, sc->send[i]->buf_addr, (dma_addr_t)sc->send[i]->buf_hw_addr); pci_free_consistent(dev, sc->sg_buf_size, sc->recv[i]->buf_addr, (dma_addr_t)sc->recv[i]->buf_hw_addr); free_circ_queue(sc->send[i]->msgs); free_circ_queue(sc->recv[i]->msgs); kfree(sc->send[i]); kfree(sc->recv[i]); } pcie_capability_write_dword(dev,PCI_EXP_LNKCTL,lnkctl_result); pcie_capability_write_dword(dev,PCI_EXP_DEVCTL,devctl_result); kfree(sc->recv); kfree(sc->send); free_irq(dev->irq, sc); pci_disable_msi(dev); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); } // Save pointer to structure pci_set_drvdata(dev, sc); sc->dev = dev; sc->id = -1; for (i = 0; i < NUM_FPGAS; i++) { if (!atomic_xchg(&used_fpgas[i], 1)) { sc->id = i; fpgas[i] = sc; break; } } if (sc->id == -1) { printk(KERN_ERR "riffa: could not save FPGA information, %d is limit.\n", NUM_FPGAS); for (i = 0; i < sc->num_chnls; ++i) { pci_free_consistent(dev, sc->sg_buf_size, sc->send[i]->buf_addr, (dma_addr_t)sc->send[i]->buf_hw_addr); pci_free_consistent(dev, sc->sg_buf_size, sc->recv[i]->buf_addr, (dma_addr_t)sc->recv[i]->buf_hw_addr); free_circ_queue(sc->send[i]->msgs); free_circ_queue(sc->recv[i]->msgs); kfree(sc->send[i]); kfree(sc->recv[i]); } kfree(sc->recv); kfree(sc->send); pci_free_consistent(dev, SPILL_BUF_SIZE, sc->spill_buf_addr, (dma_addr_t)sc->spill_buf_hw_addr); pcie_capability_write_dword(dev,PCI_EXP_LNKCTL,lnkctl_result); pcie_capability_write_dword(dev,PCI_EXP_DEVCTL,devctl_result); free_irq(dev->irq, sc); pci_disable_msi(dev); iounmap(sc->bar0); pci_release_regions(dev); pci_disable_device(dev); kfree(sc); return (-ENOMEM); } else { printk(KERN_INFO "riffa: saved FPGA with id: %d\n", sc->id); } return 0; } /** * Called when the device is unloaded. */ static void __devexit fpga_remove(struct pci_dev *dev) { int i; u32 result; struct fpga_state * sc; pcie_capability_read_dword(dev,PCI_EXP_DEVCTL,&result); pcie_capability_write_dword(dev,PCI_EXP_DEVCTL,result & (~PCI_EXP_DEVCTL_EXT_TAG)); pcie_capability_read_dword(dev,PCI_EXP_DEVCTL,&result); pcie_capability_write_dword(dev,PCI_EXP_LNKCTL,result & (~PCI_EXP_LNKCTL_RCB)); if ((sc = (struct fpga_state *)pci_get_drvdata(dev)) != NULL) { // Free structs, memory regions, etc. atomic_set(&used_fpgas[sc->id], 0); for (i = 0; i < sc->num_chnls; ++i) { pci_free_consistent(dev, sc->sg_buf_size, sc->send[i]->buf_addr, (dma_addr_t)sc->send[i]->buf_hw_addr); pci_free_consistent(dev, sc->sg_buf_size, sc->recv[i]->buf_addr, (dma_addr_t)sc->recv[i]->buf_hw_addr); free_circ_queue(sc->send[i]->msgs); free_circ_queue(sc->recv[i]->msgs); kfree(sc->send[i]); kfree(sc->recv[i]); } kfree(sc->recv); kfree(sc->send); pci_free_consistent(dev, SPILL_BUF_SIZE, sc->spill_buf_addr, (dma_addr_t)sc->spill_buf_hw_addr); free_irq(dev->irq, sc); iounmap(sc->bar0); kfree(sc); } pci_disable_msi(dev); pci_release_regions(dev); pci_disable_device(dev); pci_set_drvdata(dev, NULL); } /////////////////////////////////////////////////////// // MODULE INIT/EXIT FUNCTIONS /////////////////////////////////////////////////////// static DEFINE_PCI_DEVICE_TABLE(fpga_ids) = { {PCI_DEVICE(VENDOR_ID0, PCI_ANY_ID)}, {PCI_DEVICE(VENDOR_ID1, PCI_ANY_ID)}, {0}, }; MODULE_DEVICE_TABLE(pci, fpga_ids); static struct pci_driver fpga_driver = { .name = DEVICE_NAME, .id_table = fpga_ids, .probe = fpga_probe, .remove = __devexit_p(fpga_remove), }; static const struct file_operations fpga_fops = { .owner = THIS_MODULE, .unlocked_ioctl = fpga_ioctl, }; /** * Called to initialize the PCI device. */ static int __init fpga_init(void) { int i; int error; for (i = 0; i < NUM_FPGAS; i++) atomic_set(&used_fpgas[i], 0); error = pci_register_driver(&fpga_driver); if (error != 0) { printk(KERN_ERR "riffa: pci_module_register returned %d\n", error); return (error); } error = register_chrdev(MAJOR_NUM, DEVICE_NAME, &fpga_fops); if (error < 0) { printk(KERN_ERR "riffa: register_chrdev returned %d\n", error); return (error); } mymodule_class = class_create(THIS_MODULE, DEVICE_NAME); if (IS_ERR(mymodule_class)) { error = PTR_ERR(mymodule_class); printk(KERN_ERR "riffa: class_create() returned %d\n", error); return (error); } devt = MKDEV(MAJOR_NUM, 0); device_create(mymodule_class, NULL, devt, "%s", DEVICE_NAME); return 0; } /** * Called to destroy the PCI device. */ static void __exit fpga_exit(void) { device_destroy(mymodule_class, devt); class_destroy(mymodule_class); pci_unregister_driver(&fpga_driver); unregister_chrdev(MAJOR_NUM, DEVICE_NAME); } module_init(fpga_init); module_exit(fpga_exit); ================================================ FILE: sw/riffa_2.1/driver/linux/riffa_driver.h ================================================ /******************************************************************************* * This software is Copyright © 2012 The Regents of the University of * California. All Rights Reserved. * * Permission to copy, modify, and distribute this software and its * documentation for educational, research and non-profit purposes, without fee, * and without a written agreement is hereby granted, provided that the above * copyright notice, this paragraph and the following three paragraphs appear in * all copies. * * Permission to make commercial use of this software may be obtained by * contacting: * Technology Transfer Office * 9500 Gilman Drive, Mail Code 0910 * University of California * La Jolla, CA 92093-0910 * (858) 534-5815 * invent@ucsd.edu * * This software program and documentation are copyrighted by The Regents of the * University of California. The software program and documentation are supplied * "as is", without any accompanying services from The Regents. The Regents does * not warrant that the operation of the program will be uninterrupted or error- * free. The end-user understands that the program was developed for research * purposes and is advised not to rely exclusively on the program for any * reason. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR * CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, * EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF * CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, * AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. */ /* * Filename: riffa_driver.h * Version: 2.0 * Description: Linux PCIe device driver for RIFFA. Uses Linux kernel APIs in * version 2.6.27+ (tested on version 2.6.32 - 3.3.0). * Author: Matthew Jacobsen * History: @mattj: Initial release. Version 2.0. */ #ifndef RIFFA_DRIVER_H #define RIFFA_DRIVER_H #include #define DBUG 1 #ifdef DEBUG #define DEBUG_MSG(...) printk(__VA_ARGS__) #else #define DEBUG_MSG(...) #endif // The major device number. We can't rely on dynamic registration because ioctls // need to know it. #define MAJOR_NUM 100 #define DEVICE_NAME "riffa" #define VENDOR_ID0 0x10EE #define VENDOR_ID1 0x1172 // Message events for readmsgs/writemsgs queues. #define EVENT_TXN_LEN 1 #define EVENT_TXN_OFFLAST 2 #define EVENT_TXN_DONE 3 #define EVENT_SG_BUF_READ 4 // Constants and device offsets #define NUM_FPGAS 5 // max # of FPGAs to support in a single PC #define MAX_CHNLS 12 // max # of channels per FPGA #define MAX_BUS_WIDTH_PARAM 4 // max bus width parameter #define SG_BUF_SIZE (4*1024) // size of shared SG buffer #define SG_ELEMS 200 // # of SG elements to transfer at a time #define SPILL_BUF_SIZE (4*1024) // size of shared spill common buffer #define RX_SG_LEN_REG_OFF 0x0 // config offset for RX SG buf length #define RX_SG_ADDR_LO_REG_OFF 0x1 // config offset for RX SG buf low addr #define RX_SG_ADDR_HI_REG_OFF 0x2 // config offset for RX SG buf high addr #define RX_LEN_REG_OFF 0x3 // config offset for RX txn length #define RX_OFFLAST_REG_OFF 0x4 // config offset for RX txn last/offset #define RX_TNFR_LEN_REG_OFF 0xD // config offset for RX transfer length #define TX_SG_LEN_REG_OFF 0x5 // config offset for TX SG buf length #define TX_SG_ADDR_LO_REG_OFF 0x6 // config offset for TX SG buf low addr #define TX_SG_ADDR_HI_REG_OFF 0x7 // config offset for TX SG buf high addr #define TX_LEN_REG_OFF 0x8 // config offset for TX txn length #define TX_OFFLAST_REG_OFF 0x9 // config offset for TX txn last/offset #define TX_TNFR_LEN_REG_OFF 0xE // config offset for TX transfer length #define INFO_REG_OFF 0xA // config offset for link info #define IRQ_REG0_OFF 0xB // config offset for interrupt reg 0 #define IRQ_REG1_OFF 0xC // config offset for interrupt reg 1 // Structs struct fpga_chnl_io { int id; int chnl; unsigned int len; unsigned int offset; unsigned int last; unsigned long long timeout; char * data; }; typedef struct fpga_chnl_io fpga_chnl_io; struct fpga_info_list { int num_fpgas; int id[NUM_FPGAS]; int num_chnls[NUM_FPGAS]; char name[NUM_FPGAS][16]; int vendor_id[NUM_FPGAS]; int device_id[NUM_FPGAS]; }; typedef struct fpga_info_list fpga_info_list; // IOCTLs #define IOCTL_SEND _IOW(MAJOR_NUM, 1, fpga_chnl_io *) #define IOCTL_RECV _IOR(MAJOR_NUM, 2, fpga_chnl_io *) #define IOCTL_LIST _IOR(MAJOR_NUM, 3, fpga_info_list *) #define IOCTL_RESET _IOW(MAJOR_NUM, 4, int) #endif ================================================ FILE: sw/riffa_2.1/driver/windows/README.txt ================================================ To build the Windows driver: 1) Install Windows Driver Development Kit supporting Windows 7 (tested on version 7600.16385.1). 2) Open a DDK command window environment for Windows 7 (which ever version you're targeting). 3) Move to the directory containing this README.txt and run: build -ceZ 4) The driver should be built and ready in the output directory along with a Windows 7 catalog file and the coinstaller DLLs. A few notes: - You will need to sign the driver (riffa.sys) and catalog file (riffa.cat) before you can install it on a x64 Windows 7 or Vista computer. The build process will attempt to sign the catalog file with the UCSD certificate. You don't have that, so you won't get a signed driver simply by building. You'll need to get a certificate from a certificate authority that is capable of cross-certificate kernel driver signing. See this page for more details: http://msdn.microsoft.com/en-us/windows/hardware/gg487315.aspx - Debugging on Windows is difficult because there exists no kernel log file. Drivers are supposed to log messages using a trace events framework which is overly complex and requires developer tools to first collect the output and then more (different) tools to make the output human readable. Instead, this driver writes normal log messages via a kernel debugger facility. To see the messages you'll need the Windows Development Kit debugger (WinDbg) or a small utility called DbgView. DbgView is a standalone kernel debug viewer that can be downloaded from Microsoft here: http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx Just start with administrator privileges and be sure to enable Capture Kernel, Capture Events, and Capture Verbose Kernel Output. - Building with the checked environment will produce a version of the driver with verbose debugging output. Building with the free environment will produce a version of the driver with minimal messaging output. The debug version will have a "(Debug)" label in the Windows device manager, so you can tell which version is installed. - Inno Setup scripts produce a Windows Installer. You may use our script if you like. ================================================ FILE: sw/riffa_2.1/driver/windows/dirs ================================================ DIRS= \ sys ================================================ FILE: sw/riffa_2.1/driver/windows/install/install.bat ================================================ @echo off rmdir /s /q build md build md build\x86 md build\x64 copy win7.iss .\build copy license.txt .\build xcopy /E /H /K /I /Y %1 .\build\x86 xcopy /E /H /K /I /Y %2 .\build\x64 xcopy /E /H /K /I /Y ..\..\..\c_c++\windows .\build\c_c++ xcopy /E /H /K /I /Y ..\..\..\java .\build\java xcopy /E /H /K /I /Y ..\..\..\python .\build\python xcopy /E /H /K /I /Y ..\..\..\matlab .\build\matlab if "%3" == "chk" ( "c:\program files\inno setup 5\iscc.exe" /dDebug="1" /o.\build .\build\win7.iss ) else ( "c:\program files\inno setup 5\iscc.exe" /o.\build .\build\win7.iss ) signtool sign /v /s my /n "University of California, San Diego" /t http://timestamp.verisign.com/scripts/timestamp.dll .\build\setup.exe ================================================ FILE: sw/riffa_2.1/driver/windows/install/license.txt ================================================ This software is Copyright 2012 The Regents of the University of California. All Rights Reserved. Permission to copy, modify, and distribute this software and its documentation for educational, research and non-profit purposes, without fee, and without a written agreement is hereby granted, provided that the above copyright notice, this paragraph and the following three paragraphs appear in all copies. Permission to make commercial use of this software may be obtained by contacting: Technology Transfer Office 9500 Gilman Drive, Mail Code 0910 University of California La Jolla, CA 92093-0910 (858) 534-5815 invent@ucsd.edu This software program and documentation are copyrighted by The Regents of the University of California. The software program and documentation are supplied "as is", without any accompanying services from The Regents. The Regents does not warrant that the operation of the program will be uninterrupted or error-free. The end-user understands that the program was developed for research purposes and is advised not to rely exclusively on the program for any reason. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ================================================ FILE: sw/riffa_2.1/driver/windows/install/win7.iss ================================================ ; -- 64Bit.iss -- ; Demonstrates installation of a program built for the x64 (a.k.a. AMD64) ; architecture. ; To successfully run this installation and the program it installs, ; you must have a "x64" edition of Windows. ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING .ISS SCRIPT FILES! #ifdef Debug #define DebugMsg1 "%n%nNOTE: This version has been compiled to output additional debug messages (with some performance overhead)." #else #define DebugMsg1 "" #endif [Setup] AppName=RIFFA AppVersion=2.0 AppPublisher=University of California, San Diego AppPublisherURL=https://sites.google.com/a/eng.ucsd.edu/matt-jacobsen/riffa AppCopyright=Copyright (C) 2012 The Regents of the University of California. All Rights Reserved. LicenseFile=license.txt PrivilegesRequired=admin MinVersion=6.1 OnlyBelowVersion=6.2 DisableProgramGroupPage=yes Compression=lzma2 SolidCompression=yes UsePreviousAppDir=no DefaultDirName={pf}\Riffa OutputDir=outputdir ; "ArchitecturesInstallIn64BitMode=x64" requests that the install be ; done in "64-bit mode" on x64, meaning it should use the native ; 64-bit Program Files directory and the 64-bit view of the registry. ArchitecturesInstallIn64BitMode=x64 [Messages] WelcomeLabel1=Welcome to the [name] Setup Wizard WelcomeLabel2=This will install the [name/ver] FPGA drivers and C/C++ bindings on your computer.{#DebugMsg1}%n%nSee the install program directory for details on installing other language bindings.%n%nIt is recommended that you close all other applications and disable any anti virus before continuing. FinishedLabelNoIcons=Setup has finished installing [name/ver] on your computer.%n%nAny [name] compatible FPGA devices should be detected upon reboot. [Dirs] Name: "{app}\c_c++"; Permissions: users-modify Name: "{app}\java"; Permissions: users-modify Name: "{app}\python"; Permissions: users-modify Name: "{app}\matlab"; Permissions: users-modify [Files] Source: "c_c++\x86\riffa.lib"; DestDir: "{app}\c_c++"; Check: "not IsWin64" Source: "c_c++\x86\riffa.h"; DestDir: "{app}\c_c++"; Check: "not IsWin64" Source: "c_c++\x86\sample_app\README.txt"; DestDir: "{app}\c_c++"; Check: "not IsWin64" Source: "c_c++\x86\sample_app\timer.h"; DestDir: "{app}\c_c++"; Check: "not IsWin64" Source: "c_c++\x86\sample_app\testutil.c"; DestDir: "{app}\c_c++"; Check: "not IsWin64" Source: "c_c++\x86\sample_app\testutil.exe"; DestDir: "{app}\c_c++"; Check: "not IsWin64" Source: "c_c++\x64\riffa.lib"; DestDir: "{app}\c_c++"; Check: IsWin64 Source: "c_c++\x64\riffa.h"; DestDir: "{app}\c_c++"; Check: IsWin64 Source: "c_c++\x64\sample_app\README.txt"; DestDir: "{app}\c_c++"; Check: IsWin64 Source: "c_c++\x64\sample_app\timer.h"; DestDir: "{app}\c_c++"; Check: IsWin64 Source: "c_c++\x64\sample_app\testutil.c"; DestDir: "{app}\c_c++"; Check: IsWin64 Source: "c_c++\x64\sample_app\testutil.exe"; DestDir: "{app}\c_c++"; Check: IsWin64 Source: "java\README.txt"; DestDir: "{app}\java" Source: "java\riffa.jar"; DestDir: "{app}\java" Source: "java\SampleApp.java"; DestDir: "{app}\java" Source: "matlab\README.txt"; DestDir: "{app}\matlab" Source: "matlab\Riffa.m"; DestDir: "{app}\matlab" Source: "python\dist\README.txt"; DestDir: "{app}\python" Source: "python\dist\riffa-2.0.zip"; DestDir: "{app}\python" Source: "python\sample_app\sampleapp.py"; DestDir: "{app}\python" Source: "x86\riffa.sys"; DestDir: "{tmp}"; Check: "not IsWin64" Source: "x86\riffa.inf"; DestDir: "{tmp}"; Check: "not IsWin64" Source: "x86\riffa.cat"; DestDir: "{tmp}"; Check: "not IsWin64" Source: "x86\WdfCoInstaller01009.dll"; DestDir: "{tmp}"; Check: "not IsWin64" Source: "x86\WdfCoInstaller01009_chk.dll"; DestDir: "{tmp}"; Check: "not IsWin64" Source: "x64\riffa.sys"; DestDir: "{tmp}"; Check: IsWin64 Source: "x64\riffa.inf"; DestDir: "{tmp}"; Check: IsWin64 Source: "x64\riffa.cat"; DestDir: "{tmp}"; Check: IsWin64 Source: "x64\WdfCoInstaller01009.dll"; DestDir: "{tmp}"; Check: IsWin64 Source: "x64\WdfCoInstaller01009_chk.dll"; DestDir: "{tmp}"; Check: IsWin64 Source: "c_c++\x86\riffa.dll"; DestDir: {sys}; Flags: 32bit; Check: "not IsWin64" Source: "c_c++\x64\riffa.dll"; DestDir: {sys}; Flags: 64bit; Check: IsWin64 [Run] Filename: "{sys}\pnputil.exe"; Parameters: " -i -a {tmp}\riffa.inf"; WorkingDir: "{tmp}"; Description: "Install driver"; StatusMsg: "Installing drivers..."; Flags: runascurrentuser runhidden; ================================================ FILE: sw/riffa_2.1/driver/windows/sys/makefile ================================================ # # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source # file to this component. This file merely indirects to the real make file # that is shared by all the components of Windows # !INCLUDE $(NTMAKEENV)\makefile.def ================================================ FILE: sw/riffa_2.1/driver/windows/sys/makefile.inc ================================================ _LNG=$(LANGUAGE) _INX=. STAMP=stampinf -f $@ -a $(_BUILDARCH) -k $(KMDF_VERSION_MAJOR).$(KMDF_VERSION_MINOR) $(OBJ_PATH)\$(O)\$(INF_NAME).inf: $(_INX)\$(INF_NAME).inx copy $(_INX)\$(@B).inx $@ $(STAMP) ! if "$(DDKBUILDENV)" == "chk" echo RIFFA.DEBUG=" (Debug)" >> $@ ! else echo RIFFA.DEBUG="" >> $@ ! endif POST: copy $(BASEDIR)\redist\wdf\$(_BUILDARCH)\WdfCoInstaller*.dll $(OBJ_PATH)\$(O) ! if "$(DDK_TARGET_OS)" == "Win7" ! if "$(_BUILDARCH)" == "x86" inf2cat /driver:$(OBJ_PATH)\$(O) /os:7_x86 ! else inf2cat /driver:$(OBJ_PATH)\$(O) /os:7_x64 ! endif ! endif signtool sign /v /ac "$(_INX)\GlobalSign Root CA.crt" /s my /n "University of California, San Diego" /t http://timestamp.verisign.com/scripts/timestamp.dll $(OBJ_PATH)\$(O)\$(INF_NAME).cat signtool sign /v /ac "$(_INX)\GlobalSign Root CA.crt" /s my /n "University of California, San Diego" /t http://timestamp.verisign.com/scripts/timestamp.dll $(OBJ_PATH)\$(O)\$(INF_NAME).sys ================================================ FILE: sw/riffa_2.1/driver/windows/sys/precomp.h ================================================ #define WIN9X_COMPAT_SPINLOCK #include #pragma warning(disable:4201) // nameless struct/union warning #include #include #include #include #include #pragma warning(default:4201) #include // required for GUID definitions #include // required for WMILIB_CONTEXT #include "riffa_driver.h" #include "riffa_private.h" #include "trace.h" ================================================ FILE: sw/riffa_2.1/driver/windows/sys/riffa.c ================================================ #include "precomp.h" // The trace message header (.tmh) file must be included in a source file // before any WPP macro calls and after defining a WPP_CONTROL_GUIDS // macro (defined in toaster.h). During the compilation, WPP scans the source // files for DoTraceMessage() calls and builds a .tmh file which stores a unique // data GUID for each message, the text resource string for each message, // and the data types of the variables passed in for each message. This file // is automatically generated by the WPP preprocessor. // #include "riffa.tmh" #ifdef ALLOC_PRAGMA #pragma alloc_text (INIT, DriverEntry) #pragma alloc_text (PAGE, RiffaEvtDeviceAdd) #pragma alloc_text (PAGE, RiffaEvtDriverContextCleanup) #pragma alloc_text (PAGE, RiffaEvtDevicePrepareHardware) #pragma alloc_text (PAGE, RiffaEvtDeviceReleaseHardware) #endif /** * DriverEntry initializes the driver and is the first routine called by the * system after the driver is loaded. DriverEntry configures and creates a WDF driver * object. * . * DriverObject - represents the instance of the function driver that is loaded * into memory. DriverObject is allocated by the system before the * driver is loaded, and it is released by the system after the system unloads * the function driver from memory. * * RegistryPath - represents the driver specific path in the Registry. * The function driver can use the path to store driver related data between * reboots. The path does not store hardware instance specific data. * * Returns STATUS_SUCCESS if successful, STATUS_UNSUCCESSFUL otherwise. */ NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_SUCCESS; WDF_DRIVER_CONFIG config; WDF_OBJECT_ATTRIBUTES attributes; // Initialize WDF WPP tracing. WPP_INIT_TRACING(DriverObject, RegistryPath); // TraceEvents function is mapped to DoTraceMessage provided by // WPP by using a directive in the sources file. TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "RIFFA Driver."); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "Built %s %s", __DATE__, __TIME__); // Initialize the Driver Config structure. WDF_DRIVER_CONFIG_INIT(&config, RiffaEvtDeviceAdd); // Register a cleanup callback so that we can call WPP_CLEANUP when // the framework driver object is deleted during driver unload. WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.EvtCleanupCallback = RiffaEvtDriverContextCleanup; // Create the WDFDRIVER object status = WdfDriverCreate(DriverObject, RegistryPath, &attributes, &config, WDF_NO_HANDLE); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfDriverCreate failed\n"); // Cleanup tracing here because DriverContextCleanup will not be called // as we have failed to create WDFDRIVER object itself. WPP_CLEANUP(DriverObject); } return status; } /****************************************************************************** * PNP EVENT CALLBACKS *****************************************************************************/ /** * Called by the framework in response to AddDevice call from the PnP manager. * We create and initialize a WDF device object to represent a new instance of * our device. * . * Driver - Handle to a framework driver object created in DriverEntry * * DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. * * Returns STATUS_SUCCESS if successful, another status otherwise. */ NTSTATUS RiffaEvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) { NTSTATUS status = STATUS_SUCCESS; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES attributes; WDF_IO_QUEUE_CONFIG queueConfig; WDF_DMA_ENABLER_CONFIG dmaConfig; WDF_INTERRUPT_CONFIG intrConfig; WDFDEVICE device; PDEVICE_EXTENSION devExt = NULL; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); // Setup direct I/O for read & write operations WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); // Zero out the PnpPowerCallbacks structure. WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // Register the PnP Callbacks. pnpPowerCallbacks.EvtDevicePrepareHardware = RiffaEvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = RiffaEvtDeviceReleaseHardware; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); // Initialize FDO Request context. WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_EXTENSION); WdfDeviceInitSetRequestAttributes(DeviceInit, &attributes); // Initialize FDO Attributes. WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION); // Create the device status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { // Device Initialization failed. DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: DeviceCreate failed\n"); return status; } // Get the DeviceExtension and initialize it. RiffaGetDeviceContext is an // inline function defined by the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro // in the private header file. This function will do the type checking and // return the device context. If you pass a wrong object a wrong object handle // it will return NULL and assert if run under framework verifier mode. devExt = RiffaGetDeviceContext(device); memset(devExt->IntrData, 0, 2 * RIFFA_MAX_NUM_CHNLS * sizeof(INTR_CHNL_DIR_DATA)); memset(devExt->Chnl, 0, 2 * RIFFA_MAX_NUM_CHNLS * sizeof(CHNL_DIR_STATE)); devExt->Device = device; // Create a new IO Queue for IRP_MJ_DEVICE_CONTROL requests. WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoDeviceControl = RiffaEvtIoDeviceControl; status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &devExt->IoctlQueue); if(!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfIoQueueCreate failed\n"); return status; } // Set the Ioctl Queue forwarding for IRP_MJ_DEVICE_CONTROL requests. status = WdfDeviceConfigureRequestDispatching(device, devExt->IoctlQueue, WdfRequestTypeDeviceControl); if(!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: DeviceConfigureRequestDispatching failed\n"); return status; } // Create a WDFINTERRUPT object. WDF_INTERRUPT_CONFIG_INIT(&intrConfig, RiffaEvtInterruptIsr, RiffaEvtInterruptDpc); intrConfig.AutomaticSerialization = TRUE; status = WdfInterruptCreate(device, &intrConfig, WDF_NO_OBJECT_ATTRIBUTES, &devExt->Interrupt); if(!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfInterruptCreate failed\n"); return status; } // Create a new DMA Enabler instance. Use Scatter/Gather, 64-bit Addresses, // Duplex-type profile, 4-byte alignment. WdfDeviceSetAlignmentRequirement(device, FILE_LONG_ALIGNMENT); WDF_DMA_ENABLER_CONFIG_INIT(&dmaConfig, WdfDmaProfileScatterGather64Duplex, RIFFA_MAX_TNFR_LEN); status = WdfDmaEnablerCreate(device, &dmaConfig, WDF_NO_OBJECT_ATTRIBUTES, &devExt->DmaEnabler); if (!NT_SUCCESS (status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfDmaEnablerCreate failed\n"); return status; } // Tell the Framework that this device will need an interface // NOTE: See the note in public.h concerning this GUID value. status = WdfDeviceCreateDeviceInterface(device, &GUID_RIFFA_INTERFACE, NULL); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: DeviceCreateDeviceInterface failed\n"); return status; } return status; } /** * Free all the resources allocated in DriverEntry. * . * Driver - handle to a WDF Driver object. */ VOID RiffaEvtDriverContextCleanup(IN WDFDRIVER Driver) { PAGED_CODE (); WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver)); } /** * Performs whatever initialization is needed to setup the device, setting up * a DMA channel or mapping any I/O port resources. This will only be called * as a device starts or restarts, not every time the device moves into the D0 * state. * . * Device - A handle to the WDFDEVICE * * Resources - The raw PnP resources associated with the device. * * ResourcesTranslated - The translated PnP resources associated with the device. * * Returns STATUS_SUCCESS if successful, another status otherwise. Failure will * result in the device stack being torn down. */ NTSTATUS RiffaEvtDevicePrepareHardware(WDFDEVICE Device, WDFCMRESLIST Resources, WDFCMRESLIST ResourcesTranslated) { NTSTATUS status; PDEVICE_EXTENSION devExt; PTIMER_EXTENSION timerExt; WDF_TIMER_CONFIG timerConfig; WDF_OBJECT_ATTRIBUTES attributes; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; BOOLEAN foundBar0 = FALSE; UINT32 info; UINT32 i; UNREFERENCED_PARAMETER(Resources); PAGED_CODE(); // Get the device extension devExt = RiffaGetDeviceContext(Device); // Parse the resource list and save the resource information. for (i=0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++) { desc = WdfCmResourceListGetDescriptor(ResourcesTranslated, i); if(!desc) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfResourceCmGetDescriptor failed\n"); return STATUS_DEVICE_CONFIGURATION_ERROR; } switch (desc->Type) { case CmResourceTypeMemory: if (!foundBar0 && desc->u.Memory.Length == 0x400) { // Map in the Registers Memory resource: BAR0 devExt->Bar0Length = desc->u.Memory.Length; devExt->Bar0 = (PULONG)MmMapIoSpace(desc->u.Memory.Start, desc->u.Memory.Length, MmNonCached); if (!devExt->Bar0) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: unable to map BAR memory %08I64X, length %d", desc->u.Memory.Start.QuadPart, desc->u.Memory.Length); return STATUS_INSUFFICIENT_RESOURCES; } foundBar0 = TRUE; } break; default: break; } } // Make sure we found BAR0 if (!foundBar0) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: missing BAR0\n"); return STATUS_DEVICE_CONFIGURATION_ERROR; } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: BAR0 address: %p\n", devExt->Bar0); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: BAR0 length: %u\n", devExt->Bar0Length); // Read the device ids status = RiffaReadHardwareIds(devExt); if(!NT_SUCCESS(status)) return status; // Read the configuration register (also resets the device) info = READ_REGISTER_ULONG(devExt->Bar0 + RIFFA_INFO_REG); devExt->NumChnls = (info & 0xF); devExt->MaxNumScatterGatherElems = RIFFA_MIN_NUM_SG_ELEMS*((info>>19) & 0xF); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: found FPGA with name: %s\n", devExt->Name); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: vendor id: 0x%04X\n", devExt->VendorId); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: device id: 0x%04X\n", devExt->DeviceId); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: number of channels: %d\n", (info & 0xF)); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: bus interface width: %d\n", ((info>>19) & 0xF)<<5); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: bus master enabled: %d\n", ((info>>4) & 0x1)); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: negotiated link width: %d\n", ((info>>5) & 0x3F)); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: negotiated link rate: %d MTs\n", ((info>>11) & 0x3)*2500); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: max downstream payload: %d bytes\n", 128<<((info>>13) & 0x7)); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: max upstream payload: %d bytes\n", 128<<((info>>16) & 0x7)); // Check for bus master enabled if (((info>>4) & 0x1) != 1) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: bus master not enabled!\n"); return STATUS_DEVICE_CONFIGURATION_ERROR; } // Check for valid link parameters if (((info>>5) & 0x3F) == 0 || ((info>>11) & 0x3) == 0) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: bad link parameters!\n"); return STATUS_DEVICE_CONFIGURATION_ERROR; } // Check for valid number of channels if ((info & 0xF) == 0 || (info & 0xF) > RIFFA_MAX_NUM_CHNLS) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: bad number of channels!\n"); return STATUS_DEVICE_CONFIGURATION_ERROR; } // Check for valid bus width if (((info>>19) & 0xF) == 0 || ((info>>19) & 0xF) > RIFFA_MAX_BUS_WIDTH_PARAM) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: bad bus width!\n"); return STATUS_DEVICE_CONFIGURATION_ERROR; } // Allocate common buffers, DMA transactions, spin locks, timers for each channel. for (i = 0; i < devExt->NumChnls; i++) { // Common buffer creation, not cached. status = WdfCommonBufferCreate(devExt->DmaEnabler, RIFFA_MIN_SG_BUF_SIZE*((info>>19) & 0xF), WDF_NO_OBJECT_ATTRIBUTES, &devExt->Chnl[i].CommonBuffer); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfCommonBufferCreate failed\n"); return status; } devExt->Chnl[i].CommonBufferBase = WdfCommonBufferGetAlignedVirtualAddress(devExt->Chnl[i].CommonBuffer); devExt->Chnl[i].CommonBufferBaseLA = WdfCommonBufferGetAlignedLogicalAddress(devExt->Chnl[i].CommonBuffer); status = WdfCommonBufferCreate(devExt->DmaEnabler, RIFFA_MIN_SG_BUF_SIZE*((info>>19) & 0x1F), WDF_NO_OBJECT_ATTRIBUTES, &devExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].CommonBuffer); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfCommonBufferCreate failed\n"); return status; } devExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].CommonBufferBase = WdfCommonBufferGetAlignedVirtualAddress(devExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].CommonBuffer); devExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].CommonBufferBaseLA = WdfCommonBufferGetAlignedLogicalAddress(devExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].CommonBuffer); // Since we are using sequential queue and processing one request at // a time, we will create transaction objects upfront and reuse them // to do DMA transfer. Transactions objects are parented to the DMA // enabler object by default. They will be deleted along with the DMA // enabler object. No need to delete them explicitly. WDF_OBJECT_ATTRIBUTES_INIT(&attributes); status = WdfDmaTransactionCreate(devExt->DmaEnabler, &attributes, &devExt->Chnl[i].DmaTransaction); if(!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfDmaTransactionCreate failed\n"); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); status = WdfDmaTransactionCreate(devExt->DmaEnabler, &attributes, &devExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].DmaTransaction); if(!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfDmaTransactionCreate failed\n"); return status; } // Create spinlocks for each direction. Make the parent the IOCTL queue // so that the spinlocks will be automatically deleted when the queue is. WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = devExt->IoctlQueue; status = WdfSpinLockCreate(&attributes, &devExt->Chnl[i].SpinLock); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfSpinLockCreate failed\n"); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = devExt->IoctlQueue; status = WdfSpinLockCreate(&attributes, &devExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].SpinLock); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfSpinLockCreate failed\n"); return status; } // Create a timer for each direction. Set the parent as the IOCTL queue // so that we can get the device extension and have the timer deleted // when the queue is. Also set the timer's context to have the chnl num. WDF_TIMER_CONFIG_INIT(&timerConfig, RiffaEvtTimerFunc); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, TIMER_EXTENSION); attributes.ParentObject = devExt->IoctlQueue; status = WdfTimerCreate(&timerConfig, &attributes, &devExt->Chnl[i].Timer); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfTimerCreate failed\n"); return status; } timerExt = RiffaGetTimerContext(devExt->Chnl[i].Timer); timerExt->Chnl = i; WDF_TIMER_CONFIG_INIT(&timerConfig, RiffaEvtTimerFunc); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, TIMER_EXTENSION); attributes.ParentObject = devExt->IoctlQueue; status = WdfTimerCreate(&timerConfig, &attributes, &devExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].Timer); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfTimerCreate failed\n"); return status; } timerExt = RiffaGetTimerContext(devExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].Timer); timerExt->Chnl = RIFFA_MAX_NUM_CHNLS + i; } // Create spill buffer, not cached. status = WdfCommonBufferCreate(devExt->DmaEnabler, RIFFA_SPILL_BUF_SIZE, WDF_NO_OBJECT_ATTRIBUTES, &devExt->SpillBuffer); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: WdfCommonBufferCreate failed\n"); return status; } devExt->SpillBufferBase = WdfCommonBufferGetAlignedVirtualAddress(devExt->SpillBuffer); devExt->SpillBufferBaseLA = WdfCommonBufferGetAlignedLogicalAddress(devExt->SpillBuffer); return STATUS_SUCCESS; } /** * Unmap the resources that were mapped in RiffaEvtDevicePrepareHardware. * This will only be called when the device stopped for resource rebalance, * surprise-removed or query-removed. * . * Device - A handle to the WDFDEVICE * * ResourcesTranslated - The translated PnP resources associated with the device. * * Returns STATUS_SUCCESS if successful, another status otherwise. Failure will * result in the device stack being torn down. */ NTSTATUS RiffaEvtDeviceReleaseHardware(IN WDFDEVICE Device, IN WDFCMRESLIST ResourcesTranslated) { PDEVICE_EXTENSION devExt; NTSTATUS status = STATUS_SUCCESS; UNREFERENCED_PARAMETER(ResourcesTranslated); PAGED_CODE(); // Get the device extension devExt = RiffaGetDeviceContext(Device); // Unmap the I/O address space BAR0 if (devExt->Bar0) { MmUnmapIoSpace(devExt->Bar0, devExt->Bar0Length); devExt->Bar0 = NULL; } return status; } /** * Attempts to read the hardware ids (vendor id, device id, bus num, * device num, function num) and set it in the PDEVICE_EXTENSION object. * . * DevExt - Pointer to the Device Extension * * Returns STATUS_SUCCESS if successful, another status otherwise. */ NTSTATUS RiffaReadHardwareIds(IN PDEVICE_EXTENSION DevExt) { NTSTATUS status; PDEVICE_OBJECT pdo; UINT32 length; UINT32 pciBus; UINT32 pciAddr; USHORT pciDev; USHORT pciFxn; WCHAR hwIds[2048]; wchar_t * id; // Initialize the values DevExt->DeviceId = 0; DevExt->VendorId = 0; DevExt->Name[0] = 0; // Get the PDO from our FDO. pdo = WdfDeviceWdmGetPhysicalDevice(DevExt->Device); // Read DevicePropertyBusNumber. status = IoGetDeviceProperty(pdo, DevicePropertyBusNumber, sizeof(UINT32), (PVOID)&pciBus, &length); if(!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: IoGetDeviceProperty failed\n"); return status; } // Read DevicePropertyAddress (contains device and function). status = IoGetDeviceProperty(pdo, DevicePropertyAddress, sizeof(UINT32), (PVOID)&pciAddr, &length); if(!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: IoGetDeviceProperty failed\n"); return status; } // Parse the function and device values and create a name. pciFxn = (USHORT)((pciAddr) & 0x0000FFFF); pciDev = (USHORT)(((pciAddr)>>16) & 0x0000FFFF); sprintf_s(DevExt->Name, 16, "%02x:%02x:%01x", pciBus, pciDev, pciFxn); // Read Device HardwareID. Should be something like: // PCI\VEN_10B5&DEV_515A&SUBSYS_905610B5&REV_02 status = IoGetDeviceProperty(pdo, DevicePropertyHardwareID, 2048, (PVOID)hwIds, &length); if(!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: IoGetDeviceProperty failed\n"); return status; } // Null terminate the string. hwIds[length] = 0; // Add null-char // Search for the device id. id = wcsstr(hwIds, L"DEV_"); if (id == NULL) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: bad DevicePropertyHardwareID, no device id in: %S\n", hwIds); return STATUS_DEVICE_CONFIGURATION_ERROR; } // Null terminate after the 4 char id and convert into an int. hwIds[((int)(id - hwIds)) + 8] = 0; // Add null-char swscanf_s(id + 4, L"%x", &DevExt->DeviceId); // Search for the vendor id. id = wcsstr(hwIds, L"VEN_"); if (id == NULL) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: bad DevicePropertyHardwareID, no vendor id in: %S\n", hwIds); return STATUS_DEVICE_CONFIGURATION_ERROR; } hwIds[((int)(id - hwIds)) + 8] = 0; // Add null-char swscanf_s(id + 4, L"%x", &DevExt->VendorId); return STATUS_SUCCESS; } /****************************************************************************** * INTERRUPT FUNCTIONS *****************************************************************************/ /** * Interrupt handler for this driver. Called at DIRQL level when the * device or another device sharing the same interrupt line asserts * the interrupt. The driver first checks the device to make sure whether * this interrupt is generated by its device and if so clear the interrupt * register to disable further generation of interrupts and queue a * DPC to do other I/O work related to interrupt - such as reading * the device memory, starting a DMA transaction, coping it to * the request buffer and completing the request, etc. * . * Interupt - Handle to WDFINTERRUPT Object for this device. * * MessageID - MSI message ID (always 0 in this configuration) * * Returns TRUE if this device generated the interrupt, FALSE otherwise. */ BOOLEAN RiffaEvtInterruptIsr(IN WDFINTERRUPT Interrupt, IN ULONG MessageID) { PDEVICE_EXTENSION devExt; UINT32 vect0 = 0; UINT32 vect1 = 0; BOOLEAN recog = FALSE; UNREFERENCED_PARAMETER(MessageID); devExt = RiffaGetDeviceContext(WdfInterruptGetDevice(Interrupt)); // Read the interrupt register vect0 = READ_REGISTER_ULONG(devExt->Bar0 + RIFFA_IRQ_0_REG); if (devExt->NumChnls > 6) vect1 = READ_REGISTER_ULONG(devExt->Bar0 + RIFFA_IRQ_1_REG); // Process the interrupt vector(s) recog = RiffaProcessInterrupt(devExt, 0, vect0); if (devExt->NumChnls > 6) recog = (recog | RiffaProcessInterrupt(devExt, 6, vect1)); // Queue a callback for the DPC if needed. if (recog) WdfInterruptQueueDpcForIsr(Interrupt); return recog; } /** * Processes the interrupt vector read from the device during the interrupt * service routine. The vectors are organized from right to left (LSB to MSB) as: * [ 0] TX_TXN for channel 0 in VECT_0, channel 6 in VECT_1 * [ 1] TX_SG_BUF_RECVD for channel 0 in VECT_0, channel 6 in VECT_1 * [ 2] TX_TXN_DONE for channel 0 in VECT_0, channel 6 in VECT_1 * [ 3] RX_SG_BUF_RECVD for channel 0 in VECT_0, channel 6 in VECT_1 * [ 4] RX_TXN_DONE for channel 0 in VECT_0, channel 6 in VECT_1 * ... * [25] TX_TXN for channel 5 in VECT_0, channel 11 in VECT_1 * [26] TX_SG_BUF_RECVD for channel 5 in VECT_0, channel 11 in VECT_1 * [27] TX_TXN_DONE for channel 5 in VECT_0, channel 11 in VECT_1 * [28] RX_SG_BUF_RECVD for channel 5 in VECT_0, channel 11 in VECT_1 * [29] RX_TXN_DONE for channel 5 in VECT_0, channel 11 in VECT_1 * Positions 30 - 31 in both VECT_0 and VECT_1 are zero. * . * DevExt - Pointer to the Device Extension * * Offset - Channel offset * * Vect - Interrupt vector * * Returns TRUE if a DPC should be queued to do more work, FALSE otherwise. */ BOOLEAN RiffaProcessInterrupt(IN PDEVICE_EXTENSION DevExt, IN UINT32 Offset, IN UINT32 Vect) { BOOLEAN queueDpc = FALSE; UINT32 offlast; UINT32 len; int i; int chnl; if (Vect & 0xC0000000) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, received invalid interrupt:0x%08x\n", DevExt->Name, Vect); return FALSE; } for (i = 0; i < 6 && (i+Offset) < DevExt->NumChnls; i++) { chnl = i + Offset; // New TX (PC receive) transaction. if (Vect & (1<<((5*i)+0))) { queueDpc = TRUE; // Read the offset/last and length offlast = READ_REGISTER_ULONG(DevExt->Bar0 + CHNL_REG(chnl, RIFFA_TX_OFFLAST_REG)); len = READ_REGISTER_ULONG(DevExt->Bar0 + CHNL_REG(chnl, RIFFA_TX_LEN_REG)); DevExt->IntrData[RIFFA_MAX_NUM_CHNLS + chnl].OffLast = offlast; DevExt->IntrData[RIFFA_MAX_NUM_CHNLS + chnl].Length = len; DevExt->IntrData[RIFFA_MAX_NUM_CHNLS + chnl].NewTxn = TRUE; } // TX (PC receive) scatter gather buffer is read. if (Vect & (1<<((5*i)+1))) { queueDpc = TRUE; DevExt->IntrData[RIFFA_MAX_NUM_CHNLS + chnl].SgRead = TRUE; } // TX (PC receive) transaction done. if (Vect & (1<<((5*i)+2))) { queueDpc = TRUE; DevExt->IntrData[RIFFA_MAX_NUM_CHNLS + chnl].Done = TRUE; } // RX (PC send) scatter gather buffer is read. if (Vect & (1<<((5*i)+3))) { queueDpc = TRUE; DevExt->IntrData[chnl].SgRead = TRUE; } // RX (PC send) transaction done. if (Vect & (1<<((5*i)+4))) { queueDpc = TRUE; DevExt->IntrData[chnl].Done = TRUE; } } return queueDpc; } /** * DPC callback for ISR. Please note that on a multiprocessor system, * you could have more than one DPCs running simulataneously on * multiple processors. So if you are accesing any global resources * make sure to synchrnonize the accesses with a spinlock. * . * Interupt - Handle to WDFINTERRUPT Object for this device. * * Device - WDFDEVICE object passed to InterruptCreate */ VOID RiffaEvtInterruptDpc(IN WDFINTERRUPT Interrupt, IN WDFDEVICE Device) { NTSTATUS status; BOOLEAN txnComplete; BOOLEAN cont; PDEVICE_EXTENSION devExt; INTR_CHNL_DIR_DATA intrData[2 * RIFFA_MAX_NUM_CHNLS]; UINT32 chnl; UINT32 tnfr; UINT64 length; LONG doneReqd; UNREFERENCED_PARAMETER(Device); devExt = RiffaGetDeviceContext(WdfInterruptGetDevice(Interrupt)); // Acquire this device's InterruptSpinLock. WdfInterruptAcquireLock(Interrupt); // Copy over the values and zero them out. memcpy(&intrData, devExt->IntrData, 2 * RIFFA_MAX_NUM_CHNLS * sizeof(INTR_CHNL_DIR_DATA)); memset(devExt->IntrData, 0, 2 * RIFFA_MAX_NUM_CHNLS * sizeof(INTR_CHNL_DIR_DATA)); // Release our interrupt spinlock WdfInterruptReleaseLock(Interrupt); // Update state for each channel for (chnl = 0; chnl < devExt->NumChnls; chnl++) { // Send more scatter gather elements. if (intrData[RIFFA_MAX_NUM_CHNLS + chnl].SgRead == TRUE) { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, recv sg buf read\n", devExt->Name, chnl)); RiffaProgramScatterGather(devExt, RIFFA_MAX_NUM_CHNLS + chnl); } // Finished with upstream transfer. if (intrData[RIFFA_MAX_NUM_CHNLS + chnl].Done == TRUE) { // Acquire the channel lock, check if request is null, release. WdfSpinLockAcquire(devExt->Chnl[RIFFA_MAX_NUM_CHNLS + chnl].SpinLock); cont = (devExt->Chnl[RIFFA_MAX_NUM_CHNLS + chnl].Request != NULL); WdfSpinLockRelease(devExt->Chnl[RIFFA_MAX_NUM_CHNLS + chnl].SpinLock); if (cont) { // Check if we've requested a done (in the event of a split transaction) doneReqd = InterlockedExchange(&devExt->Chnl[RIFFA_MAX_NUM_CHNLS + chnl].ReqdDone, 0); // Indicate this DMA operation has completed. This might result in // another transfer if there is still data to be transfered in the request. txnComplete = WdfDmaTransactionDmaCompleted( devExt->Chnl[RIFFA_MAX_NUM_CHNLS + chnl].DmaTransaction, &status); if (txnComplete) { // Read the actual transfer length tnfr = READ_REGISTER_ULONG(devExt->Bar0 + CHNL_REG(chnl, RIFFA_TX_TNFR_LEN_REG)); KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, recv txn done\n", devExt->Name, chnl)); RiffaTransactionComplete(devExt, RIFFA_MAX_NUM_CHNLS + chnl, tnfr, status); } else { if (doneReqd == 0) { // Not complete and not expecting a done signal. Must be an error. // End the transaction early. Read the actual transfer length tnfr = READ_REGISTER_ULONG(devExt->Bar0 + CHNL_REG(chnl, RIFFA_TX_TNFR_LEN_REG)); KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, recv txn done\n", devExt->Name, chnl)); RiffaTransactionComplete(devExt, RIFFA_MAX_NUM_CHNLS + chnl, tnfr, STATUS_TRANSACTION_ABORTED); } else { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, recv txn split, registers remapped\n", devExt->Name, chnl)); } } } } // New upstream transfer. if (intrData[RIFFA_MAX_NUM_CHNLS + chnl].NewTxn == TRUE) { // If the user has already called the receive function, start the // transaction. If not, set the transaction data and the "ready" // bit so that when the user calls the receive function, the // transaction can start. devExt->Chnl[RIFFA_MAX_NUM_CHNLS + chnl].Length = (((UINT64)intrData[RIFFA_MAX_NUM_CHNLS + chnl].Length)<<2); devExt->Chnl[RIFFA_MAX_NUM_CHNLS + chnl].Offset = (((UINT64)(intrData[RIFFA_MAX_NUM_CHNLS + chnl].OffLast>>1))<<2); devExt->Chnl[RIFFA_MAX_NUM_CHNLS + chnl].Last = (intrData[RIFFA_MAX_NUM_CHNLS + chnl].OffLast & 0x1); KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, new recv txn (len:%u off:%u last:%d)\n", devExt->Name, chnl, intrData[RIFFA_MAX_NUM_CHNLS + chnl].Length, intrData[RIFFA_MAX_NUM_CHNLS + chnl].OffLast>>1, intrData[RIFFA_MAX_NUM_CHNLS + chnl].OffLast & 0x1)); if (InterlockedExchange(&devExt->Chnl[RIFFA_MAX_NUM_CHNLS + chnl].Ready, 2) == 1) { // Clear the "ready" bit and start the transaction InterlockedExchange(&devExt->Chnl[RIFFA_MAX_NUM_CHNLS + chnl].Ready, 0); RiffaStartRecvTransaction(devExt, RIFFA_MAX_NUM_CHNLS + chnl); } } // Send more scatter gather elements. if (intrData[chnl].SgRead == TRUE) { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, send sg buf read\n", devExt->Name, chnl)); RiffaProgramScatterGather(devExt, chnl); } // Finished with downstream transfer. if (intrData[chnl].Done == TRUE) { // Acquire the channel lock, check if request is null, release. WdfSpinLockAcquire(devExt->Chnl[chnl].SpinLock); cont = (devExt->Chnl[chnl].Request != NULL); WdfSpinLockRelease(devExt->Chnl[chnl].SpinLock); if (cont) { // Check if we've requested a done (in the event of a split transaction) doneReqd = InterlockedExchange(&devExt->Chnl[chnl].ReqdDone, 0); // Indicate this DMA operation has completed. This may result in // another transfer if there is still data to be transfered in the request. txnComplete = WdfDmaTransactionDmaCompleted( devExt->Chnl[chnl].DmaTransaction, &status); if (txnComplete) { // Read the actual transfer length tnfr = READ_REGISTER_ULONG(devExt->Bar0 + CHNL_REG(chnl, RIFFA_RX_TNFR_LEN_REG)); KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, send txn done\n", devExt->Name, chnl)); RiffaTransactionComplete(devExt, chnl, tnfr, status); } else { if (doneReqd == 0) { // Not complete and not expecting a done signal. Must be an error. // End the transaction early. Read the actual transfer length tnfr = READ_REGISTER_ULONG(devExt->Bar0 + CHNL_REG(chnl, RIFFA_RX_TNFR_LEN_REG)); KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, send txn done\n", devExt->Name, chnl)); RiffaTransactionComplete(devExt, chnl, tnfr, STATUS_TRANSACTION_ABORTED); } else { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, send txn split, registers remapped\n", devExt->Name, chnl)); } } } } } } /****************************************************************************** * IOCTL FUNCTIONS *****************************************************************************/ /** * This event is called when the framework receives IRP_MJ_DEVICE_CONTROL * requests from the system. * . * Queue - Handle to the framework queue object that is associated with the * I/O request. * * Request - Handle to a framework request object. * * OutputBufferLength - Length of the request's output buffer, * if an output buffer is available. * * InputBufferLength - Length of the request's input buffer, * if an input buffer is available. * * IoControlCode - the driver-defined or system-defined I/O control code * (IOCTL) that is associated with the request. */ VOID RiffaEvtIoDeviceControl(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode) { PDEVICE_EXTENSION devExt; devExt = RiffaGetDeviceContext(WdfIoQueueGetDevice(Queue)); // Determine which I/O control code was specified. switch (IoControlCode) { case IOCTL_RIFFA_SEND: // (METHOD_OUT_DIRECT) RiffaIoctlSend(devExt, Request, OutputBufferLength, InputBufferLength); break; case IOCTL_RIFFA_RECV: // (METHOD_OUT_DIRECT) RiffaIoctlRecv(devExt, Request, OutputBufferLength, InputBufferLength); break; case IOCTL_RIFFA_LIST: // (METHOD_OUT_DIRECT) RiffaIoctlList(devExt, Request, OutputBufferLength, InputBufferLength); break; case IOCTL_RIFFA_RESET: // (METHOD_OUT_DIRECT) RiffaIoctlReset(devExt, Request); break; default: // The specified I/O control code is unrecognized by this driver. DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, invalid ioctl request type\n", devExt->Name); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_DEVICE_REQUEST, 0); break; } } /** * Handles IRP_MJ_DEVICE_CONTROL requests for IOCTL_RIFFA_SEND. * . * DevExt - Handle to the device extension object. * * Request - Handle to a framework request object. * * OutputBufferLength - Length of the request's output buffer, * if an output buffer is available. * * InputBufferLength - Length of the request's input buffer, * if an input buffer is available. */ VOID RiffaIoctlSend(IN PDEVICE_EXTENSION DevExt, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength) { NTSTATUS status = STATUS_SUCCESS; PREQUEST_EXTENSION reqExt; PRIFFA_FPGA_CHNL_IO io; UINT64 length; PCHAR buf = NULL; size_t bufSize; // Input should be non-zero if(!InputBufferLength) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl send zero length input buffer\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } // Get the input buffer status = WdfRequestRetrieveInputBuffer(Request, 0, &buf, &bufSize); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl send WdfRequestRetrieveInputBuffer failed\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, status, 0); return; } if (bufSize < sizeof(RIFFA_FPGA_CHNL_IO)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl send input buffer too small to contain RIFFA_FPGA_CHNL_IO\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } io = (PRIFFA_FPGA_CHNL_IO)buf; // Validate the length, last, chnl length = (io->Length < (OutputBufferLength>>2) ? io->Length : (OutputBufferLength>>2)); if (io->Last > 1) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl send invalid last: %d\n", DevExt->Name, io->Last); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } if (io->Chnl >= DevExt->NumChnls) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl send invalid channel: %d, device only has %d channel(s)\n", DevExt->Name, io->Chnl, DevExt->NumChnls); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } // Check that this isn't an already running transaction if (InterlockedExchange(&DevExt->Chnl[io->Chnl].InUse, 1) == 1) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl send already in use on channel: %d\n", DevExt->Name, io->Chnl); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } // Set the channel number in the request context for RiffaEvtRequestCancel. reqExt = RiffaGetRequestContext(Request); reqExt->Chnl = io->Chnl; // Start a send transaction. if (length) { // Start a DMA transaction for sending. DevExt->Chnl[io->Chnl].Timeout = io->Timeout; DevExt->Chnl[io->Chnl].Length = (length<<2); DevExt->Chnl[io->Chnl].SpillAfter = (length<<2); DevExt->Chnl[io->Chnl].Offset = (io->Offset<<2); DevExt->Chnl[io->Chnl].Last = io->Last; DevExt->Chnl[io->Chnl].Provided = 0; DevExt->Chnl[io->Chnl].ProvidedPrev = 0; DevExt->Chnl[io->Chnl].Confirmed = 0; DevExt->Chnl[io->Chnl].ConfirmedPrev = 0; DevExt->Chnl[io->Chnl].ActiveCount = 0; DevExt->Chnl[io->Chnl].Cancel = 0; DevExt->Chnl[io->Chnl].Request = Request; InterlockedExchange(&DevExt->Chnl[io->Chnl].ReqdDone, 0); status = RiffaStartDmaTransaction(DevExt, io->Chnl, (length<<2), 0, WdfDmaDirectionWriteToDevice); if (!NT_SUCCESS(status)) { WdfRequestCompleteWithInformation(Request, status, 0); } else { // Mark the WDFREQUEST as cancellable. status = WdfRequestMarkCancelableEx(Request, RiffaEvtRequestCancel); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl send WdfRequestMarkCancelableEx failed\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, status, 0); } } } else if (io->Last) { // Program the device for zero length send (device RX) and complete RiffaProgramSend(DevExt, io->Chnl, (UINT32)length, io->Offset, io->Last); WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 0); } else { // Invalid request, results in no send DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl send invalid, no length or last\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); } } /** * Handles IRP_MJ_DEVICE_CONTROL requests for IOCTL_RIFFA_RECV. * . * DevExt - Handle to the device extension object. * * Request - Handle to a framework request object. * * OutputBufferLength - Length of the request's output buffer, * if an output buffer is available. * * InputBufferLength - Length of the request's input buffer, * if an input buffer is available. */ VOID RiffaIoctlRecv(IN PDEVICE_EXTENSION DevExt, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength) { NTSTATUS status = STATUS_SUCCESS; PREQUEST_EXTENSION reqExt; PRIFFA_FPGA_CHNL_IO io; UINT64 length; PCHAR buf = NULL; size_t bufSize; // Input should be non-zero if(!InputBufferLength) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl recv zero length input buffer\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } // Get the input buffer status = WdfRequestRetrieveInputBuffer(Request, 0, &buf, &bufSize); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl recv WdfRequestRetrieveInputBuffer failed\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, status, 0); return; } if (bufSize < sizeof(RIFFA_FPGA_CHNL_IO)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl recv input buffer too small to contain RIFFA_FPGA_CHNL_IO\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } io = (PRIFFA_FPGA_CHNL_IO)buf; // Validate the length, chnl length = (io->Length < (OutputBufferLength>>2) ? io->Length : (OutputBufferLength>>2)); if (io->Chnl >= DevExt->NumChnls) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl recv invalid channel: %d, device only has %d channel(s)\n", DevExt->Name, io->Chnl, DevExt->NumChnls); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } // Check that this isn't an already running transaction if (InterlockedExchange(&DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].InUse, 1) == 1) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl recv already in use on channel: %d\n", DevExt->Name, io->Chnl); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } // Set the channel number in the request context for RiffaEvtRequestCancel. reqExt = RiffaGetRequestContext(Request); reqExt->Chnl = RIFFA_MAX_NUM_CHNLS + io->Chnl; // Start a receive transaction. If an interrupt with the transaction // info has already been received, start the transaction. If not, set // this transaction request and the "ready" bit so that when the // interrupt is received the transaction can start. DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Timeout = io->Timeout; DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Capacity = (length<<2); DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Provided = 0; DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].ProvidedPrev = 0; DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Confirmed = 0; DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].ConfirmedPrev = 0; DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].ActiveCount = 0; DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Cancel = 0; DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Request = Request; InterlockedExchange(&DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].ReqdDone, 0); if (InterlockedExchange(&DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Ready, 1) == 2) { // Clear the "ready" bit and start the transaction InterlockedExchange(&DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Ready, 0); // Start a recv transaction. if (DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Length) { // Calculate room in the user space buffer and what needs to be spilled if (DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Capacity > DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Offset) { // Some (possibly all) of the data can fit in the user buffer. DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].SpillAfter = DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Capacity - DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Offset; length = (DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Capacity < DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Length ? DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Capacity : DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Length); status = RiffaStartDmaTransaction(DevExt, RIFFA_MAX_NUM_CHNLS + io->Chnl, length + DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Offset, DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Offset, WdfDmaDirectionReadFromDevice); if (!NT_SUCCESS(status)) { WdfRequestCompleteWithInformation(Request, status, 0); } } else { // No room in user buffer, spill everything DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].SpillAfter = 0; RiffaProgramScatterGather(DevExt, RIFFA_MAX_NUM_CHNLS + io->Chnl); } } else if (DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Last) { // Recognize zero length receive and complete WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 0); } else { // Invalid request, should never happen DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl recv invalid, no length or last\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0); } } else { // Start the timer (if necessary) if (DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Timeout > 0) WdfTimerStart(DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Timer, WDF_REL_TIMEOUT_IN_MS(DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + io->Chnl].Timeout)); } // Mark the WDFREQUEST as cancellable. status = WdfRequestMarkCancelableEx(Request, RiffaEvtRequestCancel); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl send WdfRequestMarkCancelableEx failed\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, status, 0); } } /** * Handles IRP_MJ_DEVICE_CONTROL requests for IOCTL_RIFFA_LIST. * . * DevExt - Handle to the device extension object. * * Request - Handle to a framework request object. * * OutputBufferLength - Length of the request's output buffer, * if an output buffer is available. * * InputBufferLength - Length of the request's input buffer, * if an input buffer is available. */ VOID RiffaIoctlList(IN PDEVICE_EXTENSION DevExt, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength) { NTSTATUS status = STATUS_SUCCESS; PRIFFA_FPGA_INFO info; PCHAR buf = NULL; size_t bufSize; UINT32 i; // Input should be non-zero if(!InputBufferLength) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl list zero length input buffer\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } // Get the input buffer status = WdfRequestRetrieveInputBuffer(Request, 0, &buf, &bufSize); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl list WdfRequestRetrieveInputBuffer failed\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, status, 0); return; } if (bufSize < sizeof(UINT32)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl list input buffer too small to contain fpga id\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } i = *((UINT32 *)buf); // Validate the index value if (i >= RIFFA_MAX_NUM_FPGAS) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl list fpga id invalid\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } // Output should be non-zero if(!OutputBufferLength) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl list zero length output buffer\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } // Get the output buffer status = WdfRequestRetrieveOutputBuffer(Request, 0, &buf, &bufSize); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl list WdfRequestRetrieveOutputBuffer failed\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, status, 0); return; } if (bufSize < sizeof(RIFFA_FPGA_INFO)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s, ioctl list input buffer too small to contain RIFFA_FPGA_INFO\n", DevExt->Name); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } info = (PRIFFA_FPGA_INFO)buf; // Fill in the information. info->id[i] = i; info->num_chnls[i] = DevExt->NumChnls; strcpy_s(info->name[i], 16, DevExt->Name); info->vendor_id[i] = DevExt->VendorId; info->device_id[i] = DevExt->DeviceId; WdfRequestCompleteWithInformation(Request, status, 0); } /** * Handles IRP_MJ_DEVICE_CONTROL requests for IOCTL_RIFFA_RESET. * . * DevExt - Handle to the device extension object. * * Request - Handle to a framework request object. * * OutputBufferLength - Length of the request's output buffer, * if an output buffer is available. * * InputBufferLength - Length of the request's input buffer, * if an input buffer is available. */ VOID RiffaIoctlReset(IN PDEVICE_EXTENSION DevExt, IN WDFREQUEST Request) { UINT32 i; // Reset the device by reading the info/status register READ_REGISTER_ULONG(DevExt->Bar0 + RIFFA_INFO_REG); // Reset all the channels for (i = 0; i < DevExt->NumChnls; i++) { InterlockedExchange(&DevExt->Chnl[i].Ready, 0); InterlockedExchange(&DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].Ready, 0); InterlockedExchange(&DevExt->Chnl[i].InUse, 0); InterlockedExchange(&DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].InUse, 0); InterlockedExchange(&DevExt->Chnl[i].ReqdDone, 0); InterlockedExchange(&DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].ReqdDone, 0); DevExt->Chnl[i].ActiveCount = 0; DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].ActiveCount = 0; DevExt->Chnl[i].Cancel = 0; DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].Cancel = 0; WdfDmaTransactionRelease(DevExt->Chnl[i].DmaTransaction); WdfDmaTransactionRelease(DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].DmaTransaction); RiffaCompleteRequest(DevExt, i, STATUS_CANCELLED); RiffaCompleteRequest(DevExt, RIFFA_MAX_NUM_CHNLS + i, STATUS_CANCELLED); WdfTimerStop(DevExt->Chnl[i].Timer, FALSE); WdfTimerStop(DevExt->Chnl[RIFFA_MAX_NUM_CHNLS + i].Timer, FALSE); } // Reset the interrupt data memset(DevExt->IntrData, 0, 2 * RIFFA_MAX_NUM_CHNLS * sizeof(INTR_CHNL_DIR_DATA)); // Finish this request WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 0); } /****************************************************************************** * DMA ENTRY, EXIT, TIMER FUNCTIONS *****************************************************************************/ /** * Called at the entry point of functions after the DMA has started. If the * WDFREQUEST is still valid, increments the active count and returns TRUE. IF * the WDFREQUEST is not valid (i.e. is NULL'd out), then the request has been * cancelled (by timeout timer or by user process termination), and FALSE is * returned (active count is not incremented). * * DevExt - Pointer to the Device Extension * * Chnl - Channel number on which the DMA is taking place */ BOOLEAN RiffaThreadEnter(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl) { BOOLEAN cont; // Acquire the channel lock, check if request is null, increment, release. WdfSpinLockAcquire(DevExt->Chnl[Chnl].SpinLock); cont = (DevExt->Chnl[Chnl].Request != NULL); if (cont) DevExt->Chnl[Chnl].ActiveCount++; WdfSpinLockRelease(DevExt->Chnl[Chnl].SpinLock); return cont; } /** * Called at the exit of functions where RiffaThreadEnter was called, after the * DMA has started. Decrements the active count. If this is the last thread, it * checks to see if a cancel request was set. If so, cancels the request (if * not already completed). * * DevExt - Pointer to the Device Extension * * Chnl - Channel number on which the DMA is taking place * * IsSend - TRUE if the thread is operating on a send DMA, FALSE otherwise */ VOID RiffaThreadExit(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl) { // Acquire the channel lock, decrement, check for last exiting thread and a // cancel request, cancel if necessary, release. WdfSpinLockAcquire(DevExt->Chnl[Chnl].SpinLock); DevExt->Chnl[Chnl].ActiveCount--; if (DevExt->Chnl[Chnl].ActiveCount == 0 && DevExt->Chnl[Chnl].Cancel == 1) RiffaCompleteRequest(DevExt, Chnl, STATUS_CANCELLED); WdfSpinLockRelease(DevExt->Chnl[Chnl].SpinLock); } /** * Called when the WDFREQUEST object for the specified channel should be * completed with the specified status. The WDFREQUEST has been marked * cancelable so it must first be unmarked cancelable. After completion, the * pointer to the WDFREQUEST is NULL'd out to indicate that the WDFREQUEST is * no longer valid. * * DevExt - Pointer to the Device Extension * * Chnl - Channel number on which the DMA is taking place * * Status - NTSTATUS to set for completion */ VOID RiffaCompleteRequest(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl, IN NTSTATUS Status) { NTSTATUS status; WDFREQUEST request; if ((request = DevExt->Chnl[Chnl].Request) != NULL) { // Try to complete the request status = WdfRequestUnmarkCancelable(request); if (status != STATUS_CANCELLED) { // Complete the request (nobody has done it yet) DevExt->Chnl[Chnl].Request = NULL; WdfRequestCompleteWithInformation(request, Status, (ULONG_PTR)(DevExt->Chnl[Chnl].ConfirmedPrev + DevExt->Chnl[Chnl].Confirmed)>>2); } } } /** * EvtRequestCancel handler for WDFREQUEST objects for IOCTL sends/receives. * Called if the IO Manager or calling application needs to cancel the send. * In practice this should only happen when the user application hangs and the * user CTRL+C signals or Task Ends the application. * * Request - WDFREQUEST object from the IOCTL queue, representing the send */ VOID RiffaEvtRequestCancel(IN WDFREQUEST Request) { PDEVICE_EXTENSION devExt; PREQUEST_EXTENSION reqExt; UINT32 chnl; BOOLEAN canCancel; devExt = RiffaGetDeviceContext(WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request))); reqExt = RiffaGetRequestContext(Request); KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, request being cancelled\n", devExt->Name, (reqExt->Chnl >= RIFFA_MAX_NUM_CHNLS ? reqExt->Chnl - RIFFA_MAX_NUM_CHNLS : reqExt->Chnl))); // Acquire the channel lock WdfSpinLockAcquire(devExt->Chnl[reqExt->Chnl].SpinLock); // See if we can cancel right now. canCancel = (devExt->Chnl[reqExt->Chnl].ActiveCount == 0); if (canCancel) { // NULL out the request so that no other threads use it devExt->Chnl[reqExt->Chnl].Request = NULL; } else { // Set the cancel flag so that the last active thread cancels for us. devExt->Chnl[reqExt->Chnl].Cancel = 1; } // Release the channel lock WdfSpinLockRelease(devExt->Chnl[reqExt->Chnl].SpinLock); // Cancel the request if (canCancel) { InterlockedExchange(&devExt->Chnl[reqExt->Chnl].Ready, 0); InterlockedExchange(&devExt->Chnl[reqExt->Chnl].InUse, 0); devExt->Chnl[reqExt->Chnl].ActiveCount = 0; devExt->Chnl[reqExt->Chnl].Cancel = 0; WdfDmaTransactionRelease(devExt->Chnl[reqExt->Chnl].DmaTransaction); WdfTimerStop(devExt->Chnl[reqExt->Chnl].Timer, FALSE); WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, (ULONG_PTR)(devExt->Chnl[reqExt->Chnl].ConfirmedPrev + devExt->Chnl[reqExt->Chnl].Confirmed)>>2); } } /** * Called when the WDFTIMER expires. Used to handle timeouts from IOCTL calls. * * Timer - WDFTIMER that expired */ VOID RiffaEvtTimerFunc(IN WDFTIMER Timer) { PDEVICE_EXTENSION devExt; PTIMER_EXTENSION timerExt; WDFREQUEST request; NTSTATUS status; BOOLEAN canCancel; timerExt = RiffaGetTimerContext(Timer); devExt = RiffaGetDeviceContext(WdfIoQueueGetDevice(WdfTimerGetParentObject(Timer))); // Acquire the channel lock WdfSpinLockAcquire(devExt->Chnl[timerExt->Chnl].SpinLock); // See if we can cancel right now. request = devExt->Chnl[timerExt->Chnl].Request; if (request == NULL) { canCancel = FALSE; } else { canCancel = (devExt->Chnl[timerExt->Chnl].ActiveCount == 0); if (canCancel) { // NULL out the request so that no other threads use it devExt->Chnl[timerExt->Chnl].Request = NULL; } else { // Set the cancel flag so that the last active thread cancels for us. devExt->Chnl[timerExt->Chnl].Cancel = 1; } } // Release the channel lock WdfSpinLockRelease(devExt->Chnl[timerExt->Chnl].SpinLock); // Cancel the request if (canCancel) { if (timerExt->Chnl < RIFFA_MAX_NUM_CHNLS) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s chnl:%d, send timed out\n", devExt->Name, timerExt->Chnl); } else { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s chnl:%d, recv timed out\n", devExt->Name, timerExt->Chnl - RIFFA_MAX_NUM_CHNLS); } status = WdfRequestUnmarkCancelable(request); if (status != STATUS_CANCELLED) { // Complete the request (nobody has done it yet) InterlockedExchange(&devExt->Chnl[timerExt->Chnl].Ready, 0); InterlockedExchange(&devExt->Chnl[timerExt->Chnl].InUse, 0); devExt->Chnl[timerExt->Chnl].ActiveCount = 0; devExt->Chnl[timerExt->Chnl].Cancel = 0; WdfDmaTransactionRelease(devExt->Chnl[timerExt->Chnl].DmaTransaction); WdfTimerStop(devExt->Chnl[timerExt->Chnl].Timer, FALSE); WdfRequestCompleteWithInformation(request, STATUS_CANCELLED, (ULONG_PTR)(devExt->Chnl[timerExt->Chnl].ConfirmedPrev + devExt->Chnl[timerExt->Chnl].Confirmed)>>2); } } } /****************************************************************************** * DMA CALLBACKS *****************************************************************************/ /** * Called after the user has called into the driver to receive data, from the * interrupt DPC when it detects a data receive event. Both conditions must be * met before this function will be called. The function initiates a receive * DMA operation then provides scatter gather information if necessary. * * DevExt - Pointer to the Device Extension * * Chnl - Channel number on which the DMA is taking place */ VOID RiffaStartRecvTransaction(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl) { NTSTATUS status; UINT64 length; // Stop the timer (if set) WdfTimerStop(DevExt->Chnl[Chnl].Timer, FALSE); // Check that the request has not been cancelled. if (!RiffaThreadEnter(DevExt, Chnl)) return; // Start a recv transaction. if (DevExt->Chnl[Chnl].Length) { // Calculate room in the user space buffer and what needs to be spilled if (DevExt->Chnl[Chnl].Capacity > DevExt->Chnl[Chnl].Offset) { // Some (possibly all) of the data can fit in the user buffer. DevExt->Chnl[Chnl].SpillAfter = DevExt->Chnl[Chnl].Capacity - DevExt->Chnl[Chnl].Offset; length = (DevExt->Chnl[Chnl].Capacity < DevExt->Chnl[Chnl].Length ? DevExt->Chnl[Chnl].Capacity : DevExt->Chnl[Chnl].Length); status = RiffaStartDmaTransaction(DevExt, Chnl, length + DevExt->Chnl[Chnl].Offset, DevExt->Chnl[Chnl].Offset, WdfDmaDirectionReadFromDevice); if (!NT_SUCCESS(status)) { RiffaCompleteRequest(DevExt, Chnl, status); } } else { // No room in user buffer, spill everything DevExt->Chnl[Chnl].SpillAfter = 0; RiffaProgramScatterGather(DevExt, Chnl); } } else if (DevExt->Chnl[Chnl].Last) { // Recognize zero length receive and complete RiffaCompleteRequest(DevExt, Chnl, STATUS_SUCCESS); } else { // Invalid request, should never happen RiffaCompleteRequest(DevExt, Chnl, STATUS_CANCELLED); } // Check for a cancel request and service it. RiffaThreadExit(DevExt, Chnl); } /** * Starts a DMA transaction using the user pages specified in the IOCTL output * buffer as the source/receptical. This will result in RiffaEvtProgramDma * being called with the scatter gather list. If the amount of data to map is * too large, Windows will break up the transaction into multiple transfers. * Only a portion of the output buffer will be mapped each transfer (each call * to RiffaEvtProgramDma). Returns the status after starting the DMA transaction. * * Request - Pointer to the WDFREQUEST that was passed to IOCTl * * DevExt - Pointer to the Device Extension * * Chnl - Channel number on which the DMA transaction should take place * * Length - Length (in bytes) of the DMA * * Offset - Offset (in bytes) from the start of the IOCTL output buffer where * data should be read/written * * DmaDirection - Direction of the DMA * * Returns status after starting the DMA transaction. */ NTSTATUS RiffaStartDmaTransaction(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl, IN UINT64 Length, IN UINT64 Offset, IN WDF_DMA_DIRECTION DmaDirection) { NTSTATUS status = STATUS_SUCCESS; PMDL mdl; PVOID vaddr; UINT64 length; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s chnl:%d, starting txn (len:%lld, off:%lld, isSend?:%d)\n", DevExt->Name, (Chnl < RIFFA_MAX_NUM_CHNLS ? Chnl : Chnl - RIFFA_MAX_NUM_CHNLS), Length>>2, Offset, DmaDirection == WdfDmaDirectionWriteToDevice); // Get the user space memory. status = WdfRequestRetrieveOutputWdmMdl(DevExt->Chnl[Chnl].Request, &mdl); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s chnl:%d, WdfRequestRetrieveOutputWdmMdl failed\n", DevExt->Name, (Chnl < RIFFA_MAX_NUM_CHNLS ? Chnl : Chnl - RIFFA_MAX_NUM_CHNLS)); return status; } // Move the virtual address forward to the offset vaddr = MmGetMdlVirtualAddress(mdl); vaddr = ((UINT32 *)vaddr) + Offset; // Reduce the length by the offset amount length = MmGetMdlByteCount(mdl); length = (Length < length ? Length : length); length = length - Offset; // Reuse the DMA Transaction status = WdfDmaTransactionInitialize(DevExt->Chnl[Chnl].DmaTransaction, RiffaEvtProgramDma, DmaDirection, mdl, vaddr, (size_t)length); if(!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s chnl:%d, WdfDmaTransactionInitialize failed\n", DevExt->Name, (Chnl < RIFFA_MAX_NUM_CHNLS ? Chnl : Chnl - RIFFA_MAX_NUM_CHNLS)); return status; } // Execute the transaction status = WdfDmaTransactionExecute(DevExt->Chnl[Chnl].DmaTransaction, (WDFCONTEXT)Chnl); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s chnl:%d, WdfDmaTransactionExecute failed\n", DevExt->Name, (Chnl < RIFFA_MAX_NUM_CHNLS ? Chnl : Chnl - RIFFA_MAX_NUM_CHNLS)); WdfDmaTransactionRelease(DevExt->Chnl[Chnl].DmaTransaction); return status; } return status; } /** * Programs the device with scatter gather data. Will program the device with * spill buffer data (as scatter gather buffers) if the DMA length will overrun * the receptical user buffer. * * DevExt - Pointer to the Device Extension * * Chnl - Channel number on which the DMA transaction takes place * * IsSend - TRUE if the direction is a "send", FALSE otherwise */ VOID RiffaProgramScatterGather(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl) { PSCATTER_GATHER_LIST sgList; PULONG bufBase; PHYSICAL_ADDRESS bufAddr; UINT32 pos; UINT32 i; UINT64 provided; UINT64 length; UINT64 spillAfter; // Stop the timer (if set) WdfTimerStop(DevExt->Chnl[Chnl].Timer, FALSE); // Check that the request has not been cancelled. if (!RiffaThreadEnter(DevExt, Chnl)) return; // OK, then get the variables. sgList = DevExt->Chnl[Chnl].SgList; bufBase = DevExt->Chnl[Chnl].CommonBufferBase; bufAddr = DevExt->Chnl[Chnl].CommonBufferBaseLA; pos = DevExt->Chnl[Chnl].SgPos; provided = DevExt->Chnl[Chnl].Provided; length = DevExt->Chnl[Chnl].Length; spillAfter = DevExt->Chnl[Chnl].SpillAfter; // Translate the System's SCATTER_GATHER_LIST elements // into the device's scatter gather elements. for (i = 0; i < DevExt->MaxNumScatterGatherElems && provided < spillAfter; i++, pos++) { if (pos >= sgList->NumberOfElements) break; WRITE_REGISTER_ULONG(bufBase + (i*4) + 0, sgList->Elements[pos].Address.LowPart); WRITE_REGISTER_ULONG(bufBase + (i*4) + 1, sgList->Elements[pos].Address.HighPart); WRITE_REGISTER_ULONG(bufBase + (i*4) + 2, (sgList->Elements[pos].Length>>2)); // Words! provided += sgList->Elements[pos].Length; } // Handle any spillage if (provided >= spillAfter) { for (; i < DevExt->MaxNumScatterGatherElems && provided < length; i++) { WRITE_REGISTER_ULONG(bufBase + (i*4) + 0, DevExt->SpillBufferBaseLA.LowPart); WRITE_REGISTER_ULONG(bufBase + (i*4) + 1, DevExt->SpillBufferBaseLA.HighPart); WRITE_REGISTER_ULONG(bufBase + (i*4) + 2, (RIFFA_SPILL_BUF_SIZE>>2)); // Words! provided += RIFFA_SPILL_BUF_SIZE; } } // Update the data structures DevExt->Chnl[Chnl].Confirmed += DevExt->Chnl[Chnl].ProvidedPrev; DevExt->Chnl[Chnl].ProvidedPrev = provided - DevExt->Chnl[Chnl].Provided; DevExt->Chnl[Chnl].Provided = provided; DevExt->Chnl[Chnl].SgPos = pos; if (i > 0) { // Let the device know about the new scatter gather data. if (Chnl < RIFFA_MAX_NUM_CHNLS) { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, sg buf for send txn: %d elements\n", DevExt->Name, (Chnl < RIFFA_MAX_NUM_CHNLS ? Chnl : Chnl - RIFFA_MAX_NUM_CHNLS), i)); WRITE_REGISTER_ULONG(DevExt->Bar0 + CHNL_REG(Chnl, RIFFA_RX_SG_ADDR_LO_REG), bufAddr.LowPart); WRITE_REGISTER_ULONG(DevExt->Bar0 + CHNL_REG(Chnl, RIFFA_RX_SG_ADDR_HI_REG), bufAddr.HighPart); WRITE_REGISTER_ULONG(DevExt->Bar0 + CHNL_REG(Chnl, RIFFA_RX_SG_LEN_REG), (i*4*4)>>2); // Words! } else { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, sg buf for recv txn: %d elements\n", DevExt->Name, (Chnl < RIFFA_MAX_NUM_CHNLS ? Chnl : Chnl - RIFFA_MAX_NUM_CHNLS), i)); WRITE_REGISTER_ULONG(DevExt->Bar0 + CHNL_REG(Chnl - RIFFA_MAX_NUM_CHNLS, RIFFA_TX_SG_ADDR_LO_REG), bufAddr.LowPart); WRITE_REGISTER_ULONG(DevExt->Bar0 + CHNL_REG(Chnl - RIFFA_MAX_NUM_CHNLS, RIFFA_TX_SG_ADDR_HI_REG), bufAddr.HighPart); WRITE_REGISTER_ULONG(DevExt->Bar0 + CHNL_REG(Chnl - RIFFA_MAX_NUM_CHNLS, RIFFA_TX_SG_LEN_REG), (i*4*4)>>2); // Words! } } else if (provided < length) { // Let the device know that no more scatter gather data will be provided // until a "transfer done" signal is received. This is initiated differently // for a send vs. a receive transaction. InterlockedExchange(&DevExt->Chnl[Chnl].ReqdDone, 1); if (Chnl < RIFFA_MAX_NUM_CHNLS) { // Write the length to signal request for "done" signal after all the // scatter gather regions have been used. WRITE_REGISTER_ULONG(DevExt->Bar0 + CHNL_REG(Chnl, RIFFA_RX_LEN_REG), (ULONG)(provided>>2)); } else { // Read the length to signal request for "done" signal after all the // scatter gather regions have been used. READ_REGISTER_ULONG(DevExt->Bar0 + CHNL_REG(Chnl - RIFFA_MAX_NUM_CHNLS, RIFFA_TX_LEN_REG)); } if (Chnl < RIFFA_MAX_NUM_CHNLS) { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, splitting send txn\n", DevExt->Name, Chnl)); } else { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "riffa: fpga:%s chnl:%d, splitting recv txn\n", DevExt->Name, Chnl - RIFFA_MAX_NUM_CHNLS)); } } // Check for a cancel request and service it. RiffaThreadExit(DevExt, Chnl); // Start the timer (if necessary) if (DevExt->Chnl[Chnl].Timeout > 0) WdfTimerStart(DevExt->Chnl[Chnl].Timer, WDF_REL_TIMEOUT_IN_MS(DevExt->Chnl[Chnl].Timeout)); } /** * Called after the last DMA transfer for the DMA transaction is completed. * Sets the transferred bytes and completes the IOCTL call. * * DevExt - Pointer to the Device Extension * * Chnl - Channel number on which the DMA transaction takes place * * Transferred - Words transferred according to the hardware * * Status - Status after the last transfer has completed. */ VOID RiffaTransactionComplete(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl, IN UINT32 Transferred, IN NTSTATUS Status) { // Stop the timer (if set) WdfTimerStop(DevExt->Chnl[Chnl].Timer, FALSE); // Check that the request has not been cancelled. if (!RiffaThreadEnter(DevExt, Chnl)) return; // Release the DMA Transaction WdfDmaTransactionRelease(DevExt->Chnl[Chnl].DmaTransaction); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "riffa: fpga:%s chnl:%d, words transferred: %lu\n", DevExt->Name, (Chnl < RIFFA_MAX_NUM_CHNLS ? Chnl : Chnl - RIFFA_MAX_NUM_CHNLS), Transferred); if (Chnl < RIFFA_MAX_NUM_CHNLS) { // Update the total confirmed data DevExt->Chnl[Chnl].Confirmed = (((UINT64)Transferred)<<2); // Complete the send request InterlockedExchange(&DevExt->Chnl[Chnl].InUse, 0); RiffaCompleteRequest(DevExt, Chnl, Status); } else { // Complete or repeat if (DevExt->Chnl[Chnl].Last || !NT_SUCCESS(Status)) { // Update the total confirmed data DevExt->Chnl[Chnl].Confirmed = (((UINT64)Transferred)<<2); // Complete the receive request InterlockedExchange(&DevExt->Chnl[Chnl].InUse, 0); RiffaCompleteRequest(DevExt, Chnl, Status); } else { // Not the "last" transaction. Save the transferred amount. DevExt->Chnl[Chnl].ConfirmedPrev += (((UINT64)Transferred)<<2); DevExt->Chnl[Chnl].Confirmed = 0; DevExt->Chnl[Chnl].ProvidedPrev = 0; DevExt->Chnl[Chnl].Provided = 0; // Stay in the kernel and start another receive DMA transaction. // If an interrupt with transaction info has already been received, // start the transaction. If not, set the "ready" bit. if (InterlockedExchange(&DevExt->Chnl[Chnl].Ready, 1)) { // Clear the "ready" bit and start the transaction InterlockedExchange(&DevExt->Chnl[Chnl].Ready, 0); RiffaStartRecvTransaction(DevExt, Chnl); } } } // Check for a cancel request and service it. RiffaThreadExit(DevExt, Chnl); } /** * Programs the device for DMA send transactions. Note, that there is no way to * program the device for receive transactions. Receive transactions can only * be initiated from the device. * * DevExt - Pointer to the Device Extension * * Chnl - Channel number on which the DMA transaction takes place * * Length - Length (in words) of the DMA * * Offset - Offset (in words) to send to the device * * Last - 1 if this is the last transaction for the device, 0 otherwise */ VOID RiffaProgramSend(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl, IN UINT32 Length, IN UINT32 Offset, IN UINT32 Last) { UINT32 offlast; UINT32 chnl; // Let the device know about the new transfer. offlast = ((Offset<<1) | (Last & 0x1)); chnl = (Chnl >= RIFFA_MAX_NUM_CHNLS ? Chnl - RIFFA_MAX_NUM_CHNLS : Chnl); WRITE_REGISTER_ULONG(DevExt->Bar0 + CHNL_REG(chnl, RIFFA_RX_OFFLAST_REG), offlast); WRITE_REGISTER_ULONG(DevExt->Bar0 + CHNL_REG(chnl, RIFFA_RX_LEN_REG), Length); } /** * The framework calls a driver's EvtProgramDma event callback function * when the driver calls WdfDmaTransactionExecute and the system has * enough map registers to do the transfer. The callback function must * program the hardware to start the transfer. A single transaction * initiated by calling WdfDmaTransactionExecute may result in multiple * calls to this function if the buffer is too large and there aren't * enough map registers to do the whole transfer. * * Transaction - DMA transactions initialized and started in RiffaStartDmaTransaction * * Device - A handle to the WDFDEVICE * * Context - Value passed as the context parameter to WdfDmaTransactionExecute * * Direction - DMA direction of the transfer * * SgList - Scatter gather list of the mapped memory to use for transferring * * Returns TRUE */ BOOLEAN RiffaEvtProgramDma(IN WDFDMATRANSACTION Transaction, IN WDFDEVICE Device, IN PVOID Context, IN WDF_DMA_DIRECTION Direction, IN PSCATTER_GATHER_LIST SgList) { PDEVICE_EXTENSION devExt; UINT32 chnl; // Initialize variables and structures devExt = RiffaGetDeviceContext(Device); chnl = (UINT32)Context; // Save the scatter gather list devExt->Chnl[chnl].SgList = SgList; devExt->Chnl[chnl].SgPos = 0; if (Direction == WdfDmaDirectionWriteToDevice && WdfDmaTransactionGetBytesTransferred(Transaction) == 0) { // Program the start of a new transfer. RiffaProgramSend(devExt, chnl, (UINT32)(devExt->Chnl[chnl].Length>>2), (UINT32)(devExt->Chnl[chnl].Offset>>2), devExt->Chnl[chnl].Last); } // Write the initial scatter gather data and notify the device. RiffaProgramScatterGather(devExt, chnl); return TRUE; } ================================================ FILE: sw/riffa_2.1/driver/windows/sys/riffa.inx ================================================ [Version] Signature="$WINDOWS NT$" Class=FPGA ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171} Provider=%UCSD% DriverVer=03/20/2003,6.00.3790 CatalogFile=riffa.cat [DestinationDirs] DefaultDestDir = 12 ; ================= Class section ===================== [ClassInstall32] Addreg=FPGAClassReg [FPGAClassReg] HKR,,,0,%ClassName% HKR,,Icon,,-5 HKR,,DeviceCharacteristics,0x10001,0x100 ;Use same security checks on relative opens HKR,,Security,,"D:P(A;;GA;;;WD)" ;Allow generic all access to all. ;HKR,,Security,,"D:P(A;;GA;;;SY)(A;;GA;;;BA)" ;Allow generic all access to system and built-in Admin. ; ================= Device Install section ===================== [ControlFlags] ExcludeFromSelect=* [Manufacturer] %UCSD%=UCSD,NT$ARCH$ [SourceDisksFiles] riffa.sys=1 [SourceDisksNames] 1=%DISK_NAME%, ; For Win2K [UCSD] ; DisplayName Section DeviceId CompatibleId ; ----------- ------- -------- ------------ %RIFFA.XILINXDESC%%RIFFA.DEBUG%= RIFFA_Inst, PCI\VEN_10EE, PCI\VEN_10EE %RIFFA.ALTERADESC%%RIFFA.DEBUG%= RIFFA_Inst, PCI\VEN_1172, PCI\VEN_1172 ; For XP and later [UCSD.NT$ARCH$] ; DisplayName Section DeviceId CompatibleId ; ----------- ------- -------- ------------ %RIFFA.XILINXDESC%%RIFFA.DEBUG%= RIFFA_Inst, PCI\VEN_10EE, PCI\VEN_10EE %RIFFA.ALTERADESC%%RIFFA.DEBUG%= RIFFA_Inst, PCI\VEN_1172, PCI\VEN_1172 [RIFFA_Inst.NT] CopyFiles=RIFFA.CopyFiles [RIFFA.CopyFiles] riffa.sys [RIFFA_Inst.NT.HW] AddReg=RIFFA.HwReg [RIFFA.HwReg] HKR,"Interrupt Management",,0x00000010 HKR,"Interrupt Management\MessageSignaledInterruptProperties",,0x00000010 HKR,"Interrupt Management\MessageSignaledInterruptProperties",MSISupported,0x00010001,1 [RIFFA_Inst.NT.Services] AddService=RIFFA,0x00000002,RIFFA_Service [RIFFA_Service] DisplayName = %RIFFA.SVCDESC% ServiceType = 1 ; SERVICE_KERNEL_DRIVER StartType = 3 ; SERVICE_DEMAND_START ErrorControl = 1 ; SERVICE_ERROR_NORMAL ServiceBinary = %12%\riffa.sys AddReg = RIFFA_Parameters_AddReg ;-------------- Coinstaller installation [DestinationDirs] CoInstaller_CopyFiles = 11 [RIFFA_Inst.NT.CoInstallers] AddReg=CoInstaller_AddReg CopyFiles=CoInstaller_CopyFiles [CoInstaller_CopyFiles] WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll [SourceDisksFiles] WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames [CoInstaller_AddReg] HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller" [RIFFA_Inst.NT.Wdf] KmdfService = RIFFA, RIFFA_wdfsect [RIFFA_wdfsect] KmdfLibraryVersion = $KMDFVERSION$ [Strings] UCSD = "University of California, San Diego" ClassName = "RIFFA Devices" RIFFA.SVCDESC = "Driver Service for RIFFA FPGAs" RIFFA.XILINXDESC = "Xilinx(R) FPGA" RIFFA.ALTERADESC = "Altera(R) FPGA" DISK_NAME = "RIFFA Install Disk" ================================================ FILE: sw/riffa_2.1/driver/windows/sys/riffa.rc ================================================ #include #include #define VER_FILETYPE VFT_DRV #define VER_FILESUBTYPE VFT2_DRV_SYSTEM #define VER_FILEDESCRIPTION_STR "WDF Driver for RIFFA" #define VER_INTERNALNAME_STR "riffa.sys" #define VER_ORIGINALFILENAME_STR "riffa.sys" #include "common.ver" ================================================ FILE: sw/riffa_2.1/driver/windows/sys/riffa_driver.h ================================================ // // The following value is arbitrarily chosen from the space defined // by Microsoft as being "for non-Microsoft use" // // // {40d49fb9-6085-4e1d-8753-822be944d7bb} DEFINE_GUID (GUID_RIFFA_INTERFACE, 0x40d49fb9, 0x6085, 0x4e1d, 0x87, 0x53, 0x82, 0x2b, 0xe9, 0x44, 0xd7, 0xbb); // The IOCTL function codes from 0x800 to 0xFFF are for customer use. #define IOCTL_RIFFA_SEND \ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) #define IOCTL_RIFFA_RECV \ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x901, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) #define IOCTL_RIFFA_LIST \ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x902, METHOD_OUT_DIRECT ,FILE_ANY_ACCESS) #define IOCTL_RIFFA_RESET \ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x903, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) ================================================ FILE: sw/riffa_2.1/driver/windows/sys/riffa_private.h ================================================ #if !defined(_RIFFA_H_) #define _RIFFA_H_ // Adjusts register offsets for each channel #define CHNL_REG(c, o) (((c)<<4) + o) // Register offsets #define RIFFA_RX_SG_LEN_REG 0x0 #define RIFFA_RX_SG_ADDR_LO_REG 0x1 #define RIFFA_RX_SG_ADDR_HI_REG 0x2 #define RIFFA_RX_LEN_REG 0x3 #define RIFFA_RX_OFFLAST_REG 0x4 #define RIFFA_TX_SG_LEN_REG 0x5 #define RIFFA_TX_SG_ADDR_LO_REG 0x6 #define RIFFA_TX_SG_ADDR_HI_REG 0x7 #define RIFFA_TX_LEN_REG 0x8 #define RIFFA_TX_OFFLAST_REG 0x9 #define RIFFA_INFO_REG 0xA #define RIFFA_IRQ_0_REG 0xB #define RIFFA_IRQ_1_REG 0xC #define RIFFA_RX_TNFR_LEN_REG 0xD #define RIFFA_TX_TNFR_LEN_REG 0xE // Size of common buffer for scatter gather elements #define RIFFA_MIN_SG_BUF_SIZE (4*1024) // Size of common buffer for receive data spill #define RIFFA_SPILL_BUF_SIZE (4*1024) // Maximum number of scatter gather elements for each transfer #define RIFFA_MIN_NUM_SG_ELEMS (200) // Maximum bus width (multiply by 32 to get bit width) #define RIFFA_MAX_BUS_WIDTH_PARAM (4) // Maximum DMA transfer size (in bytes). #define RIFFA_MAX_TNFR_LEN (0xFFFFFFFF) // Number of DMA channels supported #define RIFFA_MAX_NUM_CHNLS (12) // Maximum number of RIFFA FPGAs #define RIFFA_MAX_NUM_FPGAS (5) // The structure used to hold data transfer information typedef struct RIFFA_FPGA_CHNL_IO { UINT32 Id; UINT32 Chnl; UINT32 Length; UINT32 Offset; UINT32 Last; UINT64 Timeout; } RIFFA_FPGA_CHNL_IO, * PRIFFA_FPGA_CHNL_IO; // The structure used to hold FPGA information typedef struct RIFFA_FPGA_INFO { UINT32 num_fpgas; UINT32 id[RIFFA_MAX_NUM_FPGAS]; UINT32 num_chnls[RIFFA_MAX_NUM_FPGAS]; CHAR name[RIFFA_MAX_NUM_FPGAS][16]; UINT32 vendor_id[RIFFA_MAX_NUM_FPGAS]; UINT32 device_id[RIFFA_MAX_NUM_FPGAS]; } RIFFA_FPGA_INFO, * PRIFFA_FPGA_INFO; // Struct for holding DMA transaction state typedef struct CHNL_DIR_STATE { LONG Ready; LONG InUse; LONG ReqdDone; UINT64 Length; UINT64 Offset; UINT32 Last; UINT64 Timeout; UINT64 Capacity; UINT64 Provided; UINT64 ProvidedPrev; UINT64 Confirmed; UINT64 ConfirmedPrev; UINT64 SpillAfter; PSCATTER_GATHER_LIST SgList; UINT32 SgPos; UINT32 ActiveCount; UINT32 Cancel; WDFSPINLOCK SpinLock; WDFTIMER Timer; WDFREQUEST Request; WDFDMATRANSACTION DmaTransaction; WDFCOMMONBUFFER CommonBuffer; PULONG CommonBufferBase; PHYSICAL_ADDRESS CommonBufferBaseLA; // Logical Address } CHNL_DIR_STATE, *PCHNL_DIR_STATE; // Struct for holding interrupt signals and data typedef struct INTR_CHNL_DIR_DATA { BOOLEAN NewTxn; UINT32 OffLast; UINT32 Length; BOOLEAN SgRead; BOOLEAN Done; } INTR_CHNL_DIR_DATA, *PINTR_CHNL_DIR_DATA; // The device extension for the device object typedef struct _DEVICE_EXTENSION { WDFDEVICE Device; PULONG Bar0; UINT32 Bar0Length; UINT32 MaxNumScatterGatherElems; WDFINTERRUPT Interrupt; WDFDMAENABLER DmaEnabler; WDFQUEUE IoctlQueue; UINT32 NumChnls; UINT32 VendorId; UINT32 DeviceId; CHAR Name[16]; INTR_CHNL_DIR_DATA IntrData[2 * RIFFA_MAX_NUM_CHNLS]; // Send is the first bank, CHNL_DIR_STATE Chnl[(2*RIFFA_MAX_NUM_CHNLS)]; // recv is the second bank WDFCOMMONBUFFER SpillBuffer; PUCHAR SpillBufferBase; PHYSICAL_ADDRESS SpillBufferBaseLA; // Logical Address } DEVICE_EXTENSION, *PDEVICE_EXTENSION; // The request extension for the request object typedef struct _REQUEST_EXTENSION { UINT32 Chnl; } REQUEST_EXTENSION, *PREQUEST_EXTENSION; // The timer extension for the timer object typedef struct _TIMER_EXTENSION { UINT32 Chnl; } TIMER_EXTENSION, *PTIMER_EXTENSION; // This will generate the function named RiffaGetDeviceContext to be used for // retreiving the DEVICE_EXTENSION pointer. WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, RiffaGetDeviceContext) // This will generate the function named RiffaGetTimerContext to be used for // retreiving the TIMER_EXTENSION pointer. WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(TIMER_EXTENSION, RiffaGetTimerContext) // This will generate the function named RiffaGetRequestContext to be used for // retreiving the REQUEST_EXTENSION pointer. WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(REQUEST_EXTENSION, RiffaGetRequestContext) // Function prototypes DRIVER_INITIALIZE DriverEntry; EVT_WDF_DRIVER_DEVICE_ADD RiffaEvtDeviceAdd; EVT_WDF_OBJECT_CONTEXT_CLEANUP RiffaEvtDriverContextCleanup; EVT_WDF_DEVICE_PREPARE_HARDWARE RiffaEvtDevicePrepareHardware; EVT_WDF_DEVICE_RELEASE_HARDWARE RiffaEvtDeviceReleaseHardware; NTSTATUS RiffaReadHardwareIds(IN PDEVICE_EXTENSION DevExt); EVT_WDF_INTERRUPT_ISR RiffaEvtInterruptIsr; EVT_WDF_INTERRUPT_DPC RiffaEvtInterruptDpc; BOOLEAN RiffaProcessInterrupt(IN PDEVICE_EXTENSION DevExt, IN UINT32 Offset, IN UINT32 Vect); EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL RiffaEvtIoDeviceControl; VOID RiffaIoctlSend(IN PDEVICE_EXTENSION DevExt, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength); VOID RiffaIoctlRecv(IN PDEVICE_EXTENSION DevExt, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength); VOID RiffaIoctlList(IN PDEVICE_EXTENSION DevExt, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength); VOID RiffaIoctlReset(IN PDEVICE_EXTENSION DevExt, IN WDFREQUEST Request); BOOLEAN RiffaThreadEnter(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl); VOID RiffaThreadExit(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl); VOID RiffaCompleteRequest(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl, IN NTSTATUS Status); EVT_WDF_REQUEST_CANCEL RiffaEvtRequestCancel; EVT_WDF_TIMER RiffaEvtTimerFunc; VOID RiffaStartRecvTransaction(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl); NTSTATUS RiffaStartDmaTransaction(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl, IN UINT64 Length, IN UINT64 Offset, IN WDF_DMA_DIRECTION DmaDirection); VOID RiffaProgramScatterGather(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl); VOID RiffaTransactionComplete(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl, IN UINT32 Transferred, IN NTSTATUS Status); VOID RiffaProgramSend(IN PDEVICE_EXTENSION DevExt, IN UINT32 Chnl, IN UINT32 Length, IN UINT32 Offset, IN UINT32 Last); EVT_WDF_PROGRAM_DMA RiffaEvtProgramDma; #pragma warning(disable:4127) // avoid conditional expression is constant error with W4 #endif ================================================ FILE: sw/riffa_2.1/driver/windows/sys/sources ================================================ TARGETNAME=riffa TARGETTYPE=DRIVER KMDF_VERSION_MAJOR=1 INF_NAME=riffa NTTARGETFILE0=$(OBJ_PATH)\$(O)\$(INF_NAME).inf NTTARGETFILE2=POST PASS0_BINPLACE=$(NTTARGETFILE0) TARGETLIBS=$(TARGETLIBS) \ $(DDK_LIB_PATH)\ntstrsafe.lib PRECOMPILED_INCLUDE=precomp.h PRECOMPILED_PCH=precomp.pch PRECOMPILED_OBJ=precomp.obj #C_DEFINES = $(C_DEFINES) -DASSOC_WRITE_REQUEST_WITH_DMA_TRANSACTION=1 SOURCES= riffa.rc \ riffa.c # Generate WPP tracing code # $(SOURCES) -- run software preprocessor on files listed in SOURCES # -km -- use kernel mode # -func -- define function we'll use for tracing # This would map all TraceEvents calls to # DoTraceMessage. # RUN_WPP= $(SOURCES) \ -km \ -func:TraceEvents(LEVEL,FLAGS,MSG,...) \ -gen:{km-WdfDefault.tpl}*.tmh TARGET_DESTINATION=wdf # Temporarily excuse usage of serviceability impairing macros in code... ALLOW_DATE_TIME=1 ================================================ FILE: sw/riffa_2.1/driver/windows/sys/trace.h ================================================ #include // For TRACE_LEVEL definitions // // If software tracing is defined in the sources file.. // WPP_DEFINE_CONTROL_GUID specifies the GUID used for this driver. // *** REPLACE THE GUID WITH YOUR OWN UNIQUE ID *** // WPP_DEFINE_BIT allows setting debug bit masks to selectively print. // The names defined in the WPP_DEFINE_BIT call define the actual names // that are used to control the level of tracing for the control guid // specified. // // Name of the logger is RIFFA and the guid is // {CA630800-D4D4-4457-8983-DFBBFCAC5542} // (0xca630800, 0xd4d4, 0x4457, 0x89, 0x83, 0xdf, 0xbb, 0xfc, 0xac, 0x55, 0x42); // #define WPP_CHECK_FOR_NULL_STRING //to prevent exceptions due to NULL strings #define WPP_CONTROL_GUIDS \ WPP_DEFINE_CONTROL_GUID(RiffaTraceGuid, (ca630800, D4D4, 4457,8983, DFBBFCAC5542),\ WPP_DEFINE_BIT(DBG_INIT) /* bit 0 = 0x00000001 */ \ WPP_DEFINE_BIT(DBG_PNP) /* bit 1 = 0x00000002 */ \ /* You can have up to 32 defines. If you want more than that,\ you have to provide another trace control GUID */\ ) #define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags) #define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) ================================================ FILE: sw/riffa_2.1/driver/windows/win7install.bat ================================================ @echo off set OLDDIR=%CD% set BDIR1=%CD%\sys\obj%_BUILDTYPE%_%DDK_TARGET_OS%_x86\i386 set BDIR2=%CD%\sys\obj%_BUILDTYPE%_%DDK_TARGET_OS%_amd64\amd64 chdir /d %CD%\install call install.bat %BDIR1% %BDIR2% %_BUILDTYPE% chdir /d %OLDDIR%