├── top └── xtrxr5 │ ├── .gitignore │ ├── gen_project_r5.sh │ ├── build.sh │ ├── build.tcl │ ├── xtrxr4_top.tcl │ └── xlnx_pcie_clocking.v ├── openocd ├── prog.sh ├── bscan_spi_xc7a50t.bit ├── prog.tcl ├── openocd_xc7_ft232.cfg └── stream.cfg ├── lib ├── pcie │ ├── bsswap.v │ ├── dma_config.v │ ├── tx_fill_parts.v │ ├── clz.v │ ├── int_router.v │ ├── pcie_ram_to_wr.v │ ├── pcie_req_to_ram.v │ └── pcie_to_ul.v ├── fifo │ ├── sync_reg.v │ ├── ul_go_base.v │ ├── axis_cc_flow_ctrl.v │ ├── axis_atomic_fo.v │ ├── ul_read_axis.v │ ├── axis_fifo32.v │ ├── ul_read_demux_axis.v │ ├── axis_async_fifo32.v │ ├── axis_mux4.v │ ├── cross_counter.v │ └── ul_router4_wr.v ├── lms7 │ ├── rxdsp_none.v │ ├── lms7_tx_frm_brst_ex.v │ ├── fe_rx_chain_brst.v │ ├── fe_tx_chain_brst.v │ └── lms7_rx_frm_brst.v ├── xtrx │ ├── clk_estimator.v │ ├── cmd_queue.v │ ├── xtrx_gpio_ctrl.v │ ├── ul_drp_cfg.v │ └── xtrxll_regs.vh ├── qspi │ ├── qspi_mem_buf.v │ ├── ul_qspi_mem_async.v │ └── ul_qspi_mem.v ├── uart │ ├── uart_tx.v │ ├── ul_uart_tx.v │ ├── uart_rx.v │ ├── ul_uart_rx.v │ ├── uart_smartcard.v │ └── ul_uart_smartcard.v ├── ram │ ├── ram32xsp.v │ ├── ram32xsdp.v │ └── ram64xsdp.v ├── spi │ └── axis_spi.v └── i2c │ ├── ul_i2c_dme.v │ └── ll_i2c_dmastere.v ├── README.md └── LICENSE /top/xtrxr5/.gitignore: -------------------------------------------------------------------------------- 1 | xtrxr5/ 2 | -------------------------------------------------------------------------------- /openocd/prog.sh: -------------------------------------------------------------------------------- 1 | openocd -f openocd_xc7_ft232.cfg -f stream.cfg -f prog.tcl 2 | -------------------------------------------------------------------------------- /openocd/bscan_spi_xc7a50t.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myriadrf/xtrx-fpga-source/HEAD/openocd/bscan_spi_xc7a50t.bit -------------------------------------------------------------------------------- /openocd/prog.tcl: -------------------------------------------------------------------------------- 1 | init 2 | jtagspi_init 0 bscan_spi_xc7a50t.bit 3 | jtagspi_program ../top/xtrxr5/xtrxr5/xtrxr5.runs/impl_1/xtrxr4_top.bit 0 4 | fpga_program 5 | exit 6 | -------------------------------------------------------------------------------- /top/xtrxr5/gen_project_r5.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | origin_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | vivado -mode batch -nojournal -nolog -source ${origin_dir}/xtrxr4_top.tcl 6 | -------------------------------------------------------------------------------- /top/xtrxr5/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | origin_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | if [ ! -f ${origin_dir}/xtrxr5/xtrxr5.xpr ]; then 6 | . ${origin_dir}/gen_project_r5.sh 7 | fi 8 | 9 | vivado -mode batch -nojournal -nolog -source ${origin_dir}/build.tcl 10 | -------------------------------------------------------------------------------- /openocd/openocd_xc7_ft232.cfg: -------------------------------------------------------------------------------- 1 | interface ftdi 2 | ftdi_vid_pid 0x0403 0x6014 3 | ftdi_channel 0 4 | ftdi_layout_init 0x00e8 0x60eb 5 | reset_config none 6 | 7 | source [find cpld/xilinx-xc7.cfg] 8 | source [find cpld/jtagspi.cfg] 9 | adapter_khz 25000 10 | 11 | proc fpga_program {} { 12 | global _CHIPNAME 13 | xc7_program $_CHIPNAME.tap 14 | } 15 | -------------------------------------------------------------------------------- /top/xtrxr5/build.tcl: -------------------------------------------------------------------------------- 1 | set origin_dir [file dirname [info script]] 2 | 3 | open_project $origin_dir/xtrxr5/xtrxr5.xpr 4 | 5 | #reset_run synth_1 6 | #reset_run blk_mem_gen_nrx_synth_1 7 | #reset_run blk_mem_gen_ntx_synth_1 8 | #reset_run pcie_7x_0_synth_1 9 | 10 | launch_runs impl_1 -to_step write_bitstream -jobs 6 11 | wait_on_run impl_1 12 | 13 | report_property [get_runs synth_1] 14 | 15 | 16 | -------------------------------------------------------------------------------- /lib/pcie/bsswap.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module bsswap #( 7 | parameter BYTES = 4 8 | )( 9 | input [BYTES*8 - 1:0] in, 10 | output [BYTES*8 - 1:0] out 11 | ); 12 | 13 | genvar i; 14 | genvar j; 15 | generate 16 | for (i = 0; i < BYTES; i=i+1) begin: byteb 17 | for (j = 0; j < 8; j=j+1) begin: bitc 18 | assign out[8*(BYTES - i - 1) + j] = in[8*i + j]; 19 | end 20 | end 21 | endgenerate 22 | 23 | // AXI 7 6 5 4 3 2 1 0 24 | // PCIe 1.0 1.1 1.2 1.3 0.0 0.1 0.2 0.3 25 | 26 | endmodule 27 | -------------------------------------------------------------------------------- /lib/fifo/sync_reg.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module sync_reg #( 7 | parameter INIT = 0, 8 | parameter ASYNC_RESET = 0 9 | ) ( 10 | input clk, 11 | input rst, 12 | input in, 13 | output out 14 | 15 | ); 16 | 17 | (* ASYNC_REG = "TRUE" *) reg sync1; 18 | (* ASYNC_REG = "TRUE" *) reg sync2; 19 | 20 | assign out = sync2; 21 | 22 | generate 23 | if (ASYNC_RESET) begin 24 | always @(posedge clk or posedge rst) begin 25 | if (rst) begin 26 | sync1 <= INIT; 27 | sync2 <= INIT; 28 | end else begin 29 | sync1 <= in; 30 | sync2 <= sync1; 31 | end 32 | end 33 | end else begin 34 | always @(posedge clk) begin 35 | if (rst) begin 36 | sync1 <= INIT; 37 | sync2 <= INIT; 38 | end else begin 39 | sync1 <= in; 40 | sync2 <= sync1; 41 | end 42 | end 43 | end 44 | endgenerate 45 | 46 | endmodule 47 | 48 | -------------------------------------------------------------------------------- /lib/fifo/ul_go_base.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | // UL GPIO 32bit 6 | // 7 | // WRITE 8 | // 0: OUT DATA (not sampled) 9 | // 10 | 11 | module ul_go_base #( 12 | parameter DATA_WIDTH = 32, 13 | parameter ADDR_WIDTH = 1, 14 | parameter ADDR_TOTAL = ( 1 << (ADDR_WIDTH)) 15 | )( 16 | // UL Write channel 17 | input [ADDR_WIDTH - 1:0] s_ul_waddr, 18 | input [DATA_WIDTH - 1:0] s_ul_wdata, 19 | input s_ul_wvalid, 20 | output s_ul_wready, 21 | 22 | // GPO 23 | output [DATA_WIDTH - 1:0] gp_out, 24 | output [ADDR_TOTAL - 1:0] gp_out_strobe, 25 | input [ADDR_TOTAL - 1:0] gp_in_ready 26 | ); 27 | 28 | genvar i; 29 | generate 30 | for (i = 0; i < ADDR_TOTAL; i = i + 1) begin: strobe_gen 31 | assign gp_out_strobe[i] = (s_ul_wvalid && (s_ul_waddr == i)); 32 | end 33 | endgenerate 34 | 35 | assign s_ul_wready = gp_in_ready[s_ul_waddr]; 36 | assign gp_out = s_ul_wdata; 37 | 38 | endmodule 39 | -------------------------------------------------------------------------------- /lib/fifo/axis_cc_flow_ctrl.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module axis_cc_flow_ctrl( 7 | input s_axis_clk, 8 | input s_aresetn, 9 | input s_axis_valid, 10 | output s_axis_ready, 11 | 12 | input m_axis_clk, 13 | input m_aresetn, 14 | output m_axis_valid, 15 | input m_axis_ready 16 | ); 17 | 18 | reg wa; 19 | wire wb; 20 | wire ra; 21 | reg rb; 22 | 23 | sync_reg s_to_m( 24 | .clk(m_axis_clk), 25 | .rst(~m_aresetn), 26 | .in(wa), 27 | .out(wb) 28 | ); 29 | 30 | sync_reg m_to_s( 31 | .clk(s_axis_clk), 32 | .rst(~s_aresetn), 33 | .in(rb), 34 | .out(ra) 35 | ); 36 | 37 | assign s_axis_ready = wa ^ ra ^ 1'b1; 38 | assign m_axis_valid = wb ^ rb; 39 | 40 | always @(posedge s_axis_clk) begin 41 | if (~s_aresetn) begin 42 | wa <= 1'b0; 43 | end else if (s_axis_valid && s_axis_ready) begin 44 | wa <= ~wa; 45 | end 46 | end 47 | 48 | always @(posedge m_axis_clk) begin 49 | if (~m_aresetn) begin 50 | rb <= 1'b0; 51 | end else if (m_axis_valid && m_axis_ready) begin 52 | rb <= ~rb; 53 | end 54 | end 55 | 56 | 57 | endmodule 58 | -------------------------------------------------------------------------------- /lib/lms7/rxdsp_none.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module rxdsp_none( 7 | input clk, 8 | input reset, 9 | 10 | input dspcmd_valid, 11 | input [27:0] dspcmd_data, 12 | 13 | input [1:0] dspcmd_legacy, 14 | 15 | input [11:0] in_ai, 16 | input [11:0] in_aq, 17 | input [11:0] in_bi, 18 | input [11:0] in_bq, 19 | input in_valid, 20 | input in_last, 21 | 22 | output [15:0] out_ai, 23 | output [15:0] out_aq, 24 | output [15:0] out_bi, 25 | output [15:0] out_bq, 26 | output out_valid, 27 | output out_last 28 | ); 29 | 30 | assign out_ai = { {4{in_ai[11]}}, in_ai}; 31 | assign out_aq = { {4{in_aq[11]}}, in_aq}; 32 | assign out_bi = { {4{in_bi[11]}}, in_bi}; 33 | assign out_bq = { {4{in_bq[11]}}, in_bq}; 34 | assign out_valid = in_valid; 35 | assign out_last = in_last; 36 | 37 | endmodule 38 | -------------------------------------------------------------------------------- /lib/pcie/dma_config.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module dma_config #( 7 | parameter DMA_BUFFS_BITS = 5 8 | )( 9 | // UL 10 | input s_ul_clk, 11 | 12 | // UL Write channel 13 | input [DMA_BUFFS_BITS - 1:0] s_ul_waddr, 14 | input [31:0] s_ul_wdata, 15 | input s_ul_wvalid, 16 | 17 | // Control IF 18 | input dma_en, 19 | input [DMA_BUFFS_BITS - 1:0] dma_bufno, 20 | 21 | // Output config 22 | output [31:12] dma_addr_out, 23 | output [11:0] dma_buflen_out 24 | ); 25 | 26 | ////////////////////////////////////////////////////////// 27 | // DMA Write REG 28 | // 20bit physical addr + 12bit length of buffer in 16-bytes values 29 | 30 | wire [DMA_BUFFS_BITS - 1:0] dma_addr = (dma_en) ? dma_bufno : s_ul_waddr; 31 | wire dma_we = (~dma_en && s_ul_wvalid); 32 | 33 | ram32xsp #(.WIDTH(32)) dmacfg( 34 | .wclk(s_ul_clk), 35 | .we(dma_we), 36 | .addr(dma_addr), 37 | .datai(s_ul_wdata), 38 | .datao({dma_addr_out, dma_buflen_out}) 39 | ); 40 | 41 | endmodule 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XTRX SDR FPGA image source code 2 | This repository contains the source code of the XTRX SDR FPGA image. 3 | 4 | # How to build 5 | 6 | You will need a copy of Vivado, which can be freely downloaded on the Xilinx website. 7 | 8 | Start by `source`ing the `settings64.sh` file from the Vivado install. For example: 9 | ``` 10 | source /opt/Xilinx/Vivado/2019.1/settings64.sh 11 | ``` 12 | 13 | To build the bitstream, ensure you are in the `fpga-source` directory and the same shell run: 14 | ``` 15 | cd top/xtrxr5 16 | ./build.sh 17 | ``` 18 | 19 | If successful, the output bitstream will be available in the following path: 20 | ``` 21 | top/xtrxr5/xtrxr5/xtrxr5.runs/impl_1/xtrxr4_top.bit 22 | ``` 23 | 24 | # Programming with OpenOCD and JTAGHS2 cable 25 | 26 | Inside the `openocd` directory, there are scripts to allow programming with OpenOCD 27 | and a [Digilent JTAG HS2 cable](https://digilent.com/shop/jtag-hs2-programming-cable/) 28 | 29 | After the bistream is built, one may simply run: 30 | ``` 31 | ./prog.sh 32 | ``` 33 | to flash the bitstream to the xtrx device. 34 | 35 | # License 36 | RTL IP sources are released under the CERN Open Hardware Licence Version 2 - Weakly Reciprocal 37 | Please refer to the LICENSE file of the source code for the full text of the license. 38 | -------------------------------------------------------------------------------- /lib/fifo/axis_atomic_fo.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module axis_atomic_fo #( 7 | parameter CHA_BITS = 8, 8 | parameter CHB_BITS = 8 9 | )( 10 | input reset, 11 | input s_ul_clk, 12 | 13 | output s_axis_comb_tready, 14 | input s_axis_comb_tvalid, 15 | input [CHA_BITS+CHB_BITS-1:0] s_axis_comb_tdata, 16 | input [1:0] s_axis_comb_tuser, 17 | 18 | input m_axis_cha_tready, 19 | output reg m_axis_cha_tvalid, 20 | output reg [CHA_BITS-1:0] m_axis_cha_tdata, 21 | 22 | input m_axis_chb_tready, 23 | output reg m_axis_chb_tvalid, 24 | output reg [CHB_BITS-1:0] m_axis_chb_tdata 25 | ); 26 | 27 | assign s_axis_comb_tready = ~(m_axis_cha_tvalid || m_axis_chb_tvalid); 28 | 29 | always @(posedge s_ul_clk) begin 30 | if (reset) begin 31 | m_axis_cha_tvalid <= 1'b0; 32 | m_axis_chb_tvalid <= 1'b0; 33 | end else begin 34 | if (s_axis_comb_tready && s_axis_comb_tvalid) begin 35 | m_axis_cha_tvalid <= s_axis_comb_tuser[0]; 36 | m_axis_cha_tdata <= s_axis_comb_tdata[CHA_BITS-1:0]; 37 | m_axis_chb_tvalid <= s_axis_comb_tuser[1]; 38 | m_axis_chb_tdata <= s_axis_comb_tdata[CHB_BITS-1+CHA_BITS:CHA_BITS]; 39 | end 40 | 41 | if (m_axis_cha_tvalid && m_axis_chb_tready) 42 | m_axis_cha_tvalid <= 1'b0; 43 | 44 | if (m_axis_chb_tvalid && m_axis_chb_tready) 45 | m_axis_chb_tvalid <= 1'b0; 46 | 47 | end 48 | end 49 | 50 | endmodule 51 | 52 | -------------------------------------------------------------------------------- /lib/xtrx/clk_estimator.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module clk_estimator #( 7 | parameter EST_BITS = 20 8 | )( 9 | input rst, 10 | input clk, 11 | 12 | input meas_clk, 13 | 14 | input cntr_ready, 15 | output cntr_valid, 16 | output [31:0] cntr_data 17 | ); 18 | 19 | 20 | reg [EST_BITS-1:0] div_clk; 21 | always @(posedge clk) begin 22 | if (rst) begin 23 | div_clk <= 0; 24 | end else begin 25 | div_clk <= div_clk + 1'b1; 26 | end 27 | end 28 | 29 | wire out_dclk; 30 | sync_reg self_estim( 31 | .clk(meas_clk), 32 | .rst(rst), 33 | .in(div_clk[EST_BITS-1]), 34 | .out(out_dclk) 35 | ); 36 | 37 | reg [EST_BITS-1:0] cntr_clk; 38 | reg [EST_BITS-1:0] ref_cntr_data_r; 39 | reg [3:0] evnts; 40 | reg prev_out_dclk; 41 | 42 | always @(posedge meas_clk) begin 43 | if (rst) begin 44 | cntr_clk <= 0; 45 | prev_out_dclk <= 0; 46 | ref_cntr_data_r <= 0; 47 | evnts <= 0; 48 | end else begin 49 | prev_out_dclk <= out_dclk; 50 | 51 | if (prev_out_dclk == 0 && out_dclk == 1'b1) begin 52 | cntr_clk <= 0; 53 | ref_cntr_data_r <= cntr_clk; 54 | evnts <= evnts + 1'b1; 55 | end else begin 56 | cntr_clk <= cntr_clk + 1'b1; 57 | end 58 | end 59 | end 60 | 61 | // Self clock estimation 62 | assign cntr_valid = 1'b1; 63 | assign cntr_data = { evnts, {(28 - EST_BITS){1'b0}}, ref_cntr_data_r }; 64 | 65 | 66 | 67 | endmodule 68 | -------------------------------------------------------------------------------- /lib/qspi/qspi_mem_buf.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module qspi_mem_buf #( 7 | parameter MEM_ADDRBITS = 6 8 | )( 9 | input clk, 10 | input rst, 11 | 12 | // UL Write 13 | input [MEM_ADDRBITS-1:0] mem_ul_waddr, 14 | input [31:0] mem_ul_wdata, 15 | input mem_ul_wvalid, 16 | output mem_ul_wready, 17 | 18 | // UL Read address channel 19 | input [MEM_ADDRBITS-1:0] mem_ul_araddr, 20 | input mem_ul_arvalid, 21 | output mem_ul_arready, 22 | 23 | // UL Read data channel signals 24 | output [31:0] mem_ul_rdata, 25 | output mem_ul_rvalid, 26 | input mem_ul_rready, 27 | 28 | // QSPI PORT 29 | input [MEM_ADDRBITS-1:0] qspimem_addr, 30 | input qspimem_valid, 31 | input qspimem_wr, 32 | input [31:0] qspimem_out_data, 33 | output qspimem_ready, 34 | 35 | output [31:0] qspimem_in_data, 36 | output qspimem_in_valid 37 | ); 38 | 39 | wire mem_qspi_rd = qspimem_valid && ~qspimem_wr; 40 | wire mem_qspi_wr = qspimem_valid && qspimem_wr; 41 | 42 | 43 | wire [MEM_ADDRBITS-1:0] mem_addr_rd = (mem_qspi_rd) ? qspimem_addr : mem_ul_araddr; 44 | wire [31:0] mem_data_rd; 45 | assign qspimem_in_data = mem_data_rd; 46 | assign mem_ul_rdata = mem_data_rd; 47 | 48 | assign qspimem_ready = 1'b1; 49 | assign qspimem_in_valid = mem_qspi_rd; 50 | 51 | assign mem_ul_arready = ~mem_qspi_rd && mem_ul_rready; 52 | assign mem_ul_rvalid = ~mem_qspi_rd && mem_ul_arvalid; 53 | 54 | assign mem_ul_wready = ~(mem_qspi_wr); 55 | 56 | 57 | wire [MEM_ADDRBITS-1:0] mem_addr_wr = (mem_qspi_wr) ? qspimem_addr : mem_ul_waddr; 58 | wire [31:0] mem_data_wr = (mem_qspi_wr) ? qspimem_out_data : mem_ul_wdata; 59 | 60 | ram64xsdp #( 61 | .WIDTH(32) 62 | ) ram ( 63 | .wclk(clk), 64 | .we(mem_qspi_wr || mem_ul_wvalid), 65 | .waddr(mem_addr_wr), 66 | .datai(mem_data_wr), 67 | 68 | .raddr(mem_addr_rd), 69 | .datao(mem_data_rd) 70 | ); 71 | 72 | 73 | 74 | endmodule 75 | -------------------------------------------------------------------------------- /lib/uart/uart_tx.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module uart_tx #( 7 | parameter BITS_DATA = 8, 8 | parameter UART_SPEED = 9600, 9 | parameter BUS_SPEED = 62500000 10 | )( 11 | input reset, 12 | input sclk, 13 | 14 | output txd, 15 | 16 | input [BITS_DATA-1:0] axis_data, 17 | input axis_valid, 18 | output axis_ready 19 | ); 20 | 21 | 22 | // 0 - start 23 | // 1..BITS_DATA - data 24 | // BITS_DATA + 1 - stop 25 | 26 | reg [3:0] state; 27 | reg [BITS_DATA:0] data_reg; 28 | reg [15:0] clk_counter; 29 | reg ready; 30 | 31 | assign axis_ready = ready; 32 | 33 | reg clk_div; 34 | reg clk_div_prev; 35 | 36 | assign txd = data_reg[0]; 37 | 38 | always @(posedge sclk) begin 39 | if (reset) begin 40 | clk_counter <= 0; 41 | clk_div <= 0; 42 | clk_div_prev <= 0; 43 | end else begin 44 | if (clk_counter >= (((2*BUS_SPEED + UART_SPEED) / UART_SPEED) / 2)) begin 45 | clk_counter <= 0; 46 | clk_div <= ~clk_div; 47 | end else begin 48 | clk_counter <= clk_counter + 1; 49 | end 50 | 51 | clk_div_prev <= clk_div; 52 | end 53 | end 54 | 55 | wire div_clk_edge = (clk_div_prev != clk_div); 56 | 57 | 58 | always @(posedge sclk) begin 59 | if (reset) begin 60 | state <= 0; 61 | data_reg[0] <= 1; 62 | ready <= 1; 63 | end else begin 64 | case (state) 65 | 0: begin 66 | if (axis_valid && axis_ready) begin 67 | data_reg[BITS_DATA:1] <= axis_data; 68 | state <= 1; 69 | ready <= 1'b0; 70 | end 71 | end 72 | 73 | default: begin 74 | if (div_clk_edge) begin 75 | if (state == 1) begin 76 | data_reg[0] <= 1'b0; //Start bit 77 | end else begin 78 | data_reg[BITS_DATA:0] <= {1'b1, data_reg[BITS_DATA:1]}; // Data bits + stop bit 79 | end 80 | 81 | if (state == BITS_DATA + 2) begin 82 | state <= 1'b0; 83 | ready <= 1'b1; 84 | end else begin 85 | state <= state + 1; 86 | end 87 | end 88 | end 89 | endcase 90 | end 91 | end 92 | 93 | 94 | endmodule 95 | -------------------------------------------------------------------------------- /lib/uart/ul_uart_tx.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module ul_uart_tx #( 7 | parameter BITS_DATA = 8, 8 | parameter UART_SPEED = 9600, 9 | parameter BUS_SPEED = 62500000, 10 | parameter GEN_IRQ_WHEN_HAVE = 0 11 | )( 12 | input reset, 13 | input axis_clk, 14 | 15 | output txd, 16 | 17 | // Output data readback stream 18 | input [BITS_DATA-1:0] axis_data, 19 | input axis_valid, 20 | output axis_ready, 21 | 22 | output [4:0] fifo_used, 23 | output fifo_empty, 24 | 25 | input int_ready, 26 | output reg int_valid 27 | ); 28 | 29 | 30 | wire [BITS_DATA-1:0] axis_uart_data; 31 | wire axis_uart_valid; 32 | wire axis_uart_ready; 33 | 34 | uart_tx #( 35 | .BITS_DATA(BITS_DATA), 36 | .UART_SPEED(UART_SPEED), 37 | .BUS_SPEED(BUS_SPEED) 38 | ) uart_tx ( 39 | .reset(reset), 40 | .sclk(axis_clk), 41 | 42 | .txd(txd), 43 | 44 | .axis_data(axis_uart_data), 45 | .axis_valid(axis_uart_valid), 46 | .axis_ready(axis_uart_ready) 47 | ); 48 | 49 | // We fire interrupt only when we initally fully occupied TX buffer and then it gets 50 | // down to low mark level 51 | wire fifo_full = (fifo_used == 5'b1_1111); 52 | wire fifo_trigger_low = (fifo_used == GEN_IRQ_WHEN_HAVE); 53 | 54 | reg fifo_full_prev; 55 | 56 | always @(posedge axis_clk) begin 57 | if (reset) begin 58 | int_valid <= 0; 59 | fifo_full_prev <= 0; 60 | end else begin 61 | if (~fifo_full_prev) 62 | fifo_full_prev <= fifo_full; 63 | 64 | if (fifo_full_prev && fifo_trigger_low) begin 65 | int_valid <= 1'b1; 66 | fifo_full_prev <= 1'b0; 67 | end else if (int_valid && int_ready) begin 68 | int_valid <= 1'b0; 69 | end 70 | end 71 | end 72 | 73 | axis_fifo32 #( 74 | .WIDTH(BITS_DATA) 75 | ) axis_fifo32 ( 76 | .clk(axis_clk), 77 | .axisrst(reset), 78 | 79 | .axis_rx_tdata(axis_data), 80 | .axis_rx_tvalid(axis_valid), 81 | .axis_rx_tready(axis_ready), 82 | 83 | .axis_tx_tdata(axis_uart_data), 84 | .axis_tx_tvalid(axis_uart_valid), 85 | .axis_tx_tready(axis_uart_ready), 86 | 87 | .fifo_used(fifo_used), 88 | .fifo_empty(fifo_empty) 89 | ); 90 | 91 | endmodule 92 | -------------------------------------------------------------------------------- /lib/pcie/tx_fill_parts.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module tx_fill_parts #( 7 | parameter WIDTH = 16 8 | )( 9 | input reset, 10 | input s_ul_clk, 11 | 12 | input incb_valid, 13 | output incb_ready, 14 | input [WIDTH-1:0] incb_size, 15 | input [4:0] incb_idx, 16 | 17 | input decb_valid, 18 | input [WIDTH-1:0] decb_size, 19 | input [4:0] decb_idx, 20 | 21 | input [4:0] cur_buf_num, 22 | output inc_buf 23 | ); 24 | 25 | reg [4:0] buf_max_written; 26 | 27 | localparam ST_IDLE = 0; 28 | localparam ST_CHECK = 1; 29 | 30 | reg state; 31 | 32 | 33 | wire [WIDTH-1:0] ram_out; 34 | assign incb_ready = ~decb_valid && (state == ST_IDLE); 35 | 36 | wire inc_cycle = incb_valid && incb_ready; 37 | wire dec_cycle = decb_valid; 38 | wire check_cycle= ~dec_cycle && ~inc_cycle; 39 | 40 | wire [4:0] ram_addr = (dec_cycle) ? decb_idx : 41 | (check_cycle) ? cur_buf_num /*buf_last_commited*/ : incb_idx; 42 | wire ram_we = inc_cycle || dec_cycle; 43 | 44 | wire [WIDTH-1:0] writeback_dec = ram_out - decb_size; 45 | wire [WIDTH-1:0] writeback = (inc_cycle) ? incb_size : writeback_dec; 46 | 47 | //assign decb_last = (writeback_dec == 0); 48 | 49 | // FIXME to reg!! 50 | assign inc_buf = ~dec_cycle && ~dec_cycle && (state == ST_CHECK) && (ram_out == 0); 51 | 52 | always @(posedge s_ul_clk) begin 53 | if (reset) begin 54 | //buf_last_commited <= 5'b0_0000; 55 | buf_max_written <= 5'b1_1111; 56 | state <= ST_IDLE; 57 | end else begin 58 | if (dec_cycle) begin 59 | state <= ST_CHECK; 60 | end else if (inc_cycle) begin 61 | buf_max_written <= incb_idx; 62 | end else if (state == ST_CHECK) begin // check_cycle 63 | if (ram_out == 0) begin 64 | // Buffer has been filled 65 | //buf_last_commited <= buf_last_commited + 1'b1; 66 | if (buf_max_written == cur_buf_num/*buf_last_commited*/) 67 | state <= ST_IDLE; 68 | end else begin 69 | state <= ST_IDLE; 70 | end 71 | end 72 | 73 | end 74 | end 75 | 76 | ram32xsp #(.WIDTH(WIDTH)) storage( 77 | .wclk(s_ul_clk), 78 | .we(ram_we), 79 | .addr(ram_addr), 80 | .datai(writeback), 81 | .datao(ram_out) 82 | ); 83 | 84 | endmodule 85 | 86 | -------------------------------------------------------------------------------- /lib/uart/uart_rx.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module uart_rx #( 7 | parameter BITS_DATA = 8, 8 | parameter UART_SPEED = 9600, 9 | parameter BUS_SPEED = 62500000, 10 | parameter BITS_SAMPLE = 3 11 | )( 12 | input reset, 13 | input sclk, 14 | 15 | input rxd, 16 | 17 | output [BITS_DATA-1:0] data, 18 | output data_valid, 19 | 20 | output debug_rxd_one, 21 | output debug_rxd_zero 22 | ); 23 | 24 | (* ASYNC_REG = "TRUE" *) reg [BITS_SAMPLE - 1:0] rxd_sampled; 25 | always @(posedge sclk) begin 26 | if (reset) begin 27 | rxd_sampled <= ((1 << BITS_SAMPLE) - 1); 28 | end else begin 29 | rxd_sampled <= { rxd_sampled[BITS_SAMPLE - 2:0], rxd }; 30 | end 31 | end 32 | 33 | wire sampled_one = (rxd_sampled == ((1 << BITS_SAMPLE) - 1)); 34 | wire sampled_zero = (rxd_sampled == 0); 35 | 36 | assign debug_rxd_one = sampled_one; 37 | assign debug_rxd_zero = sampled_zero; 38 | 39 | // 0 - start 40 | // 1..BITS_DATA - data 41 | // BITS_DATA + 1 - stop 42 | 43 | reg [4:0] state; 44 | reg [BITS_DATA-1:0] data_reg; 45 | reg [15:0] clk_counter; 46 | reg finished; 47 | 48 | assign data = data_reg; 49 | assign data_valid = finished; 50 | assign debug_state = state; 51 | assign debug_clk_counter = clk_counter; 52 | 53 | always @(posedge sclk) begin 54 | if (reset) begin 55 | state <= 0; 56 | data_reg <= 0; 57 | clk_counter <= 0; 58 | finished <= 0; 59 | end else begin 60 | if (state == 0) begin 61 | clk_counter <= 0; 62 | 63 | // Start bit detected 64 | if (sampled_zero) begin 65 | state <= state + 1; 66 | finished <= 1'b0; 67 | end 68 | end else if (state == (2*BITS_DATA + 3)) begin 69 | if (sampled_one) begin 70 | state <= 0; 71 | finished <= 1'b1; 72 | end 73 | end else begin 74 | if (clk_counter >= (((2*BUS_SPEED + UART_SPEED) / UART_SPEED) / 4)) begin 75 | clk_counter <= 0; 76 | state <= state + 1; 77 | 78 | if (state[0] == 1'b1) begin 79 | data_reg <= { sampled_one, data_reg[BITS_DATA-1:1] }; 80 | end 81 | end else begin 82 | clk_counter <= clk_counter + 1; 83 | end 84 | end 85 | end 86 | end 87 | 88 | 89 | endmodule 90 | -------------------------------------------------------------------------------- /openocd/stream.cfg: -------------------------------------------------------------------------------- 1 | 2 | proc jtagstream_poll {tap tx n} { 3 | set m [string length $tx] 4 | set n [expr ($m>$n)?$m:$n] 5 | set txi [lrepeat $n {10 0x001}] 6 | set i 0 7 | foreach txj [split $tx ""] { 8 | lset txi $i 1 [format 0x%4.4X [expr 0x201 | ([scan $txj %c] << 1)]] 9 | incr i 10 | #echo tx[scan $txj %c] 11 | } 12 | set txi [concat {*}$txi] 13 | set rxi [split [drscan $tap {*}$txi -endstate DRPAUSE] " "] 14 | #echo $txi:$rxi 15 | set rx "" 16 | set writable 1 17 | foreach {rxj} $rxi { 18 | set readable [expr 0x$rxj & 0x200] 19 | set writable [expr 0x$rxj & $writable] 20 | if {$readable} { 21 | append rx [format %c [expr (0x$rxj >> 1) & 0xff]] 22 | } 23 | } 24 | return [list $rx $readable $writable] 25 | } 26 | 27 | proc jtagstream_drain {tap tx chunk_rx max_rx} { 28 | lassign [jtagstream_poll $tap $tx $chunk_rx] rx readable writable 29 | while {[expr $writable && ($readable > 0) && ([string length $rx] < $max_rx)]} { 30 | lassign [jtagstream_poll $tap "" $chunk_rx] rxi readable writable 31 | append rx $rxi 32 | } 33 | #if {!$writable} { 34 | # echo "write overflow" 35 | #} 36 | return $rx 37 | } 38 | 39 | proc jtagstream_rxtx {tap client is_poll} { 40 | if {![$client eof]} { 41 | if {!$is_poll} { 42 | set tx [$client read 1] 43 | } else { 44 | set tx "" 45 | } 46 | set rx [jtagstream_drain $tap $tx 64 4096] 47 | if {[string length $rx]} { 48 | #echo [string length $rx] 49 | $client puts -nonewline $rx 50 | } 51 | if {$is_poll} { 52 | after 1 [list jtagstream_rxtx $tap $client 1] 53 | } 54 | } else { 55 | $client readable {} 56 | $client onexception {} 57 | $client close 58 | } 59 | } 60 | 61 | proc jtagstream_client {tap sock} { 62 | set client [$sock accept] 63 | fconfigure $client -buffering none 64 | $client readable [list jtagstream_rxtx $tap $client 0] 65 | $client onexception [list $client close] 66 | after 1 [list jtagstream_rxtx $tap $client 1] 67 | } 68 | 69 | proc jtagstream_exit {sock} { 70 | stdin readable {} 71 | $sock readable {} 72 | } 73 | 74 | proc jtagstream_serve {tap port} { 75 | set sock [socket stream.server $port] 76 | $sock readable [list jtagstream_client $tap $sock] 77 | stdin readable [list jtagstream_exit $sock] 78 | vwait forever 79 | $sock close 80 | } 81 | -------------------------------------------------------------------------------- /top/xtrxr5/xtrxr4_top.tcl: -------------------------------------------------------------------------------- 1 | set origin_dir [file dirname [info script]] 2 | set root_dir [file normalize "$origin_dir/../.."] 3 | puts "origin_dir = $origin_dir" 4 | puts "repo root = $root_dir" 5 | 6 | create_project xtrxr5 $origin_dir/xtrxr5 7 | 8 | set proj_dir [get_property directory [current_project]] 9 | 10 | set obj [get_projects xtrxr5] 11 | set_property "part" "xc7a50tcpg236-2" $obj 12 | set_property "simulator_language" "Mixed" $obj 13 | set_property "source_mgmt_mode" "DisplayOnly" $obj 14 | set_property "target_language" "Verilog" $obj 15 | 16 | # Create 'sources_1' fileset (if not found) 17 | if {[string equal [get_filesets -quiet sources_1] ""]} { 18 | create_fileset -srcset sources_1 19 | } 20 | 21 | # Set 'sources_1' fileset object 22 | set obj [get_filesets sources_1] 23 | add_files -norecurse -fileset $obj $root_dir/lib/ram/ 24 | add_files -norecurse -fileset $obj $root_dir/lib/fifo/ 25 | add_files -norecurse -fileset $obj $root_dir/lib/i2c/ 26 | add_files -norecurse -fileset $obj $root_dir/lib/spi/ 27 | add_files -norecurse -fileset $obj $root_dir/lib/qspi/ 28 | add_files -norecurse -fileset $obj $root_dir/lib/uart/ 29 | add_files -norecurse -fileset $obj $root_dir/lib/lms7/ 30 | add_files -norecurse -fileset $obj $root_dir/lib/pcie/ 31 | add_files -norecurse -fileset $obj $root_dir/lib/xtrx/ 32 | set_property include_dirs $root_dir/lib/xtrx/ $obj 33 | 34 | #top level sources 35 | add_files -norecurse -fileset $obj $origin_dir/ 36 | 37 | #add ip cores 38 | import_ip $origin_dir/ip/blk_mem_gen_nrx/blk_mem_gen_nrx.xci -quiet 39 | import_ip $origin_dir/ip/blk_mem_gen_ntx/blk_mem_gen_ntx.xci -quiet 40 | import_ip $origin_dir/ip/pcie_7x_0/pcie_7x_0.xci -quiet 41 | 42 | #upgrade IPs if vivado version is newer 43 | upgrade_ip [get_ips blk_mem_gen_nrx] 44 | upgrade_ip [get_ips blk_mem_gen_ntx] 45 | upgrade_ip [get_ips pcie_7x_0] 46 | 47 | set_property "top" "xtrxr4_top" $obj 48 | set_property -name {STEPS.SYNTH_DESIGN.ARGS.MORE OPTIONS} -value {-generic NO_PPS=1 -generic NO_GTIME=1} -objects [get_runs synth_1] 49 | 50 | if {[string equal [get_filesets -quiet constrs_1] ""]} { 51 | create_fileset -constrset constrs_1 52 | } 53 | 54 | # Set 'constrs_1' fileset object 55 | set obj [get_filesets constrs_1] 56 | 57 | # Add/Import constrs file and set constrs file properties 58 | set file "[file normalize "$origin_dir/xtrxr5_ucf.xdc"]" 59 | set file_added [add_files -norecurse -fileset $obj $file] 60 | set file "$origin_dir/xtrxr5_ucf.xdc" 61 | set file [file normalize $file] 62 | set file_obj [get_files -of_objects [get_filesets constrs_1] [list "*$file"]] 63 | set_property "file_type" "XDC" $file_obj 64 | 65 | 66 | report_ip_status 67 | -------------------------------------------------------------------------------- /lib/fifo/ul_read_axis.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | // UL GPIO 32bit 6 | // READ 7 | // x: IN DATA (not sampled) 8 | 9 | module ul_read_axis #( 10 | parameter DATA_WIDTH = 32, 11 | parameter NBITS = 4, 12 | parameter N = (1 << NBITS) 13 | )( 14 | // UL clocks 15 | input s_ul_clk, 16 | input s_ul_aresetn, 17 | 18 | // UL Read address channel 0 19 | input [NBITS - 1:0] s_ul_araddr, 20 | input s_ul_arvalid, 21 | output s_ul_arready, 22 | // UL Write data channel 0 signals 23 | output reg [DATA_WIDTH - 1:0] s_ul_rdata, 24 | output reg s_ul_rvalid, 25 | input s_ul_rready, 26 | 27 | // read port 0..N-1 28 | output reg [N - 1:0] axis_port_ready, 29 | input [N - 1:0] axis_port_valid, 30 | input [DATA_WIDTH*N - 1:0] axis_port_data, 31 | 32 | output [NBITS - 1:0] axis_port_addr, 33 | output axis_port_addr_valid 34 | ); 35 | 36 | 37 | reg [NBITS - 1:0] selector; 38 | wire [DATA_WIDTH - 1:0] axis_data; 39 | 40 | genvar i; 41 | generate 42 | for (i = 0; i < DATA_WIDTH; i=i+1) begin: gen 43 | assign axis_data[i] = axis_port_data[DATA_WIDTH*selector + i]; 44 | end 45 | endgenerate 46 | 47 | wire axis_valid = axis_port_valid[selector]; 48 | 49 | localparam ST_WAIT_READ_ADDR = 1'b0; 50 | localparam ST_WAIT_TRANSFER = 1'b1; 51 | 52 | reg state; 53 | 54 | assign s_ul_arready = ((s_ul_rvalid && s_ul_rready) || ~s_ul_rvalid); 55 | 56 | always @(posedge s_ul_clk) begin 57 | if (~s_ul_aresetn) begin 58 | axis_port_ready <= 0; 59 | s_ul_rvalid <= 0; 60 | selector <= 0; 61 | state <= ST_WAIT_READ_ADDR; 62 | end else begin 63 | if (state == ST_WAIT_READ_ADDR) begin 64 | if (s_ul_arvalid && s_ul_arready) begin 65 | selector <= s_ul_araddr; 66 | state <= ST_WAIT_TRANSFER; 67 | axis_port_ready[s_ul_araddr] <= 1'b1; 68 | end 69 | 70 | if (s_ul_rvalid && s_ul_rready) begin 71 | s_ul_rvalid <= 1'b0; 72 | end 73 | end else begin 74 | if (axis_valid) begin 75 | axis_port_ready <= 0; 76 | s_ul_rdata <= axis_data; 77 | s_ul_rvalid <= 1'b1; 78 | state <= ST_WAIT_READ_ADDR; 79 | end 80 | end 81 | end 82 | end 83 | 84 | assign axis_port_addr = selector; 85 | assign axis_port_addr_valid = (state == ST_WAIT_TRANSFER); 86 | 87 | 88 | endmodule 89 | -------------------------------------------------------------------------------- /lib/pcie/clz.v: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // COUNT LEADING ZEROS (up to 32-bit) 3 | // 4 | // MODULUS4 CLZ ALGO 5 | // 6 | // Copyright (c) 2016-2019 Fairwaves, Inc. 7 | // SPDX-License-Identifier: CERN-OHL-W-2.0 8 | // 9 | /////////////////////////////////////////////////////////////////////////////// 10 | 11 | module clz #( 12 | parameter B_WIDTH = 5 13 | ) ( 14 | input [2**B_WIDTH - 1:0] data, 15 | 16 | output [B_WIDTH - 1:0] count, 17 | output count_nvalid 18 | ); 19 | 20 | wire [2**(B_WIDTH - 1) - 1:0] decode_mod4; 21 | wire [2**(B_WIDTH - 2) - 1:0] empty_mod4; 22 | 23 | genvar i; 24 | generate 25 | for (i = 0; i < 2**(B_WIDTH - 2); i=i+1) begin: mod4_blk 26 | assign decode_mod4[2 * i + 1:2 * i] = 27 | data[4 * i + 3] ? 2'b00 : 28 | data[4 * i + 2] ? 2'b01 : 29 | data[4 * i + 1] ? 2'b10 : 2'b11; 30 | 31 | assign empty_mod4[i] = (data[4 * i + 3:4 * i] == 4'h0); 32 | end 33 | endgenerate 34 | 35 | assign count_nvalid = &empty_mod4; 36 | 37 | generate 38 | 39 | if (B_WIDTH == 5) begin 40 | wire [2:0] select_mod = (~empty_mod4[7]) ? 3'h7 : 41 | (~empty_mod4[6]) ? 3'h6 : 42 | (~empty_mod4[5]) ? 3'h5 : 43 | (~empty_mod4[4]) ? 3'h4 : 44 | (~empty_mod4[3]) ? 3'h3 : 45 | (~empty_mod4[2]) ? 3'h2 : 46 | (~empty_mod4[1]) ? 3'h1 : 3'h0; 47 | wire [1:0] mod4_bits = (select_mod == 7) ? decode_mod4[15:14] : 48 | (select_mod == 6) ? decode_mod4[13:12] : 49 | (select_mod == 5) ? decode_mod4[11:10] : 50 | (select_mod == 4) ? decode_mod4[9:8] : 51 | (select_mod == 3) ? decode_mod4[7:6] : 52 | (select_mod == 2) ? decode_mod4[5:4] : 53 | (select_mod == 1) ? decode_mod4[3:2] : decode_mod4[1:0]; 54 | assign count = { ~select_mod, mod4_bits }; 55 | end else if (B_WIDTH == 4) begin 56 | wire [1:0] select_mod = (~empty_mod4[3]) ? 2'h3 : 57 | (~empty_mod4[2]) ? 2'h2 : 58 | (~empty_mod4[1]) ? 2'h1 : 2'h0; 59 | wire [1:0] mod4_bits = (select_mod == 3) ? decode_mod4[7:6] : 60 | (select_mod == 2) ? decode_mod4[5:4] : 61 | (select_mod == 1) ? decode_mod4[3:2] : decode_mod4[1:0]; 62 | assign count = { ~select_mod, mod4_bits }; 63 | end else if (B_WIDTH == 3) begin 64 | wire select_mod = (~empty_mod4[1]); 65 | wire [1:0] mod4_bits = (select_mod) ? decode_mod4[3:2] : decode_mod4[1:0]; 66 | assign count = { ~select_mod, mod4_bits }; 67 | end else if (B_WIDTH == 2) begin 68 | assign count = decode_mod4; 69 | end 70 | 71 | endgenerate 72 | 73 | endmodule 74 | -------------------------------------------------------------------------------- /lib/lms7/lms7_tx_frm_brst_ex.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module lms7_tx_frm_brst_ex( 7 | input rst, 8 | 9 | // LMS7 10 | output reg [11:0] out_sdr_ai, 11 | output reg [11:0] out_sdr_aq, 12 | output reg [11:0] out_sdr_bi, 13 | output reg [11:0] out_sdr_bq, 14 | output reg out_strobe, 15 | input mclk, 16 | // FIFO (RAM) 17 | input [47:0] fifo_tdata, 18 | input fifo_tvalid, 19 | output fifo_tready, 20 | 21 | // MODE 22 | input single_ch_mode, 23 | input [2:0] inter_rate 24 | ); 25 | 26 | wire [11:0] in_sampe_bi = fifo_tdata[11:0]; 27 | wire [11:0] in_sampe_ai = fifo_tdata[23:12]; 28 | wire [11:0] in_sampe_bq = fifo_tdata[35:24]; 29 | wire [11:0] in_sampe_aq = fifo_tdata[47:36]; 30 | 31 | wire [5:0] inter_val = 32 | (inter_rate == 0) ? 0 : 33 | (inter_rate == 1) ? 1 : 34 | (inter_rate == 2) ? 3 : 35 | (inter_rate == 3) ? 7 : 36 | (inter_rate == 4) ? 15 : 37 | (inter_rate == 5) ? 31 : 63; 38 | 39 | reg mode_siso; 40 | reg siso_switch; 41 | reg [5:0] iter; 42 | 43 | wire sample_release = (inter_val == iter); 44 | 45 | always @(posedge mclk) begin 46 | if (rst) begin 47 | iter <= 0; 48 | end else begin 49 | if (sample_release) begin 50 | iter <= 0; 51 | end else begin 52 | iter <= iter + 1; 53 | end 54 | end 55 | end 56 | 57 | assign fifo_tready = siso_switch && sample_release; 58 | 59 | always @(posedge mclk) begin 60 | if (rst) begin 61 | out_sdr_ai <= 12'b0; 62 | out_sdr_aq <= 12'b0; 63 | out_sdr_bi <= 12'b0; 64 | out_sdr_bq <= 12'b0; 65 | out_strobe <= 1'b0; 66 | 67 | mode_siso <= single_ch_mode; 68 | siso_switch <= ~single_ch_mode; 69 | 70 | end else begin 71 | if (mode_siso && sample_release) begin 72 | siso_switch <= ~siso_switch; 73 | end 74 | 75 | if (fifo_tvalid && sample_release) begin 76 | if (mode_siso) begin 77 | out_sdr_ai <= (~siso_switch) ? in_sampe_ai : in_sampe_aq; 78 | out_sdr_bi <= (~siso_switch) ? in_sampe_ai : in_sampe_aq; 79 | out_sdr_aq <= (~siso_switch) ? in_sampe_bi : in_sampe_bq; 80 | out_sdr_bq <= (~siso_switch) ? in_sampe_bi : in_sampe_bq; 81 | end else begin 82 | out_sdr_ai <= in_sampe_ai; 83 | out_sdr_aq <= in_sampe_aq; 84 | out_sdr_bi <= in_sampe_bi; 85 | out_sdr_bq <= in_sampe_bq; 86 | end 87 | end else if (~fifo_tvalid && sample_release) begin 88 | out_sdr_ai <= 12'b0; 89 | out_sdr_aq <= 12'b0; 90 | out_sdr_bi <= 12'b0; 91 | out_sdr_bq <= 12'b0; 92 | end 93 | 94 | out_strobe <= sample_release; 95 | end 96 | end 97 | 98 | endmodule 99 | -------------------------------------------------------------------------------- /lib/fifo/axis_fifo32.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module axis_fifo32 #( 7 | parameter WIDTH = 32, 8 | parameter DEEP_BITS = 5 9 | ) ( 10 | input clk, 11 | input axisrst, 12 | 13 | input [WIDTH-1:0] axis_rx_tdata, 14 | input axis_rx_tvalid, 15 | output axis_rx_tready, 16 | 17 | output [WIDTH-1:0] axis_tx_tdata, 18 | output axis_tx_tvalid, 19 | input axis_tx_tready, 20 | 21 | output [DEEP_BITS-1:0] fifo_used, 22 | 23 | output reg fifo_empty 24 | ); 25 | 26 | reg [DEEP_BITS-1:0] rpos; 27 | 28 | assign fifo_used = rpos; 29 | 30 | localparam FIFO_FULL = ((1 << DEEP_BITS) - 1); 31 | 32 | assign axis_tx_tvalid = (~fifo_empty); 33 | assign axis_rx_tready = (rpos != FIFO_FULL); 34 | 35 | wire fifo_wr_strobe = axis_rx_tvalid && axis_rx_tready; 36 | wire fifo_rd_strobe = axis_tx_tvalid && axis_tx_tready; 37 | 38 | `ifdef SYM 39 | localparam MAX_DEEP = 1 << DEEP_BITS; 40 | 41 | reg [WIDTH-1:0] fifo[MAX_DEEP - 1:0]; 42 | always @(posedge clk) begin 43 | if (fifo_wr_strobe) begin 44 | fifo[0] <= axis_rx_tdata; 45 | end 46 | end 47 | 48 | generate 49 | genvar i; 50 | for (i = 1; i < MAX_DEEP; i=i+1) begin : srl 51 | always @(posedge clk) begin 52 | if (fifo_wr_strobe) 53 | fifo[i] <= fifo[i - 1]; 54 | end 55 | end 56 | endgenerate 57 | 58 | assign axis_tx_tdata = fifo[rpos]; 59 | 60 | `else 61 | genvar i; 62 | generate 63 | if (DEEP_BITS == 5) begin 64 | for (i = 0; i < WIDTH; i=i+1) begin : srl32 65 | SRLC32E #( 66 | .INIT(32'h00000000) 67 | ) fifo32( 68 | .CLK(clk), 69 | .CE(fifo_wr_strobe), 70 | .D(axis_rx_tdata[i]), 71 | .A(rpos), 72 | .Q(axis_tx_tdata[i]), 73 | .Q31() 74 | ); 75 | end 76 | end else if (DEEP_BITS == 4) begin 77 | for (i = 0; i < WIDTH; i=i+1) begin : srl16 78 | SRL16E #( 79 | .INIT(16'h0000) 80 | ) fifo16 ( 81 | .CLK(clk), 82 | .CE(fifo_wr_strobe), 83 | .D(axis_rx_tdata[i]), 84 | .A0(rpos[0]), 85 | .A1(rpos[1]), 86 | .A2(rpos[2]), 87 | .A3(rpos[3]), 88 | .Q(axis_tx_tdata[i]) 89 | ); 90 | end 91 | end 92 | endgenerate 93 | `endif 94 | 95 | always @(posedge clk) begin 96 | if (axisrst) begin 97 | fifo_empty <= 1; 98 | rpos <= 0; 99 | end else begin 100 | if (fifo_wr_strobe && fifo_rd_strobe) begin 101 | end else if (fifo_wr_strobe) begin 102 | if (fifo_empty) 103 | fifo_empty <= 1'b0; 104 | else 105 | rpos <= rpos + 1; 106 | 107 | end else if (fifo_rd_strobe) begin 108 | if (rpos == 0) 109 | fifo_empty <= 1'b1; 110 | else 111 | rpos <= rpos - 1; 112 | 113 | end 114 | end 115 | end 116 | 117 | 118 | endmodule 119 | -------------------------------------------------------------------------------- /lib/fifo/ul_read_demux_axis.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module ul_read_demux_axis #( 7 | parameter DATA_WIDTH = 32, 8 | parameter NBITS = 4 9 | )( 10 | // UL clocks 11 | input s_ul_clk, 12 | input s_ul_aresetn, 13 | 14 | // UL Read address channel 0 15 | input [NBITS - 1:0] s_ul_araddr, 16 | input s_ul_arvalid, 17 | output s_ul_arready, 18 | // UL Write data channel 0 signals 19 | output [DATA_WIDTH - 1:0] s_ul_rdata, 20 | output s_ul_rvalid, 21 | input s_ul_rready, 22 | 23 | // mem port 24 | // UL Read address channel 0 25 | output [NBITS - 2:0] m0_ul_araddr, 26 | output m0_ul_arvalid, 27 | input m0_ul_arready, 28 | // UL Write data channel 0 signals 29 | input [DATA_WIDTH - 1:0] m0_ul_rdata, 30 | input m0_ul_rvalid, 31 | output m0_ul_rready, 32 | 33 | // mem port 34 | // UL Read address channel 0 35 | output [NBITS - 2:0] m1_ul_araddr, 36 | output m1_ul_arvalid, 37 | input m1_ul_arready, 38 | // UL Write data channel 0 signals 39 | input [DATA_WIDTH - 1:0] m1_ul_rdata, 40 | input m1_ul_rvalid, 41 | output m1_ul_rready 42 | ); 43 | 44 | 45 | assign m0_ul_araddr = s_ul_araddr[NBITS - 2:0]; 46 | assign m1_ul_araddr = s_ul_araddr[NBITS - 2:0]; 47 | 48 | assign s_ul_arready = ~s_ul_araddr[NBITS - 1] && m0_ul_arready || 49 | s_ul_araddr[NBITS - 1] && m1_ul_arready; 50 | 51 | assign m0_ul_arvalid = ~s_ul_araddr[NBITS - 1] && s_ul_arvalid; 52 | assign m1_ul_arvalid = s_ul_araddr[NBITS - 1] && s_ul_arvalid; 53 | 54 | wire rb_route_port; 55 | wire rb_route_port_valid; 56 | 57 | 58 | axis_fifo32 #(.WIDTH(1)) routing_fifo ( 59 | .clk(s_ul_clk), 60 | .axisrst(~s_ul_aresetn), 61 | 62 | .axis_rx_tdata(s_ul_araddr[NBITS - 1]), 63 | .axis_rx_tvalid(s_ul_arready && s_ul_arvalid), 64 | .axis_rx_tready(), //Ignore for now since it's impossible to hold 32 bit queue 65 | 66 | .axis_tx_tdata(rb_route_port), 67 | .axis_tx_tvalid(rb_route_port_valid), 68 | .axis_tx_tready(s_ul_rready && s_ul_rvalid), 69 | 70 | .fifo_used(), 71 | .fifo_empty() 72 | ); 73 | 74 | assign s_ul_rdata = (rb_route_port) ? m1_ul_rdata : m0_ul_rdata; 75 | assign s_ul_rvalid = rb_route_port_valid && (~rb_route_port && m0_ul_rvalid || 76 | rb_route_port && m1_ul_rvalid); 77 | 78 | assign m0_ul_rready = rb_route_port_valid && ~rb_route_port && s_ul_rready; 79 | assign m1_ul_rready = rb_route_port_valid && rb_route_port && s_ul_rready; 80 | 81 | 82 | endmodule 83 | -------------------------------------------------------------------------------- /lib/uart/ul_uart_rx.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module ul_uart_rx #( 7 | parameter BITS_DATA = 8, 8 | parameter UART_SPEED = 9600, 9 | parameter BUS_SPEED = 62500000, 10 | parameter BITS_SAMPLE = 3 11 | )( 12 | input reset, 13 | input axis_clk, 14 | 15 | input rxd, 16 | 17 | // Output data readback stream 18 | output [15:0] axis_rdata, 19 | output axis_rvalid, 20 | input axis_rready, 21 | 22 | // Interrupt 23 | input int_ready, 24 | output reg int_valid 25 | ); 26 | 27 | wire [BITS_DATA-1:0] data; 28 | wire data_valid; 29 | 30 | wire debug_rxd_one; 31 | wire debug_rxd_zero; 32 | 33 | uart_rx #( 34 | .BITS_DATA(BITS_DATA), 35 | .UART_SPEED(UART_SPEED), 36 | .BUS_SPEED(BUS_SPEED), 37 | .BITS_SAMPLE(BITS_SAMPLE) 38 | ) uart_rx ( 39 | .reset(reset), 40 | .sclk(axis_clk), 41 | 42 | .rxd(rxd), 43 | 44 | .data(data), 45 | .data_valid(data_valid), 46 | 47 | .debug_rxd_one(debug_rxd_one), 48 | .debug_rxd_zero(debug_rxd_zero) 49 | ); 50 | 51 | wire [4:0] fifo_used; 52 | wire fifo_empty; 53 | 54 | assign axis_rvalid = 1'b1; 55 | 56 | `include "xtrxll_regs.vh" 57 | 58 | assign axis_rdata[UART_FIFORX_EMPTY] = fifo_empty; 59 | assign axis_rdata[14:10] = fifo_used; 60 | assign axis_rdata[9:8] = {debug_rxd_one, debug_rxd_zero}; 61 | //assign axis_rdata[10:BITS_DATA] = 0; 62 | 63 | reg processed; 64 | wire axis_valid = data_valid && ~processed; 65 | wire axis_ready; 66 | 67 | //reg buf_overrun; // TODO 68 | 69 | always @(posedge axis_clk) begin 70 | if (reset) begin 71 | processed <= 0; 72 | end else begin 73 | if (axis_valid && axis_ready) begin 74 | processed <= 1; 75 | end else if (processed && ~data_valid) begin 76 | processed <= 0; 77 | end 78 | end 79 | end 80 | 81 | reg fifo_empty_prev; 82 | always @(posedge axis_clk) begin 83 | if (reset) begin 84 | int_valid <= 0; 85 | fifo_empty_prev <= 1'b1; 86 | end else begin 87 | fifo_empty_prev <= fifo_empty; 88 | 89 | if (fifo_empty_prev == 1'b1 && fifo_empty == 1'b0) begin 90 | int_valid <= 1'b1; 91 | end else if (int_valid && int_ready) begin 92 | int_valid <= 1'b0; 93 | end 94 | end 95 | end 96 | 97 | axis_fifo32 #( 98 | .WIDTH(BITS_DATA) 99 | ) axis_fifo32 ( 100 | .clk(axis_clk), 101 | .axisrst(reset), 102 | 103 | .axis_rx_tdata(data), 104 | .axis_rx_tvalid(axis_valid), 105 | .axis_rx_tready(axis_ready), 106 | 107 | .axis_tx_tdata(axis_rdata[BITS_DATA-1:0]), 108 | .axis_tx_tvalid(), 109 | .axis_tx_tready(axis_rready), 110 | 111 | .fifo_used(fifo_used), 112 | .fifo_empty(fifo_empty) 113 | ); 114 | 115 | 116 | endmodule 117 | -------------------------------------------------------------------------------- /lib/fifo/axis_async_fifo32.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module axis_async_fifo32 #( 7 | parameter WIDTH = 12, 8 | parameter DEEP_BITS = 5, 9 | parameter GRAY_BITS = DEEP_BITS, 10 | parameter PIPELINED = 0 11 | ) ( 12 | input clkrx, 13 | input rstrx, 14 | 15 | input [WIDTH-1:0] axis_rx_tdata, 16 | input axis_rx_tvalid, 17 | output axis_rx_tready, 18 | 19 | input clktx, 20 | input rsttx, 21 | 22 | output [WIDTH-1:0] axis_tx_tdata, 23 | output axis_tx_tvalid, 24 | input axis_tx_tready 25 | ); 26 | 27 | localparam CC_GRAY_BITS = ((GRAY_BITS > DEEP_BITS) ? DEEP_BITS : GRAY_BITS) + 1; 28 | 29 | wire rx_addr_inc; 30 | wire [DEEP_BITS:0] rx_addr; 31 | wire [DEEP_BITS:0] rx_addr_cc_tx; // tx addr latched @ rx domain 32 | 33 | wire tx_addr_inc; 34 | wire [DEEP_BITS:0] tx_addr; 35 | wire [DEEP_BITS:0] tx_addr_cc_rx; // rx addr latched @ tx domain 36 | 37 | 38 | cross_counter #( 39 | .WIDTH(DEEP_BITS + 1), 40 | .GRAY_BITS(CC_GRAY_BITS), 41 | .OUT_PIPELINED(PIPELINED) 42 | ) rx_addr_cross ( 43 | .inrst(rstrx), 44 | .inclk(clkrx), 45 | .incmdvalid(rx_addr_inc), 46 | .incmdinc(1'b1), 47 | .incnt(rx_addr), 48 | 49 | .outrst(rsttx), 50 | .outclk(clktx), 51 | .outcnt(rx_addr_cc_tx) 52 | ); 53 | 54 | cross_counter #( 55 | .WIDTH(DEEP_BITS + 1), 56 | .GRAY_BITS(CC_GRAY_BITS), 57 | .OUT_PIPELINED(PIPELINED) 58 | ) tx_addr_cross ( 59 | .inrst(rsttx), 60 | .inclk(clktx), 61 | .incmdvalid(tx_addr_inc), 62 | .incmdinc(1'b1), 63 | .incnt(tx_addr), 64 | 65 | .outrst(rstrx), 66 | .outclk(clkrx), 67 | .outcnt(tx_addr_cc_rx) 68 | ); 69 | 70 | wire [DEEP_BITS:0] rx_diff = rx_addr - tx_addr_cc_rx; 71 | wire [DEEP_BITS:0] tx_diff = rx_addr_cc_tx - tx_addr - 1'b1; 72 | 73 | 74 | wire rx_full = rx_diff[DEEP_BITS]; 75 | wire tx_empty = tx_diff[DEEP_BITS]; 76 | 77 | //TODO: add pipeline option for full & empty 78 | 79 | assign axis_rx_tready = ~rx_full; 80 | assign rx_addr_inc = axis_rx_tvalid && axis_rx_tready; 81 | 82 | assign axis_tx_tvalid = ~tx_empty; 83 | assign tx_addr_inc = axis_tx_tready && axis_tx_tvalid; 84 | 85 | generate 86 | if (DEEP_BITS <= 5) begin: deep32 87 | ram32xsdp #( 88 | .WIDTH(WIDTH) 89 | ) ram ( 90 | .wclk(clkrx), 91 | .we(rx_addr_inc), 92 | .waddr(rx_addr[DEEP_BITS-1:0]), 93 | .datai(axis_rx_tdata), 94 | 95 | .raddr(tx_addr[DEEP_BITS-1:0]), 96 | .datao(axis_tx_tdata) 97 | ); 98 | end else if (DEEP_BITS == 6) begin: deep64 99 | ram64xsdp #( 100 | .WIDTH(WIDTH) 101 | ) ram ( 102 | .wclk(clkrx), 103 | .we(rx_addr_inc), 104 | .waddr(rx_addr[5:0]), 105 | .datai(axis_rx_tdata), 106 | 107 | .raddr(tx_addr[5:0]), 108 | .datao(axis_tx_tdata) 109 | ); 110 | end else begin 111 | // TODO 112 | 113 | end 114 | endgenerate 115 | 116 | endmodule 117 | 118 | -------------------------------------------------------------------------------- /lib/xtrx/cmd_queue.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module cmd_queue #( 7 | parameter TS_BITS = 30, 8 | parameter CMD_QUEUE_BITS = 5 9 | )( 10 | // CMD clock 11 | input newcmd_clk, 12 | input newcmd_reset, 13 | 14 | // CMD control 15 | output newcmd_ready, 16 | input newcmd_valid, 17 | input [TS_BITS - 1:0] newcmd_data, 18 | 19 | // CMD statistics 20 | input newcmd_stat_ready, 21 | output newcmd_stat_valid, 22 | output [31:0] newcmd_stat_data, 23 | 24 | // Interrupt logic 25 | input newcmd_int_ready, 26 | output reg newcmd_int_valid, 27 | 28 | // TS clock 29 | input ts_clk, 30 | input [TS_BITS - 1:0] ts_current, 31 | 32 | input cmd_ready, 33 | output reg cmd_valid 34 | ); 35 | 36 | wire [TS_BITS-1:0] readcmd_ts; 37 | wire readcmd_queue_nonempty; 38 | wire newcmd_sp_ready; 39 | 40 | assign newcmd_ready = 1'b1; 41 | 42 | axis_async_fifo32 #( 43 | .WIDTH(TS_BITS), 44 | .DEEP_BITS(CMD_QUEUE_BITS) 45 | ) cmdfifo ( 46 | .clkrx(newcmd_clk), 47 | .rstrx(newcmd_reset), 48 | 49 | .axis_rx_tdata(newcmd_data), 50 | .axis_rx_tvalid(newcmd_valid), 51 | .axis_rx_tready(newcmd_sp_ready), 52 | 53 | .clktx(ts_clk), 54 | .rsttx(newcmd_reset), 55 | 56 | .axis_tx_tdata(readcmd_ts), 57 | .axis_tx_tvalid(readcmd_queue_nonempty), 58 | .axis_tx_tready(cmd_valid & cmd_ready) 59 | ); 60 | 61 | assign newcmd_stat_valid = 1'b1; 62 | assign newcmd_stat_data[31:CMD_QUEUE_BITS+1]= 0; 63 | assign newcmd_stat_data[CMD_QUEUE_BITS] = newcmd_sp_ready; 64 | assign newcmd_stat_data[CMD_QUEUE_BITS-1:0] = 0; 65 | 66 | 67 | reg newcmd_ready_prev; 68 | always @(posedge newcmd_clk) begin 69 | if (newcmd_reset) begin 70 | newcmd_ready_prev <= 1'b1; 71 | end else begin 72 | newcmd_ready_prev <= newcmd_sp_ready; 73 | 74 | if (newcmd_sp_ready && ~newcmd_ready_prev) begin 75 | newcmd_int_valid <= 1'b1; 76 | end else if (newcmd_int_valid && newcmd_int_ready) begin 77 | newcmd_int_valid <= 1'b0; 78 | end 79 | end 80 | end 81 | 82 | reg cmd_avaliable; 83 | reg ts_went_off_reg; 84 | wire [TS_BITS-1:0] ts_diff = readcmd_ts - ts_current - 1'b1; 85 | wire ts_went_off = ts_diff[TS_BITS-1]; 86 | 87 | always @(posedge ts_clk) begin 88 | if (newcmd_reset) begin 89 | cmd_avaliable <= 0; 90 | cmd_valid <= 0; 91 | ts_went_off_reg <= 0; 92 | end else begin 93 | if (cmd_valid == 0) begin 94 | cmd_avaliable <= readcmd_queue_nonempty; 95 | ts_went_off_reg <= ts_went_off; 96 | cmd_valid <= cmd_avaliable && ts_went_off_reg; 97 | end else if (cmd_valid & cmd_ready) begin 98 | cmd_avaliable <= 0; 99 | ts_went_off_reg <= 0; 100 | cmd_valid <= 0; 101 | end 102 | 103 | end 104 | end 105 | 106 | 107 | endmodule 108 | 109 | -------------------------------------------------------------------------------- /lib/fifo/axis_mux4.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module axis_mux4( 7 | input s_axis_clk, 8 | input s_arstn, 9 | 10 | input m_axis_tready, 11 | output [63:0] m_axis_tdata, 12 | output [7:0] m_axis_tkeep, 13 | output m_axis_tlast, 14 | output m_axis_tvalid, 15 | 16 | output s0_axis_tready, 17 | input [63:0] s0_axis_tdata, 18 | input [7:0] s0_axis_tkeep, 19 | input s0_axis_tlast, 20 | input s0_axis_tvalid, 21 | 22 | output s1_axis_tready, 23 | input [63:0] s1_axis_tdata, 24 | input [7:0] s1_axis_tkeep, 25 | input s1_axis_tlast, 26 | input s1_axis_tvalid, 27 | 28 | output s2_axis_tready, 29 | input [63:0] s2_axis_tdata, 30 | input [7:0] s2_axis_tkeep, 31 | input s2_axis_tlast, 32 | input s2_axis_tvalid, 33 | 34 | output s3_axis_tready, 35 | input [63:0] s3_axis_tdata, 36 | input [7:0] s3_axis_tkeep, 37 | input s3_axis_tlast, 38 | input s3_axis_tvalid 39 | ); 40 | 41 | 42 | localparam MUX_S0 = 2'h0; 43 | localparam MUX_S1 = 2'h1; 44 | localparam MUX_S2 = 2'h2; 45 | localparam MUX_S3 = 2'h3; 46 | 47 | reg [1:0] state; 48 | 49 | assign m_axis_tdata = (state == MUX_S0) ? s0_axis_tdata : 50 | (state == MUX_S1) ? s1_axis_tdata : 51 | (state == MUX_S2) ? s2_axis_tdata : 52 | /*(state == MUX_S3) ?*/ s3_axis_tdata; 53 | 54 | assign m_axis_tkeep = (state == MUX_S0) ? s0_axis_tkeep : 55 | (state == MUX_S1) ? s1_axis_tkeep : 56 | (state == MUX_S2) ? s2_axis_tkeep : 57 | /*(state == MUX_S3) ?*/ s3_axis_tkeep; 58 | 59 | assign m_axis_tvalid = (state == MUX_S0) ? s0_axis_tvalid : 60 | (state == MUX_S1) ? s1_axis_tvalid : 61 | (state == MUX_S2) ? s2_axis_tvalid : 62 | (state == MUX_S3) ? s3_axis_tvalid : 63 | 1'b0; 64 | 65 | assign m_axis_tlast = (state == MUX_S0) ? s0_axis_tlast : 66 | (state == MUX_S1) ? s1_axis_tlast : 67 | (state == MUX_S2) ? s2_axis_tlast : 68 | /*(state == MUX_S3) ?*/ s3_axis_tlast; 69 | 70 | assign s0_axis_tready = (state == MUX_S0) ? m_axis_tready : 1'b0; 71 | assign s1_axis_tready = (state == MUX_S1) ? m_axis_tready : 1'b0; 72 | assign s2_axis_tready = (state == MUX_S2) ? m_axis_tready : 1'b0; 73 | assign s3_axis_tready = (state == MUX_S3) ? m_axis_tready : 1'b0; 74 | 75 | wire [2:0] sel_prio_state = (s0_axis_tvalid) ? {1'b1, MUX_S0 } : 76 | (s1_axis_tvalid) ? {1'b1, MUX_S1 } : 77 | (s2_axis_tvalid) ? {1'b1, MUX_S2 } : 78 | (s3_axis_tvalid) ? {1'b1, MUX_S3 } : {1'b0, MUX_S0 }; 79 | 80 | reg started; 81 | wire last_transfer = m_axis_tready && m_axis_tvalid && m_axis_tlast; 82 | 83 | always @(posedge s_axis_clk) begin 84 | if (~s_arstn) begin 85 | state <= MUX_S0; 86 | started <= 1'b0; 87 | end else begin 88 | if (~started) begin 89 | if (m_axis_tvalid) begin 90 | started <= 1'b1; 91 | end else begin 92 | state <= sel_prio_state[1:0]; 93 | end 94 | end 95 | if (last_transfer) begin 96 | state <= sel_prio_state[1:0]; 97 | started <= (state != sel_prio_state[1:0]) && sel_prio_state[2]; 98 | end 99 | end 100 | end 101 | 102 | 103 | endmodule 104 | -------------------------------------------------------------------------------- /lib/fifo/cross_counter.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module cross_counter #( 7 | parameter WIDTH = 8, 8 | parameter GRAY_BITS = WIDTH, 9 | parameter OUT_WIDTH = WIDTH, 10 | parameter OUT_LOWER_SKIP = 0, 11 | parameter OUT_RESET_ASYNC = 0, 12 | parameter OUT_PIPELINED = 0 13 | )( 14 | input inrst, 15 | input inclk, 16 | input incmdvalid, 17 | input incmdinc, 18 | output [WIDTH - 1:0] incnt, 19 | 20 | input outclk, 21 | input outrst, 22 | output [OUT_WIDTH - 1:OUT_LOWER_SKIP] outcnt 23 | ); 24 | 25 | genvar i; 26 | 27 | reg [WIDTH - 1:0] counter; 28 | 29 | reg [GRAY_BITS - 1:OUT_LOWER_SKIP] gray_encoded; 30 | wire [GRAY_BITS - 1:OUT_LOWER_SKIP] sync_out; 31 | 32 | wire [GRAY_BITS - 1:OUT_LOWER_SKIP] gcode = 33 | counter[GRAY_BITS - 1:OUT_LOWER_SKIP] ^ counter[GRAY_BITS - 1:OUT_LOWER_SKIP+1]; 34 | 35 | 36 | always @(posedge inclk) begin 37 | if (inrst) begin 38 | counter <= 0; 39 | gray_encoded <= 0; 40 | end else begin 41 | if (incmdvalid) begin 42 | if (incmdinc) begin 43 | counter <= counter + 1; 44 | end else begin 45 | counter <= counter - 1; 46 | end 47 | end 48 | gray_encoded <= gcode; 49 | end 50 | end 51 | 52 | assign incnt = counter; 53 | 54 | 55 | generate 56 | for (i = OUT_LOWER_SKIP; i < GRAY_BITS; i=i+1) begin: forreg 57 | sync_reg #(.ASYNC_RESET(OUT_RESET_ASYNC)) sreg ( 58 | .clk(outclk), 59 | .rst(outrst), 60 | .in(gray_encoded[i]), 61 | .out(sync_out[i]) 62 | ); 63 | end 64 | endgenerate 65 | 66 | 67 | wire [GRAY_BITS - 1:OUT_LOWER_SKIP] outgray; 68 | assign outgray[GRAY_BITS - 1] = sync_out[GRAY_BITS - 1]; 69 | 70 | generate 71 | for (i = GRAY_BITS - 1; i > OUT_LOWER_SKIP; i=i-1) begin 72 | assign outgray[i - 1] = outgray[i] ^ sync_out[i - 1]; 73 | end 74 | endgenerate 75 | 76 | 77 | 78 | generate 79 | if (OUT_PIPELINED || OUT_WIDTH != GRAY_BITS) begin 80 | reg [OUT_WIDTH - 1:OUT_LOWER_SKIP] oval; 81 | assign outcnt = oval; 82 | 83 | if (OUT_RESET_ASYNC) begin 84 | always @(posedge outclk or posedge outrst) begin 85 | if (outrst) begin 86 | oval[GRAY_BITS - 1:OUT_LOWER_SKIP] <= 0; 87 | end else begin 88 | oval[GRAY_BITS - 1:OUT_LOWER_SKIP] <= outgray[GRAY_BITS - 1:OUT_LOWER_SKIP]; 89 | end 90 | end 91 | end else begin 92 | always @(posedge outclk) begin 93 | if (outrst) begin 94 | oval[GRAY_BITS - 1:OUT_LOWER_SKIP] <= 0; 95 | end else begin 96 | oval[GRAY_BITS - 1:OUT_LOWER_SKIP] <= outgray[GRAY_BITS - 1:OUT_LOWER_SKIP]; 97 | end 98 | end 99 | end 100 | 101 | if (OUT_WIDTH != GRAY_BITS) begin 102 | wire wrap_pos = (oval[GRAY_BITS - 1:OUT_LOWER_SKIP] > outgray[GRAY_BITS - 1:OUT_LOWER_SKIP]); 103 | 104 | if (OUT_RESET_ASYNC) begin 105 | always @(posedge outclk or posedge outrst) begin 106 | if (outrst) begin 107 | oval[OUT_WIDTH - 1:GRAY_BITS] <= 0; 108 | end else begin 109 | oval[OUT_WIDTH - 1:GRAY_BITS] <= oval[OUT_WIDTH - 1:GRAY_BITS] + wrap_pos; 110 | end 111 | end 112 | end else begin 113 | always @(posedge outclk) begin 114 | if (outrst) begin 115 | oval[OUT_WIDTH - 1:GRAY_BITS] <= 0; 116 | end else begin 117 | oval[OUT_WIDTH - 1:GRAY_BITS] <= oval[OUT_WIDTH - 1:GRAY_BITS] + wrap_pos; 118 | end 119 | end 120 | end 121 | end 122 | end else begin 123 | assign outcnt = outgray[OUT_WIDTH - 1:OUT_LOWER_SKIP]; 124 | end 125 | endgenerate 126 | 127 | 128 | endmodule 129 | -------------------------------------------------------------------------------- /lib/xtrx/xtrx_gpio_ctrl.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module xtrx_gpio_ctrl #( 7 | parameter GPIO_WIDTH = 12, 8 | parameter GPIO_DEF_FUNCTIONS = 0 9 | )( 10 | input clk, 11 | input rst, 12 | 13 | // GPIO configuration regusters 14 | output gpio_func_ready, 15 | input gpio_func_valid, 16 | input [GPIO_WIDTH*2-1:0] gpio_func_data, 17 | 18 | output gpio_dir_ready, 19 | input gpio_dir_valid, 20 | input [GPIO_WIDTH-1:0] gpio_dir_data, 21 | 22 | output gpio_out_ready, 23 | input gpio_out_valid, 24 | input [GPIO_WIDTH-1:0] gpio_out_data, 25 | 26 | output gpio_cs_ready, 27 | input gpio_cs_valid, 28 | input [2*GPIO_WIDTH-1:0] gpio_cs_data, 29 | 30 | // User Interrupt control 31 | input gpio_in_ready, 32 | output gpio_in_valid, 33 | output [GPIO_WIDTH-1:0] gpio_in_data, 34 | 35 | 36 | output [GPIO_WIDTH-1:0] se_gpio_oe, 37 | output [GPIO_WIDTH-1:0] se_gpio_out, 38 | input [GPIO_WIDTH-1:0] se_gpio_in, 39 | 40 | // Alt function for specific GPIO(s) 41 | input [GPIO_WIDTH-1:0] alt0_se_gpio_oe, 42 | input [GPIO_WIDTH-1:0] alt0_se_gpio_out, 43 | output [GPIO_WIDTH-1:0] alt0_se_gpio_in, 44 | 45 | input [GPIO_WIDTH-1:0] alt1_se_gpio_oe, 46 | input [GPIO_WIDTH-1:0] alt1_se_gpio_out, 47 | output [GPIO_WIDTH-1:0] alt1_se_gpio_in, 48 | 49 | input [GPIO_WIDTH-1:0] alt2_se_gpio_oe, 50 | input [GPIO_WIDTH-1:0] alt2_se_gpio_out, 51 | output [GPIO_WIDTH-1:0] alt2_se_gpio_in 52 | 53 | ); 54 | 55 | localparam ALT_FUNCTION_WIDTH = 2; 56 | 57 | // Func: 58 | // 0 - general IO 59 | // 1,2,3 - ALT function 0,1,2,3 60 | 61 | reg [GPIO_WIDTH-1:0] gpio_out; 62 | reg [GPIO_WIDTH-1:0] gpio_oe = 0; 63 | 64 | reg [GPIO_WIDTH*ALT_FUNCTION_WIDTH-1:0] gpio_alt_sel = GPIO_DEF_FUNCTIONS; 65 | 66 | genvar i, j; 67 | generate 68 | for (i = 0; i < GPIO_WIDTH; i=i+1) begin: gpio 69 | wire [ALT_FUNCTION_WIDTH-1:0] altsel; 70 | for (j = 0; j < ALT_FUNCTION_WIDTH; j=j+1) begin 71 | assign altsel[j] = gpio_alt_sel[ALT_FUNCTION_WIDTH*i+j]; 72 | end 73 | assign se_gpio_out[i] = (altsel == 1) ? alt0_se_gpio_out[i] : 74 | (altsel == 2) ? alt1_se_gpio_out[i] : 75 | (altsel == 3) ? alt2_se_gpio_out[i] : gpio_out[i]; 76 | assign se_gpio_oe[i] = (altsel == 1) ? alt0_se_gpio_oe[i] : 77 | (altsel == 2) ? alt1_se_gpio_oe[i] : 78 | (altsel == 3) ? alt2_se_gpio_oe[i] : gpio_oe[i]; 79 | 80 | assign alt0_se_gpio_in[i] = se_gpio_in[i]; 81 | assign alt1_se_gpio_in[i] = se_gpio_in[i]; 82 | assign alt2_se_gpio_in[i] = se_gpio_in[i]; 83 | end 84 | endgenerate 85 | 86 | reg [GPIO_WIDTH-1:0] gpio_in; 87 | 88 | assign gpio_func_ready = 1'b1; 89 | assign gpio_dir_ready = 1'b1; 90 | assign gpio_out_ready = 1'b1; 91 | assign gpio_cs_ready = 1'b1; 92 | 93 | assign gpio_in_valid = 1'b1; 94 | assign gpio_in_data = gpio_in; 95 | 96 | always @(posedge clk) begin 97 | if (rst) begin 98 | gpio_alt_sel <= GPIO_DEF_FUNCTIONS; 99 | gpio_oe <= 0; 100 | end else begin 101 | if (gpio_func_ready && gpio_func_valid) begin 102 | gpio_alt_sel <= gpio_func_data; 103 | end 104 | if (gpio_dir_ready && gpio_dir_valid) begin 105 | gpio_oe <= gpio_dir_data; 106 | end 107 | if (gpio_out_ready && gpio_out_valid) begin 108 | gpio_out <= gpio_out_data; 109 | end 110 | if (gpio_cs_ready && gpio_cs_valid) begin 111 | gpio_out <= (gpio_out & ~gpio_cs_data[2*GPIO_WIDTH-1:GPIO_WIDTH]) | gpio_cs_data[GPIO_WIDTH-1:0]; 112 | end 113 | // Update only on requests ?! 114 | gpio_in <= se_gpio_in; 115 | end 116 | end 117 | 118 | endmodule 119 | 120 | 121 | -------------------------------------------------------------------------------- /lib/ram/ram32xsp.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module ram32xsp #( 7 | parameter WIDTH = 8 8 | )( 9 | input wclk, 10 | input we, 11 | input [4:0] addr, 12 | input [WIDTH-1:0] datai, 13 | output [WIDTH-1:0] datao 14 | ); 15 | 16 | `ifdef SYM 17 | // Make debug friendly 18 | 19 | reg [WIDTH-1:0] r0; 20 | reg [WIDTH-1:0] r1; 21 | reg [WIDTH-1:0] r2; 22 | reg [WIDTH-1:0] r3; 23 | reg [WIDTH-1:0] r4; 24 | reg [WIDTH-1:0] r5; 25 | reg [WIDTH-1:0] r6; 26 | reg [WIDTH-1:0] r7; 27 | reg [WIDTH-1:0] r8; 28 | reg [WIDTH-1:0] r9; 29 | reg [WIDTH-1:0] r10; 30 | reg [WIDTH-1:0] r11; 31 | reg [WIDTH-1:0] r12; 32 | reg [WIDTH-1:0] r13; 33 | reg [WIDTH-1:0] r14; 34 | reg [WIDTH-1:0] r15; 35 | reg [WIDTH-1:0] r16; 36 | reg [WIDTH-1:0] r17; 37 | reg [WIDTH-1:0] r18; 38 | reg [WIDTH-1:0] r19; 39 | reg [WIDTH-1:0] r20; 40 | reg [WIDTH-1:0] r21; 41 | reg [WIDTH-1:0] r22; 42 | reg [WIDTH-1:0] r23; 43 | reg [WIDTH-1:0] r24; 44 | reg [WIDTH-1:0] r25; 45 | reg [WIDTH-1:0] r26; 46 | reg [WIDTH-1:0] r27; 47 | reg [WIDTH-1:0] r28; 48 | reg [WIDTH-1:0] r29; 49 | reg [WIDTH-1:0] r30; 50 | reg [WIDTH-1:0] r31; 51 | 52 | always @(posedge wclk) begin 53 | if (we) begin 54 | case (addr) 55 | 0: r0 <= datai; 56 | 1: r1 <= datai; 57 | 2: r2 <= datai; 58 | 3: r3 <= datai; 59 | 4: r4 <= datai; 60 | 5: r5 <= datai; 61 | 6: r6 <= datai; 62 | 7: r7 <= datai; 63 | 8: r8 <= datai; 64 | 9: r9 <= datai; 65 | 10: r10<= datai; 66 | 11: r11<= datai; 67 | 12: r12<= datai; 68 | 13: r13<= datai; 69 | 14: r14<= datai; 70 | 15: r15<= datai; 71 | 16: r16<= datai; 72 | 17: r17<= datai; 73 | 18: r18<= datai; 74 | 19: r19<= datai; 75 | 20: r20<= datai; 76 | 21: r21<= datai; 77 | 22: r22<= datai; 78 | 23: r23<= datai; 79 | 24: r24<= datai; 80 | 25: r25<= datai; 81 | 26: r26<= datai; 82 | 27: r27<= datai; 83 | 28: r28<= datai; 84 | 29: r29<= datai; 85 | 30: r30<= datai; 86 | 31: r31<= datai; 87 | endcase 88 | end 89 | end 90 | 91 | assign datao = 92 | (addr == 0) ? r0 : 93 | (addr == 1) ? r1 : 94 | (addr == 2) ? r2 : 95 | (addr == 3) ? r3 : 96 | (addr == 4) ? r4 : 97 | (addr == 5) ? r5 : 98 | (addr == 6) ? r6 : 99 | (addr == 7) ? r7 : 100 | (addr == 8) ? r8 : 101 | (addr == 9) ? r9 : 102 | (addr == 10) ? r10 : 103 | (addr == 11) ? r11 : 104 | (addr == 12) ? r12 : 105 | (addr == 13) ? r13 : 106 | (addr == 14) ? r14 : 107 | (addr == 15) ? r15 : 108 | (addr == 16) ? r16 : 109 | (addr == 17) ? r17 : 110 | (addr == 18) ? r18 : 111 | (addr == 19) ? r19 : 112 | (addr == 20) ? r20 : 113 | (addr == 21) ? r21 : 114 | (addr == 22) ? r22 : 115 | (addr == 23) ? r23 : 116 | (addr == 24) ? r24 : 117 | (addr == 25) ? r25 : 118 | (addr == 26) ? r26 : 119 | (addr == 27) ? r27 : 120 | (addr == 28) ? r28 : 121 | (addr == 29) ? r29 : 122 | (addr == 30) ? r30 : 123 | r31; 124 | 125 | 126 | `else 127 | localparam COUNT = (WIDTH + 7) / 8; 128 | 129 | wire [8*COUNT-1:0] xdatao; 130 | assign datao = xdatao[WIDTH-1:0]; 131 | 132 | wire [8*COUNT-1:0] xdatai = datai; 133 | 134 | genvar i; 135 | generate 136 | for (i = 0; i < COUNT; i=i+1) begin: part 137 | 138 | RAM32M #( 139 | .INIT_A(64'h0000000000000000), // Initial contents of A Port 140 | .INIT_B(64'h0000000000000000), // Initial contents of B Port 141 | .INIT_C(64'h0000000000000000), // Initial contents of C Port 142 | .INIT_D(64'h0000000000000000) // Initial contents of D Port 143 | ) RAM32X8SP ( 144 | .DOA(xdatao[8*i+1:8*i+0]), 145 | .DOB(xdatao[8*i+3:8*i+2]), 146 | .DOC(xdatao[8*i+5:8*i+4]), 147 | .DOD(xdatao[8*i+7:8*i+6]), 148 | 149 | .ADDRA(addr), 150 | .ADDRB(addr), 151 | .ADDRC(addr), 152 | .ADDRD(addr), 153 | 154 | .DIA(xdatai[8*i+1:8*i+0]), 155 | .DIB(xdatai[8*i+3:8*i+2]), 156 | .DIC(xdatai[8*i+5:8*i+4]), 157 | .DID(xdatai[8*i+7:8*i+6]), 158 | 159 | .WCLK(wclk), 160 | .WE(we) 161 | ); 162 | 163 | end 164 | endgenerate 165 | 166 | `endif 167 | 168 | 169 | endmodule 170 | -------------------------------------------------------------------------------- /lib/ram/ram32xsdp.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module ram32xsdp #( 7 | parameter WIDTH = 6 8 | )( 9 | input wclk, 10 | input we, 11 | input [4:0] waddr, 12 | input [WIDTH-1:0] datai, 13 | 14 | input [4:0] raddr, 15 | output [WIDTH-1:0] datao 16 | ); 17 | 18 | `ifdef SYM 19 | // Make debug friendly 20 | 21 | reg [WIDTH-1:0] r0; 22 | reg [WIDTH-1:0] r1; 23 | reg [WIDTH-1:0] r2; 24 | reg [WIDTH-1:0] r3; 25 | reg [WIDTH-1:0] r4; 26 | reg [WIDTH-1:0] r5; 27 | reg [WIDTH-1:0] r6; 28 | reg [WIDTH-1:0] r7; 29 | reg [WIDTH-1:0] r8; 30 | reg [WIDTH-1:0] r9; 31 | reg [WIDTH-1:0] r10; 32 | reg [WIDTH-1:0] r11; 33 | reg [WIDTH-1:0] r12; 34 | reg [WIDTH-1:0] r13; 35 | reg [WIDTH-1:0] r14; 36 | reg [WIDTH-1:0] r15; 37 | reg [WIDTH-1:0] r16; 38 | reg [WIDTH-1:0] r17; 39 | reg [WIDTH-1:0] r18; 40 | reg [WIDTH-1:0] r19; 41 | reg [WIDTH-1:0] r20; 42 | reg [WIDTH-1:0] r21; 43 | reg [WIDTH-1:0] r22; 44 | reg [WIDTH-1:0] r23; 45 | reg [WIDTH-1:0] r24; 46 | reg [WIDTH-1:0] r25; 47 | reg [WIDTH-1:0] r26; 48 | reg [WIDTH-1:0] r27; 49 | reg [WIDTH-1:0] r28; 50 | reg [WIDTH-1:0] r29; 51 | reg [WIDTH-1:0] r30; 52 | reg [WIDTH-1:0] r31; 53 | 54 | always @(posedge wclk) begin 55 | if (we) begin 56 | case (waddr) 57 | 0: r0 <= datai; 58 | 1: r1 <= datai; 59 | 2: r2 <= datai; 60 | 3: r3 <= datai; 61 | 4: r4 <= datai; 62 | 5: r5 <= datai; 63 | 6: r6 <= datai; 64 | 7: r7 <= datai; 65 | 8: r8 <= datai; 66 | 9: r9 <= datai; 67 | 10: r10<= datai; 68 | 11: r11<= datai; 69 | 12: r12<= datai; 70 | 13: r13<= datai; 71 | 14: r14<= datai; 72 | 15: r15<= datai; 73 | 16: r16<= datai; 74 | 17: r17<= datai; 75 | 18: r18<= datai; 76 | 19: r19<= datai; 77 | 20: r20<= datai; 78 | 21: r21<= datai; 79 | 22: r22<= datai; 80 | 23: r23<= datai; 81 | 24: r24<= datai; 82 | 25: r25<= datai; 83 | 26: r26<= datai; 84 | 27: r27<= datai; 85 | 28: r28<= datai; 86 | 29: r29<= datai; 87 | 30: r30<= datai; 88 | 31: r31<= datai; 89 | endcase 90 | end 91 | end 92 | 93 | assign datao = 94 | (raddr == 0) ? r0 : 95 | (raddr == 1) ? r1 : 96 | (raddr == 2) ? r2 : 97 | (raddr == 3) ? r3 : 98 | (raddr == 4) ? r4 : 99 | (raddr == 5) ? r5 : 100 | (raddr == 6) ? r6 : 101 | (raddr == 7) ? r7 : 102 | (raddr == 8) ? r8 : 103 | (raddr == 9) ? r9 : 104 | (raddr == 10) ? r10 : 105 | (raddr == 11) ? r11 : 106 | (raddr == 12) ? r12 : 107 | (raddr == 13) ? r13 : 108 | (raddr == 14) ? r14 : 109 | (raddr == 15) ? r15 : 110 | (raddr == 16) ? r16 : 111 | (raddr == 17) ? r17 : 112 | (raddr == 18) ? r18 : 113 | (raddr == 19) ? r19 : 114 | (raddr == 20) ? r20 : 115 | (raddr == 21) ? r21 : 116 | (raddr == 22) ? r22 : 117 | (raddr == 23) ? r23 : 118 | (raddr == 24) ? r24 : 119 | (raddr == 25) ? r25 : 120 | (raddr == 26) ? r26 : 121 | (raddr == 27) ? r27 : 122 | (raddr == 28) ? r28 : 123 | (raddr == 29) ? r29 : 124 | (raddr == 30) ? r30 : 125 | r31; 126 | 127 | `else 128 | localparam COUNT = (WIDTH + 5) / 6; 129 | 130 | wire [6*COUNT-1:0] xdatao; 131 | assign datao = xdatao[WIDTH-1:0]; 132 | 133 | wire [6*COUNT-1:0] xdatai = datai; 134 | 135 | genvar i; 136 | generate 137 | for (i = 0; i < COUNT; i=i+1) begin: part 138 | 139 | RAM32M #( 140 | .INIT_A(64'h0000000000000000), // Initial contents of A Port 141 | .INIT_B(64'h0000000000000000), // Initial contents of B Port 142 | .INIT_C(64'h0000000000000000), // Initial contents of C Port 143 | .INIT_D(64'h0000000000000000) // Initial contents of D Port 144 | ) RAM32X6SDP ( 145 | .DOA(xdatao[6*i+1:6*i+0]), 146 | .DOB(xdatao[6*i+3:6*i+2]), 147 | .DOC(xdatao[6*i+5:6*i+4]), 148 | .DOD(), 149 | 150 | .ADDRA(raddr), 151 | .ADDRB(raddr), 152 | .ADDRC(raddr), 153 | .ADDRD(waddr), 154 | 155 | .DIA(xdatai[6*i+1:6*i+0]), 156 | .DIB(xdatai[6*i+3:6*i+2]), 157 | .DIC(xdatai[6*i+5:6*i+4]), 158 | .DID(2'b0), 159 | 160 | .WCLK(wclk), 161 | .WE(we) 162 | ); 163 | 164 | end 165 | endgenerate 166 | `endif 167 | 168 | 169 | endmodule 170 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Solderpad Hardware License v2.1 2 | 3 | This license operates as a wraparound license to the Apache License Version 2.0 4 | (the “Apache License”) and incorporates the terms and conditions of the Apache 5 | License (which can be found here: http://apache.org/licenses/LICENSE-2.0), with 6 | the following additions and modifications. It must be read in conjunction with 7 | the Apache License. Section 1 below modifies definitions and terminology in the 8 | Apache License and Section 2 below replaces Section 2 of the Apache License. The 9 | Appendix replaces the Appendix in the Apache License. You may, at your option, 10 | choose to treat any Work released under this license as released under the 11 | Apache License (thus ignoring all sections written below entirely). 12 | 13 | 1. Terminology in the Apache License is supplemented or modified as follows: 14 | 15 | “Authorship”: any reference to ‘authorship’ shall be taken to read “authorship 16 | or design”. 17 | 18 | “Copyright owner”: any reference to ‘copyright owner’ shall be taken to read 19 | “Rights owner”. 20 | 21 | “Copyright statement”: the reference to ‘copyright statement’ shall be taken to 22 | read ‘copyright or other statement pertaining to Rights’. 23 | 24 | The following new definition shall be added to the Definitions section of the 25 | Apache License: 26 | 27 | “Rights” means copyright and any similar right including design right (whether 28 | registered or unregistered), rights in semiconductor topographies (mask works) 29 | and database rights (but excluding Patents and Trademarks). 30 | 31 | The following definitions shall replace the corresponding definitions in the 32 | Apache License: 33 | 34 | “License” shall mean this Solderpad Hardware License version 2.1, being the 35 | terms and conditions for use, manufacture, instantiation, adaptation, 36 | reproduction, and distribution as defined by Sections 1 through 9 of this 37 | document. 38 | 39 | “Licensor” shall mean the owner of the Rights or entity authorized by the owner 40 | of the Rights that is granting the License. 41 | 42 | “Derivative Works” shall mean any work, whether in Source or Object form, that 43 | is based on (or derived from) the Work and for which the editorial revisions, 44 | annotations, elaborations, or other modifications represent, as a whole, an 45 | original work of authorship or design. For the purposes of this License, 46 | Derivative Works shall not include works that remain reversibly separable from, 47 | or merely link (or bind by name) or physically connect to or interoperate with 48 | the Work and Derivative Works thereof. 49 | 50 | “Object” form shall mean any form resulting from mechanical transformation or 51 | translation of a Source form or the application of a Source form to physical 52 | material, including but not limited to compiled object code, generated 53 | documentation, the instantiation of a hardware design or physical object or 54 | material and conversions to other media types, including intermediate forms such 55 | as bytecodes, FPGA bitstreams, moulds, artwork and semiconductor topographies 56 | (mask works). 57 | 58 | “Source” form shall mean the preferred form for making modifications, including 59 | but not limited to source code, net lists, board layouts, CAD files, 60 | documentation source, and configuration files. 61 | 62 | “Work” shall mean the work of authorship or design, whether in Source or Object 63 | form, made available under the License, as indicated by a notice relating to 64 | Rights that is included in or attached to the work (an example is provided in 65 | the Appendix below). 66 | 67 | 2. Grant of License. Subject to the terms and conditions of this License, each 68 | Contributor hereby grants to You a perpetual, worldwide, non-exclusive, 69 | no-charge, royalty-free, irrevocable license under the Rights to reproduce, 70 | prepare Derivative Works of, make, adapt, repair, publicly display, publicly 71 | perform, sublicense, and distribute the Work and such Derivative Works in Source 72 | or Object form and do anything in relation to the Work as if the Rights did not 73 | exist. 74 | 75 | APPENDIX 76 | 77 | Copyright 2022 Fairwaves Inc. 78 | SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 79 | 80 | Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not 81 | use this file except in compliance with the License, or, at your option, the 82 | Apache License version 2.0. You may obtain a copy of the License at 83 | 84 | https://solderpad.org/licenses/SHL-2.1/ 85 | 86 | Unless required by applicable law or agreed to in writing, any work distributed 87 | under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR 88 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 89 | specific language governing permissions and limitations under the License. 90 | -------------------------------------------------------------------------------- /lib/fifo/ul_router4_wr.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module ul_router4_wr #( 7 | parameter ADDR_WIDTH = 10, 8 | parameter DATA_WIDTH = 32 9 | ) ( 10 | // UL clocks 11 | input s_ul_clk, 12 | input s_ul_aresetn, 13 | 14 | // UL Write channel 0 15 | input [ADDR_WIDTH - 1:0] s0_ul_waddr, 16 | input [DATA_WIDTH - 1:0] s0_ul_wdata, 17 | input s0_ul_wvalid, 18 | output s0_ul_wready, 19 | 20 | // UL Write channel 1 21 | input [ADDR_WIDTH - 1:0] s1_ul_waddr, 22 | input [DATA_WIDTH - 1:0] s1_ul_wdata, 23 | input s1_ul_wvalid, 24 | output s1_ul_wready, 25 | 26 | // UL Write channel 1 27 | input [ADDR_WIDTH - 1:0] s2_ul_waddr, 28 | input [DATA_WIDTH - 1:0] s2_ul_wdata, 29 | input s2_ul_wvalid, 30 | output s2_ul_wready, 31 | 32 | // UL Write channel 1 33 | input [ADDR_WIDTH - 1:0] s3_ul_waddr, 34 | input [DATA_WIDTH - 1:0] s3_ul_wdata, 35 | input s3_ul_wvalid, 36 | output s3_ul_wready, 37 | 38 | //////////////////////////////////////////// 39 | //Mux0 40 | // UL Write channel 41 | output [ADDR_WIDTH - 3:0] m0_ul_waddr, 42 | output [DATA_WIDTH - 1:0] m0_ul_wdata, 43 | output m0_ul_wvalid, 44 | input m0_ul_wready, 45 | 46 | //////////////////////////////////////////// 47 | //Mux1 48 | // UL Write channel 49 | output [ADDR_WIDTH - 3:0] m1_ul_waddr, 50 | output [DATA_WIDTH - 1:0] m1_ul_wdata, 51 | output m1_ul_wvalid, 52 | input m1_ul_wready, 53 | 54 | //////////////////////////////////////////// 55 | //Mux2 56 | // UL Write channel 57 | output [ADDR_WIDTH - 3:0] m2_ul_waddr, 58 | output [DATA_WIDTH - 1:0] m2_ul_wdata, 59 | output m2_ul_wvalid, 60 | input m2_ul_wready, 61 | 62 | //////////////////////////////////////////// 63 | //Mux3 64 | // UL Write channel 65 | output [ADDR_WIDTH - 3:0] m3_ul_waddr, 66 | output [DATA_WIDTH - 1:0] m3_ul_wdata, 67 | output m3_ul_wvalid, 68 | input m3_ul_wready 69 | ); 70 | 71 | reg [ADDR_WIDTH - 1:0] s_ul_waddr; 72 | reg [DATA_WIDTH - 1:0] s_ul_wdata; 73 | reg s_ul_wvalid; 74 | wire s_ul_wready; 75 | 76 | assign s0_ul_wready = (~s_ul_wvalid || s_ul_wready); 77 | assign s1_ul_wready = (~s_ul_wvalid || s_ul_wready) && ~s0_ul_wvalid; 78 | assign s2_ul_wready = (~s_ul_wvalid || s_ul_wready) && ~s0_ul_wvalid && ~s1_ul_wvalid; 79 | assign s3_ul_wready = (~s_ul_wvalid || s_ul_wready) && ~s0_ul_wvalid && ~s1_ul_wvalid && ~s2_ul_wvalid; 80 | 81 | always @(posedge s_ul_clk) begin 82 | if (~s_ul_aresetn) begin 83 | s_ul_wvalid <= 1'b0; 84 | end else begin 85 | if (s0_ul_wvalid && s0_ul_wready) begin 86 | s_ul_waddr <= s0_ul_waddr; 87 | s_ul_wdata <= s0_ul_wdata; 88 | s_ul_wvalid <= 1'b1; 89 | end else if (s1_ul_wvalid && s1_ul_wready) begin 90 | s_ul_waddr <= s1_ul_waddr; 91 | s_ul_wdata <= s1_ul_wdata; 92 | s_ul_wvalid <= 1'b1; 93 | end else if (s2_ul_wvalid && s2_ul_wready) begin 94 | s_ul_waddr <= s2_ul_waddr; 95 | s_ul_wdata <= s2_ul_wdata; 96 | s_ul_wvalid <= 1'b1; 97 | end else if (s3_ul_wvalid && s3_ul_wready) begin 98 | s_ul_waddr <= s3_ul_waddr; 99 | s_ul_wdata <= s3_ul_wdata; 100 | s_ul_wvalid <= 1'b1; 101 | end else if (s_ul_wvalid && s_ul_wready) begin 102 | s_ul_wvalid <= 1'b0; 103 | end 104 | end 105 | end 106 | 107 | 108 | wire [1:0] wselector = s_ul_waddr[ADDR_WIDTH - 1:ADDR_WIDTH - 2]; 109 | 110 | assign m0_ul_waddr = s_ul_waddr[ADDR_WIDTH - 3:0]; 111 | assign m1_ul_waddr = s_ul_waddr[ADDR_WIDTH - 3:0]; 112 | assign m2_ul_waddr = s_ul_waddr[ADDR_WIDTH - 3:0]; 113 | assign m3_ul_waddr = s_ul_waddr[ADDR_WIDTH - 3:0]; 114 | 115 | assign m0_ul_wdata = s_ul_wdata; 116 | assign m1_ul_wdata = s_ul_wdata; 117 | assign m2_ul_wdata = s_ul_wdata; 118 | assign m3_ul_wdata = s_ul_wdata; 119 | 120 | assign s_ul_wready = (wselector == 2'b00) ? m0_ul_wready : 121 | (wselector == 2'b01) ? m1_ul_wready : 122 | (wselector == 2'b10) ? m2_ul_wready : 123 | m3_ul_wready; 124 | 125 | assign m0_ul_wvalid = s_ul_wvalid && (wselector == 2'b00); 126 | assign m1_ul_wvalid = s_ul_wvalid && (wselector == 2'b01); 127 | assign m2_ul_wvalid = s_ul_wvalid && (wselector == 2'b10); 128 | assign m3_ul_wvalid = s_ul_wvalid && (wselector == 2'b11); 129 | 130 | 131 | endmodule 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /lib/uart/uart_smartcard.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | // Half duplex UART 6 | // 7 | 8 | module uart_smartcard #( 9 | parameter CLK_DIV = 372, 10 | parameter BITS_SAMPLE = 3, 11 | parameter CLK_DIV_BITS = 12, 12 | parameter PARITY_ODD = 0 13 | )( 14 | input reset, 15 | input baseclk, 16 | 17 | input rxd, 18 | output txd_oen, 19 | 20 | input [7:0] tx_data, 21 | input tx_valid, 22 | output tx_ready, 23 | 24 | output [7:0] rx_data, 25 | output rx_valid, 26 | input rx_ready, 27 | 28 | output parity_error 29 | ); 30 | 31 | // 32 | // SMART CARD UART FORMAT 33 | // 1 START 34 | // 8 DATA 35 | // 1 PARITY 36 | // 2 STOP (with ACK/NACK and retransmition) 37 | // 38 | // Total 12 bits per byte 39 | 40 | (* ASYNC_REG = "TRUE" *) reg [BITS_SAMPLE - 1:0] rxd_sampled; 41 | always @(posedge baseclk) begin 42 | if (reset) begin 43 | rxd_sampled <= ((1 << BITS_SAMPLE) - 1); 44 | end else begin 45 | rxd_sampled <= { rxd_sampled[BITS_SAMPLE - 2:0], rxd }; 46 | end 47 | end 48 | 49 | wire sampled_one = (rxd_sampled == ((1 << BITS_SAMPLE) - 1)); 50 | wire sampled_zero = (rxd_sampled == 0); 51 | 52 | reg parity; // Parity bit calculation 53 | 54 | localparam MODE_IDLE = 2'b00; 55 | localparam MODE_TX = 2'b01; 56 | localparam MODE_RX = 2'b11; 57 | 58 | reg [1:0] mode; // Half-duplex direction 59 | 60 | reg [CLK_DIV_BITS - 1:0] clk_div; 61 | 62 | reg [7:0] retransmition_byte; // Retransmit byte 63 | reg [8:0] tx_byte; 64 | reg [7:0] rx_byte; // Byte received 65 | 66 | reg [4:0] bit_count; // Bit count during serialization 67 | 68 | reg rx_valid_reg; 69 | 70 | reg par_err; 71 | 72 | assign tx_ready = (mode == MODE_IDLE); 73 | assign txd_oen = tx_byte[0]; 74 | 75 | assign rx_data = rx_byte; 76 | assign rx_valid = rx_valid_reg; 77 | 78 | assign parity_error = par_err; 79 | 80 | // TODO byte retransmition 81 | 82 | wire tx_edge = (bit_count[0] == 1); 83 | wire rx_edge = (bit_count[0] == 0); 84 | 85 | //////////////// 86 | // LHHL LLL LLH sets up the inverse convention: state L encodes value 1 and moment 2 conveys the 87 | // most significant bit (msb first). When decoded by inverse convention, the conveyed byte is equal to '3F'. 88 | // 89 | // LHHL HHH LLH sets up the direct convention: state H encodes value 1 and moment 2 conveys the 90 | // least significant bit (lsb first). When decoded by direct convention, the conveyed byte is equal to '3B'. 91 | 92 | 93 | always @(posedge baseclk) begin 94 | if (reset) begin 95 | mode <= MODE_IDLE; 96 | tx_byte[0] <= 1'b1; 97 | rx_valid_reg <= 1'b0; 98 | end else begin 99 | if (mode == MODE_IDLE) begin 100 | if (tx_valid) begin 101 | mode <= MODE_TX; 102 | tx_byte <= { tx_data, 1'b0 }; 103 | end else if (sampled_zero) begin 104 | rx_valid_reg <= 1'b0; 105 | mode <= MODE_RX; 106 | par_err <= 0; 107 | end 108 | 109 | bit_count <= 0; 110 | clk_div <= 0; 111 | parity <= PARITY_ODD; 112 | 113 | end else begin 114 | if (clk_div == ((CLK_DIV/2) - 1)) begin 115 | 116 | if (mode == MODE_TX) begin 117 | if (tx_edge && bit_count[4:1] < 8) begin 118 | tx_byte[7:0] <= tx_byte[8:1]; 119 | parity <= parity ^ tx_byte[1]; 120 | end else if (tx_edge && bit_count[4:1] == 8) begin 121 | tx_byte[0] <= parity; 122 | end else if (tx_edge && bit_count[4:1] == 9) begin 123 | tx_byte[0] <= 1'b1; 124 | end else if (tx_edge && bit_count[4:1] == 10) begin 125 | par_err <= sampled_zero; 126 | end else if (tx_edge && ~par_err && bit_count[4:1] == 11) begin 127 | mode <= MODE_IDLE; 128 | end else if (tx_edge /* && par_err && bit_count[4:1] == 13 */) begin 129 | // TODO: retransmition 130 | mode <= MODE_IDLE; 131 | end 132 | end else if (mode == MODE_RX) begin 133 | if (rx_edge && (bit_count[4:1] < 9)) begin 134 | rx_byte <= { sampled_one, rx_byte[7:1] }; 135 | parity <= parity ^ sampled_one; 136 | end else if (rx_edge && (bit_count[4:1] == 9)) begin 137 | if (parity != sampled_one) begin 138 | // TODO: parity error notification 139 | par_err <= 1'b1; 140 | end 141 | rx_valid_reg <= 1'b1; 142 | end else if (rx_edge && (bit_count[4:1] == 11)) begin 143 | mode <= MODE_IDLE; 144 | end 145 | end 146 | 147 | bit_count <= bit_count + 1; 148 | clk_div <= 0; 149 | end else if (mode != MODE_IDLE) begin 150 | clk_div <= clk_div + 1; 151 | end 152 | end 153 | 154 | if (rx_valid_reg && rx_ready) begin 155 | rx_valid_reg <= 1'b0; 156 | end 157 | end 158 | end 159 | 160 | 161 | endmodule 162 | -------------------------------------------------------------------------------- /lib/lms7/fe_rx_chain_brst.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module fe_rx_chain_brst #( 7 | parameter BUFFER_SIZE_BITS = 13, 8 | parameter TS_BITS = 30, 9 | parameter DIAG_BITS = 20 10 | )( 11 | // LMS7 12 | input rx_clk, 13 | input [11:0] sdr_ai, 14 | input [11:0] sdr_aq, 15 | input [11:0] sdr_bi, 16 | input [11:0] sdr_bq, 17 | input sdr_valid, 18 | output o_sdr_enable, 19 | 20 | // TS for timed commands 21 | output [TS_BITS-1:0] ts_current, 22 | 23 | // TS 24 | input ts_command_valid, 25 | output ts_command_ready, 26 | 27 | output rx_running, 28 | 29 | // FE CTRL 30 | input rxfe_ctrl_clk, 31 | 32 | output [2:0] rxfe_bufpos, 33 | output rxfe_resume, 34 | input [7:0] rxfe_ctrl, 35 | 36 | // RAM FIFO Interface 37 | output rxfe_rxdma_ten, 38 | output [BUFFER_SIZE_BITS-1:0] rxfe_rxdma_taddr, 39 | output [63:0] rxfe_rxdma_tdata_wr, 40 | 41 | input [31:0] rxfe_cmd_data, 42 | input rxfe_cmd_valid, 43 | output rxfe_cmd_ready, 44 | 45 | // Timestamp report in another clock domain 46 | output [31:0] cc_ts_current 47 | ); 48 | 49 | wire s_ul_clk = rxfe_ctrl_clk; 50 | 51 | wire [1:0] dma_decim_rate = rxfe_ctrl[1:0]; 52 | wire [1:0] dma_fmt = rxfe_ctrl[3:2]; 53 | wire dma_siso_mode = rxfe_ctrl[4]; 54 | wire dma_enable = rxfe_ctrl[5]; 55 | wire frm_rst = rxfe_ctrl[6]; 56 | wire dma_stall = rxfe_ctrl[7]; 57 | 58 | 59 | wire [63:0] axis_lms7_buff_tdata; 60 | wire axis_lms7_buff_tvalid; 61 | wire axis_lms7_buff_tlast; 62 | 63 | 64 | wire frm_enable; 65 | wire frm_stall; 66 | 67 | 68 | sync_reg #(.ASYNC_RESET(1)) sync_reg_en_to_frm ( 69 | .clk(rx_clk), 70 | .rst(frm_rst), 71 | .in(dma_enable), 72 | .out(frm_enable) 73 | ); 74 | 75 | sync_reg sync_reg_stall_to_frm ( 76 | .clk(rx_clk), 77 | .rst(frm_rst), 78 | .in(dma_stall), 79 | .out(frm_stall) 80 | ); 81 | 82 | assign rx_running = frm_enable; 83 | 84 | reg frm_resume_cmd_triggered; 85 | 86 | sync_reg sync_reg_to_ul ( 87 | .clk(s_ul_clk), 88 | .rst(~dma_enable), 89 | 90 | .in(frm_resume_cmd_triggered), 91 | .out(rxfe_resume) 92 | ); 93 | 94 | assign ts_command_ready = 1'b1; 95 | 96 | always @(posedge rx_clk or posedge frm_rst) begin 97 | if (frm_rst) begin 98 | frm_resume_cmd_triggered <= 0; 99 | end else begin 100 | if (ts_command_valid && ts_command_ready) begin 101 | if (frm_stall) begin 102 | frm_resume_cmd_triggered <= 1'b1; 103 | end 104 | end else begin 105 | if (frm_resume_cmd_triggered && ~frm_stall) begin 106 | frm_resume_cmd_triggered <= 1'b0; 107 | end 108 | end 109 | end 110 | end 111 | 112 | assign o_sdr_enable = dma_enable; //fe_enable; 113 | 114 | wire fe_cmd_valid_cc; 115 | wire fe_cmd_ready_cc; 116 | 117 | axis_cc_flow_ctrl axis_cc_flow_ctrl( 118 | .s_axis_clk(s_ul_clk), 119 | .s_aresetn(dma_enable), 120 | .s_axis_valid(rxfe_cmd_valid), 121 | .s_axis_ready(rxfe_cmd_ready), 122 | 123 | .m_axis_clk(rx_clk), 124 | .m_aresetn(frm_enable), 125 | .m_axis_valid(fe_cmd_valid_cc), 126 | .m_axis_ready(fe_cmd_ready_cc) 127 | ); 128 | 129 | lms7_rx_frm_brst lms7_rx_frm_brst( 130 | .fe_reset(~frm_enable), 131 | 132 | // AXI 133 | .axis_tx_tdata(axis_lms7_buff_tdata), 134 | .axis_tx_tvalid(axis_lms7_buff_tvalid), 135 | .axis_tx_tlast(axis_lms7_buff_tlast), 136 | .axis_tx_tkeep(), 137 | 138 | .ts_current(ts_current), 139 | 140 | .in_sdr_ai(sdr_ai), 141 | .in_sdr_aq(sdr_aq), 142 | .in_sdr_bi(sdr_bi), 143 | .in_sdr_bq(sdr_bq), 144 | .in_sdr_valid(sdr_valid), 145 | .in_sdr_clk(rx_clk), 146 | 147 | .in_mode_siso(dma_siso_mode), 148 | .in_fmt(dma_fmt), 149 | .decim_rate(dma_decim_rate), 150 | 151 | .fe_cmd_data(rxfe_cmd_data), 152 | .fe_cmd_valid(fe_cmd_valid_cc), 153 | .fe_cmd_ready(fe_cmd_ready_cc), 154 | 155 | .cc_rst(~dma_enable), 156 | .cc_clk(s_ul_clk), 157 | .cc_ts_current(cc_ts_current) 158 | ); 159 | 160 | localparam GRAY_BITS = 3; 161 | wire [GRAY_BITS:1] wr_addr_aclk; 162 | wire [BUFFER_SIZE_BITS-1:0] wr_addr_rxclk; 163 | assign rxfe_bufpos = wr_addr_aclk[GRAY_BITS:1]; 164 | 165 | cross_counter #( 166 | .WIDTH( BUFFER_SIZE_BITS ), 167 | .GRAY_BITS(GRAY_BITS + 1), 168 | .OUT_WIDTH(GRAY_BITS + 1), 169 | .OUT_LOWER_SKIP(1) 170 | ) cntr ( 171 | .inrst(~frm_enable), 172 | .inclk(rx_clk), 173 | .incmdvalid(axis_lms7_buff_tvalid), 174 | .incmdinc(1'b1), 175 | .incnt(wr_addr_rxclk), 176 | 177 | .outrst(~dma_enable), 178 | .outclk(s_ul_clk), 179 | .outcnt(wr_addr_aclk) 180 | ); 181 | 182 | assign rxfe_rxdma_taddr = wr_addr_rxclk; 183 | assign rxfe_rxdma_tdata_wr = axis_lms7_buff_tdata; 184 | assign rxfe_rxdma_ten = axis_lms7_buff_tvalid; 185 | 186 | 187 | endmodule 188 | 189 | -------------------------------------------------------------------------------- /lib/xtrx/ul_drp_cfg.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module ul_drp_cfg #( 7 | parameter PORTS = 4, 8 | parameter GPIO_RESET_P0 = 0, 9 | parameter GPIO_RESET_P1 = 0, 10 | parameter GPIO_RESET_P2 = 0, 11 | parameter GPIO_RESET_P3 = 0 12 | )( 13 | input reset, 14 | input axis_clk, 15 | 16 | input [31:0] axis_in_data, 17 | input axis_in_valid, 18 | output axis_in_ready, 19 | 20 | output [31:0] axis_out_data, 21 | output axis_out_valid, 22 | input axis_out_ready, 23 | 24 | 25 | output drp_clk, 26 | 27 | // DRP port0 28 | output [15:0] drp_di_0, 29 | output [6:0] drp_daddr_0, 30 | output drp_den_0, 31 | output drp_dwe_0, 32 | input [15:0] drp_do_0, 33 | input drp_drdy_0, 34 | 35 | output [3:0] drp_gpio_out_0, 36 | input [3:0] drp_gpio_in_0, 37 | 38 | // DRP port1 39 | output [15:0] drp_di_1, 40 | output [6:0] drp_daddr_1, 41 | output drp_den_1, 42 | output drp_dwe_1, 43 | input [15:0] drp_do_1, 44 | input drp_drdy_1, 45 | 46 | output [3:0] drp_gpio_out_1, 47 | input [3:0] drp_gpio_in_1, 48 | 49 | // DRP port2 50 | output [15:0] drp_di_2, 51 | output [6:0] drp_daddr_2, 52 | output drp_den_2, 53 | output drp_dwe_2, 54 | input [15:0] drp_do_2, 55 | input drp_drdy_2, 56 | 57 | output [3:0] drp_gpio_out_2, 58 | input [3:0] drp_gpio_in_2, 59 | 60 | // DRP port3 61 | output [15:0] drp_di_3, 62 | output [6:0] drp_daddr_3, 63 | output drp_den_3, 64 | output drp_dwe_3, 65 | input [15:0] drp_do_3, 66 | input drp_drdy_3, 67 | 68 | output [3:0] drp_gpio_out_3, 69 | input [3:0] drp_gpio_in_3 70 | ); 71 | 72 | `include "xtrxll_regs.vh" 73 | 74 | reg [1:0] drp_selector; 75 | 76 | reg [15:0] drp_di; 77 | reg [6:0] drp_daddr; 78 | reg drp_dwe; 79 | reg [3:0] drp_den; 80 | 81 | assign drp_di_0 = drp_di; 82 | assign drp_di_1 = drp_di; 83 | assign drp_di_2 = drp_di; 84 | assign drp_di_3 = drp_di; 85 | 86 | assign drp_daddr_0 = drp_daddr; 87 | assign drp_daddr_1 = drp_daddr; 88 | assign drp_daddr_2 = drp_daddr; 89 | assign drp_daddr_3 = drp_daddr; 90 | 91 | assign drp_dwe_0 = drp_dwe; 92 | assign drp_dwe_1 = drp_dwe; 93 | assign drp_dwe_2 = drp_dwe; 94 | assign drp_dwe_3 = drp_dwe; 95 | 96 | assign drp_den_0 = drp_den[0]; 97 | assign drp_den_1 = drp_den[1]; 98 | assign drp_den_2 = drp_den[2]; 99 | assign drp_den_3 = drp_den[3]; 100 | 101 | assign drp_clk = axis_clk; 102 | 103 | wire [15:0] drp_do = (drp_selector == 2'b00) ? drp_do_0 : 104 | (drp_selector == 2'b01) ? drp_do_1 : 105 | (drp_selector == 2'b10) ? drp_do_2 : drp_do_3; 106 | wire drp_drdy = (drp_selector == 2'b00) ? drp_drdy_0 : 107 | (drp_selector == 2'b01) ? drp_drdy_1 : 108 | (drp_selector == 2'b10) ? drp_drdy_2 : drp_drdy_3; 109 | 110 | 111 | 112 | wire [15:0] di = axis_in_data[15:0]; 113 | wire [6:0] daddr = axis_in_data[GP_PORT_DRP_ADDR_BITS - 1 + GP_PORT_DRP_ADDR_OFF:GP_PORT_DRP_ADDR_OFF]; 114 | wire cmd_regacc = axis_in_data[GP_PORT_DRP_REGEN]; 115 | wire cmd_regacc_wr= axis_in_data[GP_PORT_DRP_REGWR]; 116 | wire [3:0] c_gpio = axis_in_data[4 - 1 + GP_PORT_DRP_GPIO_OFF:GP_PORT_DRP_GPIO_OFF]; 117 | 118 | // 29 is reservd for future port extention 119 | wire [1:0] sel = axis_in_data[31:30]; 120 | 121 | 122 | assign axis_out_valid = 1'b1; 123 | 124 | assign axis_out_data[15:0] = drp_do; 125 | 126 | assign axis_out_data[19:16] = drp_gpio_in_0; 127 | assign axis_out_data[23:20] = drp_gpio_in_1; 128 | assign axis_out_data[27:24] = drp_gpio_in_2; 129 | assign axis_out_data[31:28] = drp_gpio_in_3; 130 | 131 | reg [3:0] gpio_out_0; 132 | reg [3:0] gpio_out_1; 133 | reg [3:0] gpio_out_2; 134 | reg [3:0] gpio_out_3; 135 | 136 | assign drp_gpio_out_0 = gpio_out_0; 137 | assign drp_gpio_out_1 = gpio_out_1; 138 | assign drp_gpio_out_2 = gpio_out_2; 139 | assign drp_gpio_out_3 = gpio_out_3; 140 | 141 | 142 | reg state_rdy; 143 | assign axis_in_ready = state_rdy; //1'b1; 144 | 145 | always @(posedge axis_clk) begin 146 | if (reset) begin 147 | gpio_out_0 <= GPIO_RESET_P0; 148 | gpio_out_1 <= GPIO_RESET_P1; 149 | gpio_out_2 <= GPIO_RESET_P2; 150 | gpio_out_3 <= GPIO_RESET_P3; 151 | 152 | drp_den <= 4'b0; 153 | drp_dwe <= 1'b0; 154 | 155 | state_rdy <= 1'b1; 156 | 157 | drp_di <= 0; 158 | drp_daddr <= 0; 159 | end else begin 160 | if (axis_in_valid && axis_in_ready && ~cmd_regacc) begin 161 | case (sel) 162 | 2'b00: gpio_out_0 <= c_gpio; 163 | 2'b01: gpio_out_1 <= c_gpio; 164 | 2'b10: gpio_out_2 <= c_gpio; 165 | 2'b11: gpio_out_3 <= c_gpio; 166 | endcase 167 | drp_selector <= sel; 168 | 169 | drp_den <= 4'b0; 170 | //drp_dwe <= 1'b0; 171 | state_rdy <= 1'b1; 172 | end else begin 173 | if (axis_in_ready && axis_in_valid) begin 174 | drp_den <= (4'b0001 << sel); 175 | drp_dwe <= cmd_regacc_wr; 176 | drp_di <= di; 177 | drp_daddr <= daddr; 178 | state_rdy <= 1'b0; 179 | drp_selector <= sel; 180 | end else begin 181 | if (~state_rdy && drp_drdy) begin 182 | state_rdy <= 1'b1; 183 | end 184 | 185 | if (|drp_den) begin 186 | drp_den <= 4'b0; 187 | //drp_dwe <= 1'b0; 188 | end 189 | end 190 | end 191 | end 192 | end 193 | 194 | 195 | 196 | endmodule 197 | -------------------------------------------------------------------------------- /lib/pcie/int_router.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module int_router #( 7 | parameter COUNT = 16, 8 | parameter DELAY_CYCLE = 0 9 | ) ( 10 | input clk, 11 | input reset, 12 | 13 | // PCI-e interface 14 | input interrupt_msi_enabled, 15 | input interrupt_rdy, 16 | 17 | output reg interrupt, 18 | output reg interrupt_assert, 19 | output reg [7:0] interrupt_num, 20 | 21 | input legacy_interrupt_disabled, 22 | input [2:0] interrupt_mmenable, 23 | 24 | output [4:0] cap_interrupt_msgnum, 25 | output cap_interrupt_stat, 26 | 27 | // User Interrupt status 28 | input int_stat_ready, 29 | output int_stat_valid, 30 | output [COUNT - 1: 0] int_stat_data, 31 | 32 | // User Interrupt control 33 | output int_ctrl_ready, 34 | input int_ctrl_valid, 35 | input [COUNT - 1: 0] int_ctrl_data, 36 | 37 | 38 | // User Interrupr interfcae 39 | input [COUNT - 1:0] int_valid, 40 | output [COUNT - 1:0] int_ready 41 | ); 42 | assign cap_interrupt_stat = 1'b0; 43 | 44 | reg [COUNT-1:0] int_en; 45 | wire [31:0] int_active = int_valid & int_en; 46 | 47 | 48 | wire [4:0] msi_num_x; 49 | wire msi_num_xval; 50 | 51 | wire [31:0] int_active_r; 52 | genvar i; 53 | generate 54 | for (i = 0; i < 32; i=i+1) begin: rev 55 | assign int_active_r[31-i] = int_active[i]; 56 | end 57 | endgenerate 58 | 59 | clz #(.B_WIDTH(5)) clz_decode ( 60 | .data(int_active_r), 61 | 62 | .count(msi_num_x), 63 | .count_nvalid(msi_num_xval) 64 | ); 65 | wire [4:0] msi_num = /*(msi_num_xval) ? 0 :*/ msi_num_x; 66 | 67 | 68 | wire [36:0] msi_msk_and_cap = 69 | (interrupt_mmenable == 3'b000 && (COUNT > 1)) ? { 5'b00001, 32'hffff_ffff } : 70 | (interrupt_mmenable == 3'b001 && (COUNT > 2)) ? { 5'b00010, 32'hffff_fffe } : 71 | (interrupt_mmenable == 3'b010 && (COUNT > 4)) ? { 5'b00100, 32'hffff_fff8 } : 72 | (interrupt_mmenable == 3'b011 && (COUNT > 8)) ? { 5'b01000, 32'hffff_ff80 } : 73 | (interrupt_mmenable == 3'b100 && (COUNT > 16)) ? { 5'b10000, 32'hffff_8000 } : 74 | { COUNT[4:0], 32'h0000_0000 }; 75 | assign cap_interrupt_msgnum = msi_msk_and_cap[36:32]; 76 | wire [31:0] msi_ready_clean_msk = 77 | (interrupt_msi_enabled) ? msi_msk_and_cap[31:0] : 32'hffff_ffff; 78 | 79 | wire [5:0] msi_num_fit = 80 | (interrupt_mmenable == 3'b000 && (COUNT > 1)) ? 6'b1_00000 : 81 | (interrupt_mmenable == 3'b001 && (COUNT > 2) && (msi_num > 0)) ? 6'b1_00001 : 82 | (interrupt_mmenable == 3'b010 && (COUNT > 4) && (msi_num > 2)) ? 6'b1_00011 : 83 | (interrupt_mmenable == 3'b011 && (COUNT > 8) && (msi_num > 6)) ? 6'b1_00111 : 84 | (interrupt_mmenable == 3'b100 && (COUNT > 16) && (msi_num > 14)) ? 6'b1_01111 : 85 | { 1'b0, msi_num }; 86 | wire [4:0] msi_num_gen = msi_num_fit[4:0]; 87 | wire msi_no_fit = msi_num_fit[5]; 88 | 89 | assign int_ctrl_ready = 1'b1; 90 | always @(posedge clk) begin 91 | if (reset) begin 92 | int_en <= 0; 93 | end else begin 94 | if (int_ctrl_ready && int_ctrl_valid) begin 95 | int_en <= int_ctrl_data; 96 | end 97 | end 98 | end 99 | 100 | reg [COUNT - 1:0] reg_int_ready; 101 | reg [1:0] pcie_int_state; 102 | 103 | assign int_ready = reg_int_ready; 104 | assign int_stat_valid = 1'b1; 105 | assign int_stat_data = int_valid; 106 | 107 | reg assert_halt; 108 | wire int_new_avail = ~assert_halt && (int_active != 0) || assert_halt && (int_active & ~msi_ready_clean_msk != 0); 109 | 110 | localparam PCIE_INT_IDLE = 0; 111 | localparam PCIE_INT_WAIT_USER_ACK = 1; // For legacy PCI interrupts only 112 | localparam PCIE_INT_WAIT_REL_L = 2; // for MSI interrupt covering multi-vector 113 | localparam PCIE_INT_WAIT_REL_H = 3; // for MSI interrupt 114 | 115 | always @(posedge clk) begin 116 | if (reset) begin 117 | pcie_int_state <= PCIE_INT_IDLE; 118 | reg_int_ready <= 0; 119 | interrupt <= 0; 120 | interrupt_assert <= 0; 121 | assert_halt <= 0; 122 | interrupt_num <= 0; 123 | end else begin 124 | if (int_stat_ready && int_stat_valid && (assert_halt || interrupt_assert)) begin 125 | assert_halt <= 1'b0; 126 | reg_int_ready <= int_valid & msi_ready_clean_msk; 127 | end else begin 128 | reg_int_ready <= 0; 129 | end 130 | 131 | case (pcie_int_state) 132 | PCIE_INT_IDLE: begin 133 | if (int_new_avail && (~legacy_interrupt_disabled || interrupt_msi_enabled)) begin 134 | interrupt <= 1'b1; 135 | 136 | if (interrupt_msi_enabled) begin 137 | interrupt_num <= msi_num_gen; 138 | 139 | if (msi_no_fit) begin 140 | pcie_int_state <= PCIE_INT_WAIT_REL_L; 141 | assert_halt <= 1'b1; 142 | end else begin 143 | pcie_int_state <= PCIE_INT_WAIT_REL_H; 144 | end 145 | end else begin 146 | // Legacy interrupt 147 | interrupt_num <= 0; 148 | interrupt_assert <= 1'b1; 149 | pcie_int_state <= PCIE_INT_WAIT_USER_ACK; 150 | end 151 | end 152 | end 153 | 154 | PCIE_INT_WAIT_USER_ACK: begin 155 | if (int_stat_ready && int_stat_valid && (assert_halt || interrupt_assert)) begin 156 | interrupt_assert <= 0; 157 | interrupt <= 1'b1; 158 | end else begin 159 | if (interrupt_rdy) begin 160 | interrupt <= 1'b0; 161 | if (~interrupt_assert) begin 162 | pcie_int_state <= PCIE_INT_IDLE; 163 | end 164 | end 165 | end 166 | end 167 | 168 | PCIE_INT_WAIT_REL_L, PCIE_INT_WAIT_REL_H: begin 169 | if (interrupt_rdy) begin 170 | interrupt <= 1'b0; 171 | if (pcie_int_state == PCIE_INT_WAIT_REL_H) begin 172 | reg_int_ready[interrupt_num] <= 1'b1; 173 | end 174 | end 175 | 176 | if (~interrupt) begin 177 | pcie_int_state <= PCIE_INT_IDLE; 178 | end 179 | end 180 | 181 | endcase 182 | end 183 | end 184 | 185 | 186 | endmodule 187 | -------------------------------------------------------------------------------- /lib/qspi/ul_qspi_mem_async.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module ul_qspi_mem_async #( 7 | parameter MEM_ADDR_BITS = 16, 8 | parameter ASYNC_CLOCKS = 1 9 | )( 10 | input clk, 11 | input reset, 12 | 13 | /////////////////////////////// 14 | // UL 15 | // 16 | ///// qspi excmd 17 | input qspi_excmd_valid, 18 | input [31:0] qspi_excmd_data, 19 | output qspi_excmd_ready, 20 | 21 | ///// qspi cmd 22 | input qspi_cmd_valid, 23 | input [31:0] qspi_cmd_data, 24 | output qspi_cmd_ready, 25 | 26 | ///// qspi debug Rd 27 | output qspi_rd_valid, 28 | output [31:0] qspi_rd_data, 29 | input qspi_rd_ready, 30 | 31 | ///// qspi status 32 | output qspi_stat_valid, 33 | output [31:0] qspi_stat_data, 34 | input qspi_stat_ready, 35 | 36 | ////////////////////////////// 37 | // Buffer memory interface 38 | // 39 | output [MEM_ADDR_BITS - 1:2] mem_addr, 40 | output mem_valid, 41 | output mem_wr, 42 | output [31:0] mem_out_data, 43 | input mem_ready, 44 | 45 | input [31:0] mem_in_data, 46 | input mem_in_valid, 47 | 48 | ////////////////////////////// 49 | input qphy_clk, 50 | input qphy_reset, 51 | 52 | input [3:0] qphy_di, 53 | output [3:0] qphy_do, 54 | output [3:0] qphy_dt, 55 | output qphy_dncs // Crystal select 56 | ); 57 | 58 | 59 | // QSPI if 60 | wire [7:0] flash_cmd_data; 61 | wire flash_cmd_valid; 62 | wire flash_cmd_ready; 63 | wire flash_cmd_tlast; 64 | 65 | wire [7:0] qphy_flash_cmd_data; 66 | wire qphy_flash_cmd_valid; 67 | wire qphy_flash_cmd_ready; 68 | wire qphy_flash_cmd_tlast; 69 | 70 | wire [7:0] flash_in_data; 71 | wire flash_in_valid; 72 | wire flash_in_ready; 73 | wire flash_in_tlast; 74 | 75 | wire [7:0] qphy_flash_out_data; 76 | wire qphy_flash_out_valid; 77 | wire qphy_flash_out_ready; 78 | wire qphy_flash_out_tlast; 79 | 80 | 81 | ul_qspi_mem ul_qspi_mem( 82 | .clk(clk), 83 | .reset(reset), 84 | 85 | /////////////////////////////// 86 | // UL 87 | // 88 | ///// qspi excmd 89 | .qspi_excmd_valid(qspi_excmd_valid), 90 | .qspi_excmd_data(qspi_excmd_data), 91 | .qspi_excmd_ready(qspi_excmd_ready), 92 | 93 | ///// qspi cmd 94 | .qspi_cmd_valid(qspi_cmd_valid), 95 | .qspi_cmd_data(qspi_cmd_data), 96 | .qspi_cmd_ready(qspi_cmd_ready), 97 | 98 | ///// qspi debug Rd 99 | .qspi_rd_valid(qspi_rd_valid), 100 | .qspi_rd_data(qspi_rd_data), 101 | .qspi_rd_ready(qspi_rd_ready), 102 | 103 | ///// qspi status 104 | .qspi_stat_valid(qspi_stat_valid), 105 | .qspi_stat_data(qspi_stat_data), 106 | .qspi_stat_ready(qspi_stat_ready), 107 | 108 | ////////////////////////////// 109 | // Buffer memory interface 110 | // 111 | .mem_addr(mem_addr), 112 | .mem_valid(mem_valid), 113 | .mem_wr(mem_wr), 114 | .mem_out_data(mem_out_data), 115 | .mem_ready(mem_ready), 116 | 117 | .mem_in_data(mem_in_data), 118 | .mem_in_valid(mem_in_valid), 119 | 120 | ////////////////////////////// 121 | // QSPI if 122 | .flash_cmd_data(flash_cmd_data), 123 | .flash_cmd_valid(flash_cmd_valid), 124 | .flash_cmd_ready(flash_cmd_ready), 125 | .flash_cmd_tlast(flash_cmd_tlast), 126 | 127 | .flash_in_data(flash_in_data), 128 | .flash_in_valid(flash_in_valid), 129 | .flash_in_ready(flash_in_ready), 130 | .flash_in_tlast(flash_in_tlast) 131 | ); 132 | 133 | generate 134 | if (ASYNC_CLOCKS != 0) begin 135 | 136 | axis_async_fifo32 #(.WIDTH(9)) async_cmd_q ( 137 | .clkrx(clk), 138 | .rstrx(reset), 139 | 140 | .axis_rx_tdata({flash_cmd_data, flash_cmd_tlast}), 141 | .axis_rx_tvalid(flash_cmd_valid), 142 | .axis_rx_tready(flash_cmd_ready), 143 | 144 | .clktx(qphy_clk), 145 | .rsttx(qphy_reset), 146 | 147 | .axis_tx_tdata({qphy_flash_cmd_data, qphy_flash_cmd_tlast}), 148 | .axis_tx_tvalid(qphy_flash_cmd_valid), 149 | .axis_tx_tready(qphy_flash_cmd_ready) 150 | ); 151 | 152 | axis_async_fifo32 #(.WIDTH(9)) async_rb_q ( 153 | .clkrx(qphy_clk), 154 | .rstrx(qphy_reset), 155 | 156 | .axis_rx_tdata({qphy_flash_out_data, qphy_flash_out_tlast}), 157 | .axis_rx_tvalid(qphy_flash_out_valid), 158 | .axis_rx_tready(qphy_flash_out_ready), 159 | 160 | .clktx(clk), 161 | .rsttx(reset), 162 | 163 | .axis_tx_tdata({flash_in_data, flash_in_tlast}), 164 | .axis_tx_tvalid(flash_in_valid), 165 | .axis_tx_tready(flash_in_ready) 166 | ); 167 | 168 | end else begin 169 | 170 | axis_fifo32 #(.WIDTH(9)) sync_cmd_q ( 171 | .clk(clk), 172 | .axisrst(reset), 173 | 174 | .axis_rx_tdata({flash_cmd_data, flash_cmd_tlast}), 175 | .axis_rx_tvalid(flash_cmd_valid), 176 | .axis_rx_tready(flash_cmd_ready), 177 | 178 | .axis_tx_tdata({qphy_flash_cmd_data, qphy_flash_cmd_tlast}), 179 | .axis_tx_tvalid(qphy_flash_cmd_valid), 180 | .axis_tx_tready(qphy_flash_cmd_ready) 181 | ); 182 | 183 | axis_fifo32 #(.WIDTH(9)) sync_rb_q ( 184 | .clk(qphy_clk), 185 | .axisrst(reset), 186 | 187 | .axis_rx_tdata({qphy_flash_out_data, qphy_flash_out_tlast}), 188 | .axis_rx_tvalid(qphy_flash_out_valid), 189 | .axis_rx_tready(qphy_flash_out_ready), 190 | 191 | .axis_tx_tdata({flash_in_data, flash_in_tlast}), 192 | .axis_tx_tvalid(flash_in_valid), 193 | .axis_tx_tready(flash_in_ready) 194 | ); 195 | 196 | end 197 | endgenerate 198 | 199 | 200 | qspi_flash qspi_flash ( 201 | .clk(qphy_clk), 202 | .reset(qphy_reset), 203 | 204 | // Flash interface 205 | .di(qphy_di), 206 | .do(qphy_do), 207 | .dt(qphy_dt), 208 | .dncs(qphy_dncs), // Crystal select 209 | 210 | // XIP enabled, can sendout ADDR + data 211 | .flash_xip_enabled(), 212 | 213 | // Logical interface 214 | .flash_cmd_data(qphy_flash_cmd_data), 215 | .flash_cmd_valid(qphy_flash_cmd_valid), 216 | .flash_cmd_ready(qphy_flash_cmd_ready), 217 | .flash_cmd_tlast(qphy_flash_cmd_tlast), 218 | 219 | .flash_out_data(qphy_flash_out_data), 220 | .flash_out_valid(qphy_flash_out_valid), 221 | .flash_out_ready(qphy_flash_out_ready), 222 | .flash_out_tlast(qphy_flash_out_tlast) 223 | ); 224 | 225 | endmodule 226 | -------------------------------------------------------------------------------- /lib/pcie/pcie_ram_to_wr.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module pcie_ram_to_wr #( 7 | parameter BUFFER_SIZE_BITS = 17, 8 | parameter BUFFER_BUS_ADDRESS = 32, 9 | parameter MEM_TAG = 1, 10 | parameter BUFFER_BURST_BITS = 5 11 | )( 12 | // UL 13 | input s_ul_clk, 14 | input s_ul_aresetn, 15 | 16 | input ul_lm_rvalid, 17 | output reg ul_lm_rready, 18 | input [BUFFER_SIZE_BITS - 1:3] ul_lm_rlocaddr, 19 | input [BUFFER_BUS_ADDRESS - 1:3] ul_lm_rbusaddr, 20 | input [BUFFER_BURST_BITS - 1:0] ul_lm_rlength, 21 | input [MEM_TAG-1:0] ul_lm_rtag, 22 | // Bus data move confirmation 23 | output reg ul_lm_tvalid, 24 | input ul_lm_tready, 25 | output reg [MEM_TAG-1:0] ul_lm_ttag, 26 | 27 | input [1:0] cfg_pcie_attr, 28 | input [15:0] cfg_pcie_reqid, 29 | 30 | // AXIs PCIe TX 31 | input m_axis_tx_tready, 32 | output reg [63:0] m_axis_tx_tdata, 33 | output reg [7:0] m_axis_tx_tkeep, 34 | output reg m_axis_tx_tlast, 35 | output reg m_axis_tx_tvalid, 36 | 37 | // RAM interface 38 | input [63:0] bram_data_rd, 39 | output reg [BUFFER_SIZE_BITS-1:3]bram_addr, 40 | output bram_en 41 | ); 42 | 43 | wire [63:0] data_to_pcie; 44 | bsswap bs0 (.in(bram_data_rd[31:0]), .out(data_to_pcie[31:0])); 45 | bsswap bs1 (.in(bram_data_rd[63:32]), .out(data_to_pcie[63:32])); 46 | 47 | wire [BUFFER_BURST_BITS:0] ul_lm_rlength_z = ul_lm_rlength + 1; 48 | wire [9:0] pcie_lm_length = { ul_lm_rlength_z, 1'b0 }; 49 | 50 | reg [BUFFER_BURST_BITS:0] pcie_burst_counter; 51 | wire pcie_burst_last = pcie_burst_counter[BUFFER_BURST_BITS]; 52 | 53 | reg pcie_pkt_last; 54 | 55 | reg [1:0] dma_state; 56 | 57 | reg [31:0] tmp_axis_data_wrap; 58 | 59 | 60 | localparam DMA_RAM_LOAD = 0; 61 | localparam DMA_FILL_PCIE_HDR = 1; 62 | localparam DMA_FILL_PCIE_ADDR = 2; 63 | localparam DMA_PCIE_TRANSFER = 3; 64 | 65 | wire in_rd_pipe_valid = (dma_state != DMA_RAM_LOAD) && ~pcie_burst_last; 66 | wire in_rd_pipe_ready; 67 | 68 | wire mem_oready = (dma_state == DMA_FILL_PCIE_ADDR || dma_state == DMA_PCIE_TRANSFER) && m_axis_tx_tready; 69 | 70 | reg mem_ovalid; 71 | assign in_rd_pipe_ready = ~mem_ovalid || mem_oready; 72 | 73 | always @(posedge s_ul_clk) begin 74 | if (~s_ul_aresetn) begin 75 | mem_ovalid <= 1'b0; 76 | end else begin 77 | if ((mem_ovalid && mem_oready) || (~mem_ovalid && in_rd_pipe_valid)) begin 78 | mem_ovalid <= in_rd_pipe_valid; 79 | end 80 | end 81 | end 82 | 83 | assign bram_en = (in_rd_pipe_ready && in_rd_pipe_valid); 84 | 85 | always @(posedge s_ul_clk) begin 86 | if (~s_ul_aresetn) begin 87 | dma_state <= DMA_RAM_LOAD; 88 | m_axis_tx_tvalid <= 1'b0; 89 | 90 | ul_lm_rready <= 1'b0; 91 | ul_lm_tvalid <= 1'b0; 92 | end else begin 93 | 94 | if (m_axis_tx_tready && m_axis_tx_tvalid) begin 95 | m_axis_tx_tvalid <= 1'b0; 96 | end 97 | 98 | if (bram_en) begin 99 | bram_addr <= bram_addr + 1'b1; 100 | pcie_burst_counter <= pcie_burst_counter - 1'b1; 101 | end 102 | 103 | if (ul_lm_rready && ul_lm_rvalid) begin 104 | ul_lm_rready <= 1'b0; 105 | end 106 | 107 | if (ul_lm_tvalid && ul_lm_tready) begin 108 | ul_lm_tvalid <= 1'b0; 109 | end 110 | 111 | case (dma_state) 112 | DMA_RAM_LOAD: begin 113 | if (ul_lm_rvalid && (ul_lm_tready || ~ul_lm_tvalid)) begin 114 | bram_addr <= ul_lm_rlocaddr; 115 | pcie_burst_counter <= { 1'b0, ul_lm_rlength }; 116 | dma_state <= DMA_FILL_PCIE_HDR; 117 | end 118 | end 119 | 120 | DMA_FILL_PCIE_HDR: begin 121 | if ((m_axis_tx_tready || ~m_axis_tx_tvalid)) begin 122 | m_axis_tx_tvalid <= 1'b1; 123 | m_axis_tx_tkeep <= 8'hff; 124 | m_axis_tx_tdata <= { 125 | cfg_pcie_reqid, 126 | 8'b0000_0000, 8'b1111_1111, 127 | 1'b0, 7'b10_00000, 1'b0, 3'b000, 4'b0000, 128 | 1'b0, 1'b0, cfg_pcie_attr, 2'b00, pcie_lm_length }; 129 | 130 | m_axis_tx_tlast <= 1'b0; 131 | pcie_pkt_last <= 1'b0; 132 | dma_state <= DMA_FILL_PCIE_ADDR; 133 | end 134 | end 135 | 136 | DMA_FILL_PCIE_ADDR: begin 137 | if (m_axis_tx_tready) begin 138 | m_axis_tx_tvalid <= 1'b1; 139 | m_axis_tx_tkeep <= (pcie_pkt_last) ? 8'h0f : 8'hff; 140 | m_axis_tx_tdata <= { data_to_pcie[31:0], ul_lm_rbusaddr, 3'b000 }; 141 | m_axis_tx_tlast <= pcie_pkt_last; 142 | 143 | tmp_axis_data_wrap <= data_to_pcie[63:32]; 144 | 145 | pcie_pkt_last <= pcie_burst_last; 146 | if (pcie_burst_last && ~pcie_pkt_last) begin 147 | ul_lm_tvalid <= 1'b1; 148 | end 149 | 150 | dma_state <= DMA_PCIE_TRANSFER; 151 | 152 | ul_lm_rready <= 1'b1; 153 | ul_lm_ttag <= ul_lm_rtag; 154 | end 155 | end 156 | 157 | DMA_PCIE_TRANSFER: begin 158 | if (m_axis_tx_tready) begin 159 | m_axis_tx_tvalid <= 1'b1; 160 | m_axis_tx_tkeep <= (pcie_pkt_last) ? 8'h0f : 8'hff; 161 | m_axis_tx_tdata <= { data_to_pcie[31:0], tmp_axis_data_wrap }; 162 | m_axis_tx_tlast <= pcie_pkt_last; 163 | 164 | tmp_axis_data_wrap <= data_to_pcie[63:32]; 165 | 166 | pcie_pkt_last <= pcie_burst_last; 167 | if (pcie_burst_last && ~pcie_pkt_last) begin 168 | ul_lm_tvalid <= 1'b1; 169 | end 170 | 171 | if (pcie_pkt_last) begin 172 | if (ul_lm_rvalid && (ul_lm_tready || ~ul_lm_tvalid)) begin 173 | bram_addr <= ul_lm_rlocaddr; 174 | pcie_burst_counter <= { 1'b0, ul_lm_rlength }; 175 | dma_state <= DMA_FILL_PCIE_HDR; 176 | end else begin 177 | dma_state <= DMA_RAM_LOAD; 178 | end 179 | end 180 | end 181 | end 182 | endcase 183 | 184 | end 185 | end 186 | 187 | 188 | endmodule 189 | -------------------------------------------------------------------------------- /lib/spi/axis_spi.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | // UL SPI 32bit 6 | // 7 | // Write registers 8 | // read data isn't bufferred ! 9 | // 10 | 11 | module axis_spi #( 12 | parameter DATA_WIDTH = 32, 13 | parameter WR_ONLY = 0, 14 | parameter POL_LO = 0, 15 | parameter SCK_LO = 1, 16 | parameter FIXED_DIV = 2, 17 | parameter HOLD_SEN = 0, 18 | parameter DIV_BITS = 19 | // ( FIXED_DIV < 2 ) ? 1 : 20 | ( FIXED_DIV < 4 ) ? 2 : 21 | ( FIXED_DIV < 8 ) ? 3 : 22 | ( FIXED_DIV < 16 ) ? 4 : 23 | ( FIXED_DIV < 32 ) ? 5 : 24 | ( FIXED_DIV < 64 ) ? 6 : 25 | ( FIXED_DIV < 128 ) ? 7 : 8 26 | )( 27 | // UL clocks 28 | input axis_clk, 29 | input axis_resetn, 30 | 31 | // UL Write channel 32 | input [DATA_WIDTH - 1:0] axis_wdata, 33 | input axis_wvalid, 34 | output reg axis_wready, 35 | 36 | // Output data readback stream 37 | output [DATA_WIDTH - 1:0] axis_rdata, 38 | output axis_rvalid, 39 | input axis_rready, 40 | 41 | // SPI master 42 | output spi_mosi, 43 | input spi_miso, 44 | output reg spi_sclk, 45 | output reg spi_sen, 46 | 47 | output spi_interrupt_valid, 48 | input spi_interrupt_ready 49 | ); 50 | 51 | wire polarity_low = POL_LO; 52 | 53 | localparam WAIT_TRANS = 0; 54 | localparam SPI_TRANS = 1; 55 | reg state; 56 | 57 | reg [DIV_BITS-1:0] clk_div; 58 | reg [5:0] iteration; 59 | 60 | localparam SPI_CLK_HI = 0; 61 | localparam SPI_CLK_LO = 1; 62 | localparam SPI_DEASSERT = 2; 63 | localparam SPI_HOLDSEN = 3; 64 | reg [1:0] spi_state; 65 | 66 | reg [DATA_WIDTH - 1:0] data_wr; 67 | 68 | assign spi_mosi = data_wr[DATA_WIDTH - 1]; 69 | 70 | // settings 71 | wire [DIV_BITS-1:0] set_clk_div; 72 | reg finished; 73 | 74 | assign spi_interrupt_valid = finished; 75 | 76 | localparam SPI_INITIAL_SCLK_VALUE = (SCK_LO) ? 1'b0 : 1'b1; 77 | localparam SPI_INITIAL_SCLK_IVALUE = (SCK_LO) ? 1'b1 : 1'b0; 78 | 79 | wire clk_stobe = (clk_div == 0); 80 | 81 | assign axis_rvalid = 1'b1; 82 | 83 | generate 84 | if (WR_ONLY == 0) begin 85 | reg [DATA_WIDTH - 1:0] data_rd; 86 | 87 | always @(posedge axis_clk) begin 88 | if (state == SPI_TRANS && clk_stobe && spi_state == SPI_CLK_HI) begin 89 | // TODO: read data POL_LO == 1 90 | data_rd <= {data_rd[DATA_WIDTH - 2:0], spi_miso}; 91 | end 92 | end 93 | 94 | assign axis_rdata = data_rd; 95 | end else begin 96 | assign axis_rdata = 0; 97 | end 98 | endgenerate 99 | 100 | wire axi_wd_transfer = axis_wvalid && axis_wready; 101 | wire axi_wd_transfer_transaction; 102 | 103 | `ifdef USE_DYNAMIC_DIV 104 | generate 105 | if (FIXED_DIV == 0) begin 106 | reg [DIV_BITS-1:0] set_clk_div_reg; 107 | assign set_clk_div = set_clk_div_reg; 108 | assign axi_wd_transfer_transaction = axi_wd_transfer && ~s_ul_waddr; 109 | 110 | // process for setting divider 111 | always @(posedge axis_clk) begin 112 | if (!axis_resetn) begin 113 | set_clk_div_reg <= 8'hFF; 114 | end else begin 115 | if (axi_wd_transfer) begin 116 | if (s_ul_waddr) begin 117 | set_clk_div_reg <= axis_wdata[DIV_BITS-1:0]; 118 | end 119 | end 120 | end 121 | end 122 | end else begin 123 | assign axi_wd_transfer_transaction = axi_wd_transfer; 124 | assign set_clk_div = FIXED_DIV; 125 | end 126 | endgenerate 127 | `else 128 | assign axi_wd_transfer_transaction = axi_wd_transfer; 129 | assign set_clk_div = FIXED_DIV; 130 | `endif 131 | 132 | 133 | always @(posedge axis_clk) begin 134 | if (!axis_resetn) begin 135 | state <= WAIT_TRANS; 136 | axis_wready <= 1'b0; 137 | 138 | //SPI 139 | spi_sen <= 1'b1; 140 | spi_sclk <= SPI_INITIAL_SCLK_VALUE; 141 | 142 | finished <= 1'b0; 143 | end else begin 144 | case (state) 145 | WAIT_TRANS : begin 146 | if (axi_wd_transfer_transaction) begin 147 | data_wr <= axis_wdata; 148 | axis_wready <= 1'b0; 149 | finished <= 1'b0; 150 | 151 | state <= SPI_TRANS; 152 | if (HOLD_SEN) begin 153 | spi_state <= SPI_HOLDSEN; 154 | end else begin 155 | spi_state <= SPI_CLK_LO; 156 | spi_sen <= 1'b0; 157 | end 158 | clk_div <= set_clk_div; 159 | iteration <= DATA_WIDTH - 1; 160 | end else begin 161 | if (spi_interrupt_valid && spi_interrupt_ready) begin 162 | finished <= 1'b0; 163 | end 164 | axis_wready <= 1'b1; 165 | end 166 | end 167 | 168 | SPI_TRANS : begin 169 | if (clk_stobe) begin 170 | clk_div <= set_clk_div; 171 | 172 | case (spi_state) 173 | SPI_HOLDSEN: begin 174 | if (HOLD_SEN) begin 175 | spi_sclk <= ~spi_sclk; 176 | if (spi_sclk == SPI_INITIAL_SCLK_IVALUE) begin 177 | spi_sen <= 1'b0; 178 | if (POL_LO) 179 | spi_state <= SPI_CLK_HI; 180 | else 181 | spi_state <= SPI_CLK_LO; 182 | end 183 | end 184 | end 185 | SPI_CLK_LO : begin 186 | spi_sclk <= 1'b1; 187 | if (polarity_low && (iteration != (DATA_WIDTH - 1))) begin 188 | data_wr <= {data_wr[DATA_WIDTH - 2:0], 1'b0}; 189 | end 190 | 191 | spi_state <= SPI_CLK_HI; 192 | end 193 | SPI_CLK_HI : begin 194 | spi_sclk <= 1'b0; 195 | // MSB first 196 | if (~polarity_low) begin 197 | data_wr <= {data_wr[DATA_WIDTH - 2:0], 1'b0}; 198 | end 199 | 200 | if (iteration == 0) begin 201 | spi_state <= SPI_DEASSERT; 202 | end else begin 203 | iteration <= iteration - 1; 204 | spi_state <= SPI_CLK_LO; 205 | end 206 | end 207 | SPI_DEASSERT : begin 208 | spi_sen <= 1'b1; 209 | state <= WAIT_TRANS; 210 | axis_wready <= 1'b1; 211 | //end 212 | finished <= 1'b1; 213 | spi_sclk <= SPI_INITIAL_SCLK_VALUE; 214 | end 215 | endcase 216 | 217 | end else begin 218 | clk_div <= clk_div - 1; 219 | end 220 | end 221 | endcase 222 | end 223 | end 224 | 225 | endmodule 226 | -------------------------------------------------------------------------------- /lib/i2c/ul_i2c_dme.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | // i2c dual bus master multiple device controller 7 | 8 | // TX[31] - RD_VALID 0 - only WR, 1 - RD cycle after WR 9 | // TX[30:28] - RDZ_SZ (0 - 1 byte -- skip read cycle, .. 7 - 8 bytes (but only 4 last will be stored in reg)) 10 | // TX[27:26] - WR_SZ (0 - 0 byte -- skip write cycle, 1 - 1 bytes, .. 3 - 3 bytes) 11 | 12 | // TX[25:24] - Device Address Select from LUT (WR byte 0 -- address) 13 | 14 | // TX[23:16] - WR byte 3 15 | // TX[15:8] - WR byte 2 16 | // TX[7:0] - WR byte 1 17 | // 18 | // 19 | // dev_lut[7:1], dev_lut[0] - DEV0 Address, busno 20 | // dev_lut[15:9], dev_lut[8] - DEV1 Address, busno 21 | // dev_lut[23:16], dev_lut[16] - DEV2 Address, busno 22 | // dev_lut[31:25], dev_lut[24] - DEV3 Address, busno 23 | // 24 | module ul_i2c_dme #( 25 | parameter I2C_SPEED = 100000, 26 | parameter BUS_SPEED = 125000000, 27 | parameter REPORT_ERROR = 1 28 | )( 29 | // UL clocks 30 | input clk, 31 | input reset, 32 | 33 | input [31:0] dev_lut, 34 | 35 | // BUS 1 36 | input sda1_in, 37 | output sda1_out_eo, 38 | output scl1_out_eo, 39 | 40 | // BUS 2 41 | input sda2_in, 42 | output sda2_out_eo, 43 | output scl2_out_eo, 44 | 45 | input axis_cmdreg_valid, 46 | input [31:0] axis_cmdreg_data, 47 | output axis_cmdreg_ready, 48 | 49 | output axis_rbdata_valid, 50 | output [31:0] axis_rbdata_data, 51 | input axis_rbdata_ready, 52 | 53 | input int_ready, 54 | output reg int_valid 55 | ); 56 | 57 | 58 | localparam I2CDM_WR_RDVAL_OFF = 31; 59 | localparam I2CDM_WR_RDSZ_OFF = 28; 60 | localparam I2CDM_WR_WRSZ_OFF = 26; 61 | localparam I2CDM_WR_DEVNO_OFF = 24; 62 | 63 | localparam ST_NONE = 0; 64 | localparam ST_WDATA = 1; 65 | localparam ST_STRD = 2; 66 | localparam ST_RDATA = 3; 67 | 68 | reg [1:0] state; 69 | 70 | reg i2c_rdvalid; 71 | reg [2:0] i2c_rdcnt; 72 | reg [1:0] i2c_wrcnt; 73 | reg [1:0] i2c_devsel; 74 | 75 | reg [23:0] wr_data; 76 | 77 | reg [31:0] rd_data; 78 | 79 | 80 | assign axis_cmdreg_ready = (state == ST_NONE); 81 | 82 | assign axis_rbdata_valid = 1'b1; 83 | assign axis_rbdata_data = rd_data; 84 | 85 | reg [7:0] axis_iic_tx_data; 86 | reg axis_iic_tx_valid; 87 | reg axis_iic_tx_last; 88 | wire axis_iic_tx_ready; 89 | wire [3:0] axis_iic_tx_user; 90 | 91 | wire [7:0] axis_iic_rx_data; 92 | wire axis_iic_rx_valid; 93 | wire axis_iic_rx_last; 94 | wire axis_iic_rx_ready = 1'b1; 95 | 96 | wire cmd_error; 97 | 98 | ll_i2c_dmastere #( 99 | .I2C_SPEED(I2C_SPEED), 100 | .BUS_SPEED(BUS_SPEED) 101 | ) ll_i2c_dmastere ( 102 | .reset(reset), 103 | .axis_clk(clk), 104 | 105 | .sda1_in(sda1_in), 106 | .sda1_out_eo(sda1_out_eo), 107 | .scl1_out_eo(scl1_out_eo), 108 | 109 | .sda2_in(sda2_in), 110 | .sda2_out_eo(sda2_out_eo), 111 | .scl2_out_eo(scl2_out_eo), 112 | 113 | .axis_tx_data(axis_iic_tx_data), 114 | .axis_tx_last(axis_iic_tx_last), 115 | .axis_tx_valid(axis_iic_tx_valid), 116 | .axis_tx_user(axis_iic_tx_user), 117 | .axis_tx_ready(axis_iic_tx_ready), 118 | 119 | .axis_rx_data(axis_iic_rx_data), 120 | .axis_rx_last(axis_iic_rx_last), 121 | .axis_rx_valid(axis_iic_rx_valid), 122 | .axis_rx_ready(axis_iic_rx_ready), 123 | 124 | .cmd_error(cmd_error) 125 | ); 126 | 127 | 128 | always @(posedge clk) begin 129 | if (reset) begin 130 | int_valid <= 1'b0; 131 | end else begin 132 | if (axis_iic_rx_last && axis_iic_rx_valid) begin 133 | int_valid <= 1'b1; 134 | end else if (int_valid && int_ready) begin 135 | int_valid <= 1'b0; 136 | end 137 | end 138 | end 139 | 140 | wire cmd_rdval= axis_cmdreg_data[I2CDM_WR_RDVAL_OFF]; 141 | wire [2:0] cmd_rdzsz = axis_cmdreg_data[I2CDM_WR_RDSZ_OFF + 2:I2CDM_WR_RDSZ_OFF]; 142 | wire [1:0] cmd_wrsz = axis_cmdreg_data[I2CDM_WR_WRSZ_OFF + 1:I2CDM_WR_WRSZ_OFF]; 143 | wire [1:0] cmd_devsel = axis_cmdreg_data[I2CDM_WR_DEVNO_OFF + 1:I2CDM_WR_DEVNO_OFF]; 144 | 145 | wire [7:0] i2c_addr_bus = (cmd_devsel == 2'b00) ? dev_lut[7:0] : 146 | (cmd_devsel == 2'b01) ? dev_lut[15:8] : 147 | (cmd_devsel == 2'b10) ? dev_lut[23:16] : dev_lut[31:24]; 148 | wire [7:0] rd_i2c_addr = (i2c_devsel == 2'b00) ? dev_lut[7:0] : 149 | (i2c_devsel == 2'b01) ? dev_lut[15:8] : 150 | (i2c_devsel == 2'b10) ? dev_lut[23:16] : dev_lut[31:24]; 151 | 152 | 153 | assign axis_iic_tx_user = { i2c_rdcnt, rd_i2c_addr[7] }; 154 | 155 | always @(posedge clk) begin 156 | if (reset) begin 157 | state <= ST_NONE; 158 | axis_iic_tx_valid <= 1'b0; 159 | end else begin 160 | case (state) 161 | ST_NONE: begin 162 | if (axis_cmdreg_valid && axis_cmdreg_ready) begin 163 | state <= ST_WDATA; 164 | 165 | axis_iic_tx_data <= { i2c_addr_bus[6:0], 1'b0 }; 166 | axis_iic_tx_valid <= 1'b1; 167 | axis_iic_tx_last <= 1'b0; 168 | 169 | wr_data <= axis_cmdreg_data[23:0]; 170 | 171 | i2c_rdvalid <= cmd_rdval; 172 | i2c_rdcnt <= cmd_rdzsz; 173 | i2c_wrcnt <= cmd_wrsz; 174 | i2c_devsel <= cmd_devsel; 175 | end 176 | end 177 | 178 | ST_WDATA: begin 179 | if (/*axis_iic_tx_valid && */ axis_iic_tx_ready) begin 180 | if (i2c_wrcnt == 0) begin 181 | state <= ST_STRD; 182 | end 183 | 184 | i2c_wrcnt <= i2c_wrcnt - 1; 185 | 186 | axis_iic_tx_data <= wr_data[7:0]; 187 | axis_iic_tx_last <= (i2c_wrcnt == 0); 188 | 189 | wr_data[15:0] <= wr_data[23:8]; 190 | end 191 | end 192 | 193 | ST_STRD: begin 194 | if (/*axis_iic_tx_valid && */ axis_iic_tx_ready) begin 195 | if (i2c_rdvalid) begin 196 | axis_iic_tx_data <= { rd_i2c_addr[6:0], 1'b1 }; 197 | state <= ST_RDATA; 198 | end else begin 199 | axis_iic_tx_valid <= 0; 200 | state <= ST_NONE; 201 | end 202 | 203 | axis_iic_tx_last <= 1; 204 | end 205 | end 206 | 207 | ST_RDATA: begin 208 | if (/*axis_iic_tx_valid && */ axis_iic_tx_ready) begin 209 | axis_iic_tx_valid <= 0; 210 | end 211 | 212 | if (axis_iic_rx_valid /* && axis_iic_rx_ready*/) begin 213 | 214 | rd_data[31:8] <= (cmd_error && REPORT_ERROR) ? 24'hffffff : rd_data[24:0]; 215 | rd_data[7:0] <= (cmd_error && REPORT_ERROR) ? 8'hff : axis_iic_rx_data; 216 | 217 | if (axis_iic_rx_last) begin 218 | state <= ST_NONE; 219 | end 220 | end 221 | end 222 | 223 | endcase 224 | end 225 | end 226 | 227 | 228 | endmodule 229 | -------------------------------------------------------------------------------- /lib/uart/ul_uart_smartcard.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module ul_uart_smartcard #( 7 | parameter BUS_SPEED = 62500000, 8 | parameter SIM_SPEED = 4000000, 9 | parameter UART_DIV = 372, 10 | parameter UART_DIV_BITS = 8, 11 | parameter BITS_SAMPLE = 3, 12 | parameter GEN_IRQ_WHEN_HAVE = 0 13 | )( 14 | input reset, 15 | input axis_clk, 16 | 17 | input rxd, 18 | output txd_oen, 19 | 20 | output sim_clk, 21 | output reg sim_reset, 22 | output reg sim_stopn, 23 | output reg sim_mode33v, 24 | 25 | // Output data readback stream 26 | output [31:0] axis_rdata, 27 | output axis_rvalid, 28 | input axis_rready, 29 | 30 | // Input data for UART 31 | input [31:0] axis_data, 32 | input axis_valid, 33 | output axis_ready, 34 | 35 | // Input data for CFG & control 36 | input [2:0] axis_cfg_data, 37 | input axis_cfg_valid, 38 | output axis_cfg_ready, 39 | 40 | output [31:0] axis_stat_data, 41 | output axis_stat_valid, 42 | input axis_stat_ready, 43 | 44 | // Interrupt 45 | input int_tx_ready, 46 | output reg int_tx_valid, 47 | 48 | input int_rx_ready, 49 | output reg int_rx_valid 50 | ); 51 | 52 | assign axis_stat_valid = 1'b1; 53 | assign axis_cfg_ready = 1'b1; 54 | assign axis_rvalid = 1'b1; 55 | 56 | `include "xtrxll_regs.vh" 57 | 58 | always @(posedge axis_clk) begin 59 | if (reset) begin 60 | sim_reset <= 0; 61 | sim_stopn <= 0; 62 | sim_mode33v <= 0; 63 | end else begin 64 | if (axis_cfg_valid && axis_cfg_ready) begin 65 | sim_reset <= axis_cfg_data[WR_SIM_CTRL_RESET]; 66 | sim_stopn <= axis_cfg_data[WR_SIM_CTRL_ENABLE]; 67 | sim_mode33v <= axis_cfg_data[WR_SIM_CTRL_33V]; 68 | end 69 | end 70 | end 71 | 72 | `ifdef PRECISE_DIV 73 | // Smartcard clock div 74 | localparam CLK_DIV = ((2*BUS_SPEED + SIM_SPEED) / SIM_SPEED) / 2; 75 | 76 | reg sim_clk_reset; 77 | reg sim_clk_reg; 78 | reg [7:0] sim_clk_div_reg; 79 | 80 | always @(posedge axis_clk) begin 81 | if (reset) begin 82 | sim_clk_div_reg <= 0; 83 | sim_clk_reg <= 0; 84 | sim_clk_reset <= 1; 85 | end else begin 86 | if (sim_clk_div_reg == (CLK_DIV/2) - 1) begin 87 | sim_clk_div_reg <= 0; 88 | sim_clk_reg <= ~sim_clk_reg; 89 | 90 | if (sim_clk_reg) 91 | sim_clk_reset <= 0; 92 | end else begin 93 | sim_clk_div_reg <= sim_clk_div_reg + 1; 94 | end 95 | end 96 | end 97 | 98 | assign sim_clk = sim_clk_reg; 99 | 100 | `else 101 | localparam CLK_DIV = 16; 102 | 103 | reg [3:0] sim_clk_div_reg; 104 | 105 | always @(posedge axis_clk) begin 106 | if (reset) begin 107 | sim_clk_div_reg <= 0; 108 | end else begin 109 | sim_clk_div_reg <= sim_clk_div_reg + 1; 110 | end 111 | end 112 | 113 | assign sim_clk = sim_clk_div_reg[3]; 114 | 115 | `endif 116 | 117 | 118 | wire [7:0] tx_data; 119 | wire tx_valid; 120 | wire tx_ready; 121 | 122 | wire [7:0] rx_data; 123 | wire rx_valid; 124 | wire rx_ready; 125 | 126 | wire parity_error; 127 | 128 | wire full_sim_reset = ~sim_reset || reset; 129 | 130 | uart_smartcard #( 131 | .CLK_DIV(UART_DIV * CLK_DIV), 132 | .CLK_DIV_BITS(UART_DIV_BITS + 6), 133 | .BITS_SAMPLE(BITS_SAMPLE) 134 | ) uart_smartcard ( 135 | .reset(full_sim_reset), 136 | // .baseclk(sim_clk), 137 | .baseclk(axis_clk), 138 | 139 | .rxd(rxd), 140 | .txd_oen(txd_oen), 141 | 142 | .tx_data(tx_data), 143 | .tx_valid(tx_valid), 144 | .tx_ready(tx_ready), 145 | 146 | .rx_data(rx_data), 147 | .rx_valid(rx_valid), 148 | .rx_ready(rx_ready), 149 | 150 | .parity_error(parity_error) 151 | ); 152 | 153 | wire [4:0] rx_fifo_used; 154 | wire rx_fifo_empty; 155 | 156 | wire [4:0] tx_fifo_used; 157 | wire tx_fifo_empty; 158 | 159 | assign axis_rdata[31:UART_FIFOTX_EMPTY+1] = 0; 160 | assign axis_rdata[UART_FIFOTX_EMPTY] = tx_fifo_empty; 161 | assign axis_rdata[UART_FIFOTX_USED_OFF+UART_FIFOTX_USED_BITS-1:UART_FIFOTX_USED_OFF] = tx_fifo_used; 162 | 163 | assign axis_rdata[UART_FIFORX_EMPTY] = rx_fifo_empty; 164 | assign axis_rdata[UART_FIFORX_PARERR] = parity_error; 165 | assign axis_rdata[13:8] = 0; 166 | 167 | 168 | assign axis_stat_data = axis_rdata; 169 | 170 | 171 | axis_fifo32 #( 172 | .WIDTH(8) 173 | ) rx_axis_fifo32 ( 174 | .clk(axis_clk), 175 | .axisrst(full_sim_reset), 176 | 177 | .axis_rx_tdata(rx_data), 178 | .axis_rx_tvalid(rx_valid), 179 | .axis_rx_tready(rx_ready), 180 | 181 | .axis_tx_tdata(axis_rdata[7:0]), 182 | .axis_tx_tvalid(), 183 | .axis_tx_tready(axis_rready), 184 | 185 | .fifo_used(rx_fifo_used), 186 | .fifo_empty(rx_fifo_empty) 187 | ); 188 | 189 | axis_fifo32 #( 190 | .WIDTH(8) 191 | ) tx_axis_fifo32 ( 192 | .clk(axis_clk), 193 | .axisrst(full_sim_reset), 194 | 195 | .axis_rx_tdata(axis_data[7:0]), 196 | .axis_rx_tvalid(axis_valid), 197 | .axis_rx_tready(axis_ready), 198 | 199 | .axis_tx_tdata(tx_data), 200 | .axis_tx_tvalid(tx_valid), 201 | .axis_tx_tready(tx_ready), 202 | 203 | .fifo_used(tx_fifo_used), 204 | .fifo_empty(tx_fifo_empty) 205 | ); 206 | 207 | 208 | reg rx_fifo_empty_prev; 209 | always @(posedge axis_clk) begin 210 | if (reset) begin 211 | int_rx_valid <= 0; 212 | rx_fifo_empty_prev <= 1'b1; 213 | end else begin 214 | rx_fifo_empty_prev <= rx_fifo_empty; 215 | 216 | if (rx_fifo_empty_prev == 1'b1 && rx_fifo_empty == 1'b0) begin 217 | int_rx_valid <= 1'b1; 218 | end else if (int_rx_valid && int_rx_ready) begin 219 | int_rx_valid <= 1'b0; 220 | end 221 | end 222 | end 223 | 224 | // We fire interrupt only when we initally fully occupied TX buffer and then it gets 225 | // down to low mark level 226 | wire tx_fifo_full = (tx_fifo_used == 5'b1_1111); 227 | wire tx_fifo_trigger_low = (tx_fifo_used == GEN_IRQ_WHEN_HAVE); 228 | 229 | reg tx_fifo_full_prev; 230 | 231 | always @(posedge axis_clk) begin 232 | if (reset) begin 233 | int_tx_valid <= 0; 234 | tx_fifo_full_prev <= 0; 235 | end else begin 236 | if (~tx_fifo_full_prev) 237 | tx_fifo_full_prev <= tx_fifo_full; 238 | 239 | if (tx_fifo_full_prev && tx_fifo_trigger_low) begin 240 | int_tx_valid <= 1'b1; 241 | tx_fifo_full_prev <= 1'b0; 242 | end else if (int_tx_valid && int_tx_ready) begin 243 | int_tx_valid <= 1'b0; 244 | end 245 | end 246 | end 247 | 248 | endmodule 249 | 250 | -------------------------------------------------------------------------------- /lib/ram/ram64xsdp.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module ram64xsdp #( 7 | parameter WIDTH = 3 8 | )( 9 | input wclk, 10 | input we, 11 | input [5:0] waddr, 12 | input [WIDTH-1:0] datai, 13 | 14 | input [5:0] raddr, 15 | output [WIDTH-1:0] datao 16 | ); 17 | 18 | `ifdef SYM 19 | // Make debug friendly 20 | reg [WIDTH-1:0] r0; 21 | reg [WIDTH-1:0] r1; 22 | reg [WIDTH-1:0] r2; 23 | reg [WIDTH-1:0] r3; 24 | reg [WIDTH-1:0] r4; 25 | reg [WIDTH-1:0] r5; 26 | reg [WIDTH-1:0] r6; 27 | reg [WIDTH-1:0] r7; 28 | reg [WIDTH-1:0] r8; 29 | reg [WIDTH-1:0] r9; 30 | reg [WIDTH-1:0] r10; 31 | reg [WIDTH-1:0] r11; 32 | reg [WIDTH-1:0] r12; 33 | reg [WIDTH-1:0] r13; 34 | reg [WIDTH-1:0] r14; 35 | reg [WIDTH-1:0] r15; 36 | reg [WIDTH-1:0] r16; 37 | reg [WIDTH-1:0] r17; 38 | reg [WIDTH-1:0] r18; 39 | reg [WIDTH-1:0] r19; 40 | reg [WIDTH-1:0] r20; 41 | reg [WIDTH-1:0] r21; 42 | reg [WIDTH-1:0] r22; 43 | reg [WIDTH-1:0] r23; 44 | reg [WIDTH-1:0] r24; 45 | reg [WIDTH-1:0] r25; 46 | reg [WIDTH-1:0] r26; 47 | reg [WIDTH-1:0] r27; 48 | reg [WIDTH-1:0] r28; 49 | reg [WIDTH-1:0] r29; 50 | reg [WIDTH-1:0] r30; 51 | reg [WIDTH-1:0] r31; 52 | reg [WIDTH-1:0] r32; 53 | reg [WIDTH-1:0] r33; 54 | reg [WIDTH-1:0] r34; 55 | reg [WIDTH-1:0] r35; 56 | reg [WIDTH-1:0] r36; 57 | reg [WIDTH-1:0] r37; 58 | reg [WIDTH-1:0] r38; 59 | reg [WIDTH-1:0] r39; 60 | reg [WIDTH-1:0] r40; 61 | reg [WIDTH-1:0] r41; 62 | reg [WIDTH-1:0] r42; 63 | reg [WIDTH-1:0] r43; 64 | reg [WIDTH-1:0] r44; 65 | reg [WIDTH-1:0] r45; 66 | reg [WIDTH-1:0] r46; 67 | reg [WIDTH-1:0] r47; 68 | reg [WIDTH-1:0] r48; 69 | reg [WIDTH-1:0] r49; 70 | reg [WIDTH-1:0] r50; 71 | reg [WIDTH-1:0] r51; 72 | reg [WIDTH-1:0] r52; 73 | reg [WIDTH-1:0] r53; 74 | reg [WIDTH-1:0] r54; 75 | reg [WIDTH-1:0] r55; 76 | reg [WIDTH-1:0] r56; 77 | reg [WIDTH-1:0] r57; 78 | reg [WIDTH-1:0] r58; 79 | reg [WIDTH-1:0] r59; 80 | reg [WIDTH-1:0] r60; 81 | reg [WIDTH-1:0] r61; 82 | reg [WIDTH-1:0] r62; 83 | reg [WIDTH-1:0] r63; 84 | 85 | always @(posedge wclk) begin 86 | if (we) begin 87 | case (waddr) 88 | 0: r0 <= datai; 89 | 1: r1 <= datai; 90 | 2: r2 <= datai; 91 | 3: r3 <= datai; 92 | 4: r4 <= datai; 93 | 5: r5 <= datai; 94 | 6: r6 <= datai; 95 | 7: r7 <= datai; 96 | 8: r8 <= datai; 97 | 9: r9 <= datai; 98 | 10: r10<= datai; 99 | 11: r11<= datai; 100 | 12: r12<= datai; 101 | 13: r13<= datai; 102 | 14: r14<= datai; 103 | 15: r15<= datai; 104 | 16: r16<= datai; 105 | 17: r17<= datai; 106 | 18: r18<= datai; 107 | 19: r19<= datai; 108 | 20: r20<= datai; 109 | 21: r21<= datai; 110 | 22: r22<= datai; 111 | 23: r23<= datai; 112 | 24: r24<= datai; 113 | 25: r25<= datai; 114 | 26: r26<= datai; 115 | 27: r27<= datai; 116 | 28: r28<= datai; 117 | 29: r29<= datai; 118 | 30: r30<= datai; 119 | 31: r31<= datai; 120 | 32: r32<= datai; 121 | 33: r33<= datai; 122 | 34: r34<= datai; 123 | 35: r35<= datai; 124 | 36: r36<= datai; 125 | 37: r37<= datai; 126 | 38: r38<= datai; 127 | 39: r39<= datai; 128 | 40: r40<= datai; 129 | 41: r41<= datai; 130 | 42: r42<= datai; 131 | 43: r43<= datai; 132 | 44: r44<= datai; 133 | 45: r45<= datai; 134 | 46: r46<= datai; 135 | 47: r47<= datai; 136 | 48: r48<= datai; 137 | 49: r49<= datai; 138 | 50: r50<= datai; 139 | 51: r51<= datai; 140 | 52: r52<= datai; 141 | 53: r53<= datai; 142 | 54: r54<= datai; 143 | 55: r55<= datai; 144 | 56: r56<= datai; 145 | 57: r57<= datai; 146 | 58: r58<= datai; 147 | 59: r59<= datai; 148 | 60: r60<= datai; 149 | 61: r61<= datai; 150 | 62: r62<= datai; 151 | 63: r63<= datai; 152 | endcase 153 | end 154 | end 155 | 156 | assign datao = 157 | (raddr == 0) ? r0 : 158 | (raddr == 1) ? r1 : 159 | (raddr == 2) ? r2 : 160 | (raddr == 3) ? r3 : 161 | (raddr == 4) ? r4 : 162 | (raddr == 5) ? r5 : 163 | (raddr == 6) ? r6 : 164 | (raddr == 7) ? r7 : 165 | (raddr == 8) ? r8 : 166 | (raddr == 9) ? r9 : 167 | (raddr == 10) ? r10 : 168 | (raddr == 11) ? r11 : 169 | (raddr == 12) ? r12 : 170 | (raddr == 13) ? r13 : 171 | (raddr == 14) ? r14 : 172 | (raddr == 15) ? r15 : 173 | (raddr == 16) ? r16 : 174 | (raddr == 17) ? r17 : 175 | (raddr == 18) ? r18 : 176 | (raddr == 19) ? r19 : 177 | (raddr == 20) ? r20 : 178 | (raddr == 21) ? r21 : 179 | (raddr == 22) ? r22 : 180 | (raddr == 23) ? r23 : 181 | (raddr == 24) ? r24 : 182 | (raddr == 25) ? r25 : 183 | (raddr == 26) ? r26 : 184 | (raddr == 27) ? r27 : 185 | (raddr == 28) ? r28 : 186 | (raddr == 29) ? r29 : 187 | (raddr == 30) ? r30 : 188 | (raddr == 31) ? r31 : 189 | (raddr == 32) ? r32 : 190 | (raddr == 33) ? r33 : 191 | (raddr == 34) ? r34 : 192 | (raddr == 35) ? r35 : 193 | (raddr == 36) ? r36 : 194 | (raddr == 37) ? r37 : 195 | (raddr == 38) ? r38 : 196 | (raddr == 39) ? r39 : 197 | (raddr == 40) ? r40 : 198 | (raddr == 41) ? r41 : 199 | (raddr == 42) ? r42 : 200 | (raddr == 43) ? r43 : 201 | (raddr == 44) ? r44 : 202 | (raddr == 45) ? r45 : 203 | (raddr == 46) ? r46 : 204 | (raddr == 47) ? r47 : 205 | (raddr == 48) ? r48 : 206 | (raddr == 49) ? r49 : 207 | (raddr == 50) ? r50 : 208 | (raddr == 51) ? r51 : 209 | (raddr == 52) ? r52 : 210 | (raddr == 53) ? r53 : 211 | (raddr == 54) ? r54 : 212 | (raddr == 55) ? r55 : 213 | (raddr == 56) ? r56 : 214 | (raddr == 57) ? r57 : 215 | (raddr == 58) ? r58 : 216 | (raddr == 59) ? r59 : 217 | (raddr == 60) ? r60 : 218 | (raddr == 61) ? r61 : 219 | (raddr == 62) ? r62 : 220 | r63; 221 | 222 | `else 223 | localparam COUNT = (WIDTH + 2) / 3; 224 | 225 | wire [3*COUNT-1:0] xdatao; 226 | assign datao = xdatao[WIDTH-1:0]; 227 | 228 | wire [3*COUNT-1:0] xdatai = datai; 229 | 230 | genvar i; 231 | generate 232 | for (i = 0; i < COUNT; i=i+1) begin: part 233 | 234 | RAM64M #( 235 | .INIT_A(64'h0000000000000000), // Initial contents of A Port 236 | .INIT_B(64'h0000000000000000), // Initial contents of B Port 237 | .INIT_C(64'h0000000000000000), // Initial contents of C Port 238 | .INIT_D(64'h0000000000000000) // Initial contents of D Port 239 | ) RAM64X6SDP ( 240 | .DOA(xdatao[3*i+0]), 241 | .DOB(xdatao[3*i+1]), 242 | .DOC(xdatao[3*i+2]), 243 | .DOD(), 244 | 245 | .ADDRA(raddr), 246 | .ADDRB(raddr), 247 | .ADDRC(raddr), 248 | .ADDRD(waddr), 249 | 250 | .DIA(xdatai[3*i+0]), 251 | .DIB(xdatai[3*i+1]), 252 | .DIC(xdatai[3*i+2]), 253 | .DID(2'b0), 254 | 255 | .WCLK(wclk), 256 | .WE(we) 257 | ); 258 | 259 | end 260 | endgenerate 261 | `endif 262 | 263 | 264 | endmodule 265 | -------------------------------------------------------------------------------- /lib/lms7/fe_tx_chain_brst.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module fe_tx_chain_brst #( 7 | parameter LOW_ADDDR_BITS = 13, 8 | parameter TS_BITS = 30 9 | )( 10 | input mclk, 11 | input arst, 12 | input mode_siso, 13 | input mode_repeat, 14 | input [2:0] inter_rate, 15 | 16 | // LMS7 if 17 | output [11:0] out_sdr_ai, 18 | output [11:0] out_sdr_aq, 19 | output [11:0] out_sdr_bi, 20 | output [11:0] out_sdr_bq, 21 | output out_strobe, 22 | 23 | // Output overrun notification 24 | // TODO 25 | output [1:0] debug_fe_state, 26 | output [LOW_ADDDR_BITS-1:0] debug_rd_addr, 27 | 28 | output ts_rd_addr_inc, 29 | output [TS_BITS-1:0] ts_rd_addr_late_samples, 30 | 31 | output ts_rd_addr_processed_inc, 32 | input ts_rd_valid, // Valid start time & No of samples 33 | input [TS_BITS-1:0] ts_rd_start, 34 | input [LOW_ADDDR_BITS-1:0] ts_rd_samples, 35 | output [TS_BITS-1:0] ts_current, 36 | 37 | //FIFO RAM iface 38 | output fifo_rd_en, 39 | output [LOW_ADDDR_BITS-1:0] fifo_rd_addr, 40 | input [47:0] fifo_rd_data, 41 | 42 | 43 | // Output current read addr (with 1 extra MSB) 44 | input out_rd_clk, 45 | input out_rd_rst, 46 | output [LOW_ADDDR_BITS:4] out_rd_addr 47 | ); 48 | 49 | wire out_iq_sel; 50 | 51 | wire overrun; 52 | 53 | 54 | wire fifo_tready; 55 | wire fifo_tvalid; 56 | 57 | lms7_tx_frm_brst_ex lms7_tx_frm_brst_ex( 58 | .rst(arst), 59 | 60 | // LMS7 61 | .out_sdr_ai(out_sdr_ai), 62 | .out_sdr_aq(out_sdr_aq), 63 | .out_sdr_bi(out_sdr_bi), 64 | .out_sdr_bq(out_sdr_bq), 65 | .out_strobe(out_strobe), 66 | .mclk(mclk), 67 | 68 | // FIFO (RAM) 69 | .fifo_tdata(fifo_rd_data), 70 | .fifo_tvalid(fifo_tvalid), 71 | .fifo_tready(fifo_tready), 72 | 73 | .single_ch_mode(mode_siso), 74 | .inter_rate(inter_rate) 75 | ); 76 | 77 | wire fifo_rd_last; 78 | wire blk_in_time; 79 | 80 | reg blk_in_time_reg; 81 | reg blk_in_time_reg_2; 82 | 83 | 84 | localparam ST_WAIT_TS = 0; 85 | localparam ST_WAIT_BURST = 1; 86 | localparam ST_INBURST = 2; 87 | 88 | localparam ST_REPEAT = 3; // repeat mode in functional generator 89 | 90 | reg [1:0] state; 91 | 92 | assign debug_fe_state = state; 93 | 94 | 95 | reg ts_rd_addr_inc_reg; 96 | assign ts_rd_addr_inc = ts_rd_addr_inc_reg; 97 | 98 | 99 | wire clk_iter_strobe = fifo_tready; 100 | assign fifo_rd_en = (state != ST_WAIT_TS) && (clk_iter_strobe); 101 | 102 | reg [LOW_ADDDR_BITS-1:0] cur_sample_in_burst; 103 | 104 | wire prev_last_sample_in_burst = (cur_sample_in_burst == 2); 105 | reg last_sample_in_burst; 106 | 107 | reg repeat_reset; 108 | 109 | assign fifo_tvalid = (state == ST_REPEAT || state == ST_INBURST); 110 | 111 | 112 | wire fifo_rd_addr_inc = (state == ST_REPEAT && fifo_tready) || 113 | (state == ST_WAIT_BURST && blk_in_time_reg && clk_iter_strobe) || 114 | (state == ST_INBURST && (fifo_tready) && (~last_sample_in_burst || ts_rd_valid && blk_in_time_reg)); 115 | 116 | 117 | assign ts_rd_addr_processed_inc = (state == ST_INBURST) && last_sample_in_burst && fifo_tready; 118 | 119 | 120 | always @(posedge mclk) begin 121 | if (arst) begin 122 | ts_rd_addr_inc_reg <= 1'b0; 123 | cur_sample_in_burst <= 1'b0; 124 | last_sample_in_burst <= 1'b0; 125 | repeat_reset <= 1'b0; 126 | 127 | if (mode_repeat) begin 128 | state <= ST_REPEAT; 129 | cur_sample_in_burst <= ts_rd_samples; 130 | end else begin 131 | state <= ST_WAIT_TS; 132 | end 133 | end else begin 134 | 135 | ts_rd_addr_inc_reg <= ((state == ST_WAIT_BURST) && blk_in_time_reg && clk_iter_strobe) || 136 | ((state == ST_INBURST) && fifo_tready && last_sample_in_burst && ts_rd_valid && blk_in_time_reg); 137 | 138 | case (state) 139 | ST_WAIT_TS: begin 140 | if (ts_rd_valid && clk_iter_strobe) begin 141 | state <= ST_WAIT_BURST; 142 | cur_sample_in_burst <= ts_rd_samples; 143 | end 144 | end 145 | 146 | ST_WAIT_BURST: begin 147 | if (blk_in_time_reg && clk_iter_strobe) begin 148 | state <= ST_INBURST; 149 | end 150 | end 151 | 152 | ST_INBURST: begin 153 | if (fifo_tready) begin 154 | if (last_sample_in_burst) begin 155 | if (ts_rd_valid) begin 156 | cur_sample_in_burst <= ts_rd_samples; 157 | 158 | if (~blk_in_time_reg) begin 159 | state <= ST_WAIT_BURST; 160 | end 161 | end else begin 162 | state <= ST_WAIT_TS; 163 | end 164 | 165 | last_sample_in_burst <= 1'b0; 166 | end else begin 167 | cur_sample_in_burst <= cur_sample_in_burst - 1'b1; 168 | last_sample_in_burst <= prev_last_sample_in_burst; 169 | end 170 | end 171 | end 172 | 173 | // Nothing to do in repeat mode 174 | ST_REPEAT: begin 175 | if (fifo_tready) begin 176 | if (last_sample_in_burst) begin 177 | cur_sample_in_burst <= ts_rd_samples; 178 | last_sample_in_burst <= 1'b0; 179 | end else begin 180 | cur_sample_in_burst <= cur_sample_in_burst - 1'b1; 181 | last_sample_in_burst <= prev_last_sample_in_burst; 182 | end 183 | end 184 | 185 | repeat_reset <= (fifo_tready && prev_last_sample_in_burst); 186 | end 187 | 188 | endcase 189 | end 190 | end 191 | 192 | assign debug_rd_addr = fifo_rd_addr; 193 | 194 | cross_counter #( 195 | .WIDTH(LOW_ADDDR_BITS), 196 | .GRAY_BITS(3+4), 197 | .OUT_WIDTH(LOW_ADDDR_BITS+1), 198 | .OUT_LOWER_SKIP(4) 199 | ) sym_addr ( 200 | .inrst(arst | repeat_reset), 201 | .inclk(mclk), 202 | .incmdvalid(fifo_rd_addr_inc), 203 | .incmdinc(1'b1), 204 | .incnt(fifo_rd_addr), 205 | 206 | .outrst(out_rd_rst), 207 | .outclk(out_rd_clk), 208 | .outcnt(out_rd_addr) 209 | ); 210 | 211 | 212 | reg [TS_BITS-1:0] ts_current_reg; 213 | assign ts_current = ts_current_reg; 214 | 215 | always @(posedge mclk) begin 216 | if (arst) begin 217 | ts_current_reg <= 0; 218 | end else begin 219 | if (clk_iter_strobe) begin 220 | ts_current_reg <= ts_current_reg + 1; 221 | end 222 | end 223 | end 224 | 225 | wire [TS_BITS-1:0] diff_v = ts_current - ts_rd_start + 1'b1; 226 | assign ts_rd_addr_late_samples = diff_v; 227 | 228 | 229 | always @(posedge mclk) begin 230 | if (arst) begin 231 | blk_in_time_reg <= 0; 232 | end else begin 233 | if (clk_iter_strobe) begin 234 | blk_in_time_reg <= ~diff_v[TS_BITS-1]; 235 | end 236 | end 237 | end 238 | 239 | assign blk_in_time = blk_in_time_reg; 240 | 241 | 242 | endmodule 243 | -------------------------------------------------------------------------------- /top/xtrxr5/xlnx_pcie_clocking.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | `timescale 1ns / 1ps 7 | 8 | module xlnx_pci_clocking #( 9 | parameter PCIE_LANE = 2, // PCIe number of lanes 10 | parameter PCIE_LINK_SPEED = 2, // PCIe link speed 11 | parameter PCIE_USERCLK_FREQ = 3, // PCIe user clock 1 frequency 12 | parameter PCIE_OOBCLK_MODE = 1, // PCIe oob clock mode 13 | parameter PCIE_GEN1_MODE = 0 14 | ) ( 15 | //---------- Input ------------------------------------- 16 | input CLK_RST_N, 17 | input CLK_TXOUTCLK, 18 | input [PCIE_LANE-1:0] CLK_PCLK_SEL, 19 | 20 | //---------- Output ------------------------------------ 21 | output CLK_PCLK, 22 | output CLK_DCLK, 23 | output CLK_USERCLK, 24 | output CLK_MMCM_LOCK, 25 | 26 | input alt_refclk, 27 | input alt_refclk_use, 28 | 29 | output clk_50mhz_out, 30 | 31 | // MMCM DRP configuration port 32 | input cfg_mmcm_drp_dclk, 33 | input [15:0] cfg_mmcm_drp_di, 34 | input [6:0] cfg_mmcm_drp_daddr, 35 | input cfg_mmcm_drp_den, 36 | input cfg_mmcm_drp_dwe, 37 | output [15:0] cfg_mmcm_drp_do, 38 | output cfg_mmcm_drp_drdy, 39 | input [3:0] cfg_mmcm_drp_gpio_out, 40 | output [3:0] cfg_mmcm_drp_gpio_in 41 | ); 42 | 43 | localparam DIVCLK_DIVIDE = 1; 44 | localparam CLKFBOUT_MULT_F = 10; 45 | localparam CLKIN1_PERIOD = 10; 46 | localparam CLKOUT0_DIVIDE_F = 8; 47 | localparam CLKOUT1_DIVIDE = 4; 48 | localparam CLKOUT2_DIVIDE = (PCIE_USERCLK_FREQ == 5) ? 2 : 49 | (PCIE_USERCLK_FREQ == 4) ? 4 : 50 | (PCIE_USERCLK_FREQ == 3) ? 8 : 51 | (PCIE_USERCLK_FREQ == 1) ? 32 : 16; 52 | localparam CLKOUT3_DIVIDE = CLKOUT2_DIVIDE; 53 | localparam CLKOUT4_DIVIDE = 62; 54 | 55 | wire refclk; 56 | wire mmcm_fb; 57 | wire clk_125mhz; 58 | wire clk_125mhz_buf; 59 | wire clk_250mhz; 60 | wire userclk1; 61 | reg pclk_sel = 1'd0; 62 | 63 | wire pclk_1; 64 | wire pclk; 65 | wire userclk1_1; 66 | wire mmcm_lock; 67 | wire clk_50mhz; 68 | 69 | (* ASYNC_REG = "TRUE", SHIFT_EXTRACT = "NO" *) reg [PCIE_LANE-1:0] pclk_sel_reg1 = {PCIE_LANE{1'd0}}; 70 | (* ASYNC_REG = "TRUE", SHIFT_EXTRACT = "NO" *) reg [PCIE_LANE-1:0] pclk_sel_reg2 = {PCIE_LANE{1'd0}}; 71 | 72 | always @ (posedge pclk) 73 | begin 74 | if (!CLK_RST_N) begin 75 | pclk_sel_reg1 <= {PCIE_LANE{1'd0}}; 76 | pclk_sel_reg2 <= {PCIE_LANE{1'd0}}; 77 | end else begin 78 | pclk_sel_reg1 <= CLK_PCLK_SEL; 79 | pclk_sel_reg2 <= pclk_sel_reg1; 80 | end 81 | end 82 | 83 | BUFG txoutclk_i(.I(CLK_TXOUTCLK), .O(refclk)); 84 | 85 | wire refclk2; 86 | BUFG refclk2_i(.I(alt_refclk), .O(refclk2)); 87 | 88 | MMCME2_ADV #( 89 | .BANDWIDTH ("OPTIMIZED"), 90 | .CLKOUT4_CASCADE ("FALSE"), 91 | .COMPENSATION ("ZHOLD"), 92 | .STARTUP_WAIT ("FALSE"), 93 | .DIVCLK_DIVIDE (DIVCLK_DIVIDE), 94 | .CLKFBOUT_MULT_F (CLKFBOUT_MULT_F), 95 | .CLKFBOUT_PHASE (0.000), 96 | .CLKFBOUT_USE_FINE_PS ("FALSE"), 97 | .CLKOUT0_DIVIDE_F (CLKOUT0_DIVIDE_F), 98 | .CLKOUT0_PHASE (0.000), 99 | .CLKOUT0_DUTY_CYCLE (0.500), 100 | .CLKOUT0_USE_FINE_PS ("FALSE"), 101 | .CLKOUT1_DIVIDE (CLKOUT1_DIVIDE), 102 | .CLKOUT1_PHASE (0.000), 103 | .CLKOUT1_DUTY_CYCLE (0.500), 104 | .CLKOUT1_USE_FINE_PS ("FALSE"), 105 | .CLKOUT2_DIVIDE (CLKOUT2_DIVIDE), 106 | .CLKOUT2_PHASE (0.000), 107 | .CLKOUT2_DUTY_CYCLE (0.500), 108 | .CLKOUT2_USE_FINE_PS ("FALSE"), 109 | .CLKOUT3_DIVIDE (CLKOUT3_DIVIDE), 110 | .CLKOUT3_PHASE (0.000), 111 | .CLKOUT3_DUTY_CYCLE (0.500), 112 | .CLKOUT3_USE_FINE_PS ("FALSE"), 113 | .CLKOUT4_DIVIDE (CLKOUT4_DIVIDE), 114 | .CLKOUT4_PHASE (0.000), 115 | .CLKOUT4_DUTY_CYCLE (0.500), 116 | .CLKOUT4_USE_FINE_PS ("FALSE"), 117 | .CLKIN1_PERIOD (CLKIN1_PERIOD), 118 | .CLKIN2_PERIOD (CLKIN1_PERIOD), 119 | .REF_JITTER1 (0.010) 120 | ) mmcm_i ( 121 | //---------- Input ------------------------------------ 122 | .CLKIN1 (refclk), 123 | .CLKIN2 (refclk2), 124 | .CLKINSEL (~alt_refclk_use), 125 | .CLKFBIN (mmcm_fb), 126 | .RST (!CLK_RST_N), 127 | .PWRDWN (1'd0), 128 | 129 | //---------- Output ------------------------------------ 130 | .CLKFBOUT (mmcm_fb), 131 | .CLKFBOUTB (), 132 | .CLKOUT0 (clk_125mhz), 133 | .CLKOUT0B (), 134 | .CLKOUT1 (clk_250mhz), 135 | .CLKOUT1B (), 136 | .CLKOUT2 (userclk1), 137 | .CLKOUT2B (), 138 | .CLKOUT3 (), 139 | .CLKOUT3B (), 140 | .CLKOUT4 (clk_50mhz), 141 | .CLKOUT5 (), 142 | .CLKOUT6 (), 143 | .LOCKED (mmcm_lock), 144 | 145 | //---------- Dynamic Reconfiguration ------------------- 146 | .DCLK (cfg_mmcm_drp_dclk), 147 | .DADDR (cfg_mmcm_drp_daddr), 148 | .DEN (cfg_mmcm_drp_den), 149 | .DWE (cfg_mmcm_drp_dwe), 150 | .DI (cfg_mmcm_drp_di), 151 | .DO (cfg_mmcm_drp_do), 152 | .DRDY (cfg_mmcm_drp_drdy), 153 | 154 | //---------- Dynamic Phase Shift ----------------------- 155 | .PSCLK (1'd0), 156 | .PSEN (1'd0), 157 | .PSINCDEC (1'd0), 158 | .PSDONE (), 159 | 160 | //---------- Status ------------------------------------ 161 | .CLKINSTOPPED (cfg_mmcm_drp_gpio_in[1]), 162 | .CLKFBSTOPPED (cfg_mmcm_drp_gpio_in[2]) 163 | ); 164 | 165 | assign cfg_mmcm_drp_gpio_in[0] = mmcm_lock; 166 | assign cfg_mmcm_drp_gpio_in[3] = 0; 167 | 168 | //---------- Select PCLK MUX --------------------------------------------------- 169 | generate 170 | if (PCIE_LINK_SPEED != 1) begin : pclk_i1_bufgctrl 171 | BUFGCTRL pclk_i1( 172 | .CE0 (1'd1), 173 | .CE1 (1'd1), 174 | .I0 (clk_125mhz), 175 | .I1 (clk_250mhz), 176 | .IGNORE0 (1'd0), 177 | .IGNORE1 (1'd0), 178 | .S0 (~pclk_sel), 179 | .S1 ( pclk_sel), 180 | .O (pclk_1) 181 | ); 182 | end else begin : pclk_i1_bufg 183 | BUFG pclk_i1(.I(clk_125mhz), .O(clk_125mhz_buf)); 184 | assign pclk_1 = clk_125mhz_buf; 185 | end 186 | endgenerate 187 | 188 | generate 189 | if (PCIE_LINK_SPEED != 1) begin : dclk_i_bufg 190 | BUFG dclk_i(.I(clk_125mhz), .O(CLK_DCLK)); 191 | end else begin : dclk_i 192 | assign CLK_DCLK = clk_125mhz_buf; 193 | end 194 | endgenerate 195 | 196 | 197 | generate 198 | if (PCIE_GEN1_MODE == 1'b1 && PCIE_USERCLK_FREQ == 3) begin :userclk1_i1_no_bufg 199 | assign userclk1_1 = pclk_1; 200 | end else begin : userclk1_i1 201 | BUFG usrclk1_i1(.I(userclk1), .O(userclk1_1)); 202 | end 203 | endgenerate 204 | 205 | assign pclk = pclk_1; 206 | assign CLK_USERCLK = userclk1_1; 207 | 208 | always @(posedge pclk) 209 | begin 210 | if (!CLK_RST_N) begin 211 | pclk_sel <= 1'd0; 212 | end else begin 213 | if (&pclk_sel_reg2) 214 | pclk_sel <= 1'd1; // 250Mhz 215 | else if (&(~pclk_sel_reg2)) 216 | pclk_sel <= 1'd0; // 125Mhz 217 | else 218 | pclk_sel <= pclk_sel; 219 | 220 | end 221 | end 222 | 223 | BUFG clk_50mhz_i(.I(clk_50mhz), .O(clk_50mhz_out)); 224 | 225 | assign CLK_PCLK = pclk; 226 | assign CLK_MMCM_LOCK = mmcm_lock; 227 | 228 | endmodule 229 | -------------------------------------------------------------------------------- /lib/pcie/pcie_req_to_ram.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module pcie_req_to_ram #( 7 | parameter LOW_ADDDR_BITS = 14 8 | )( 9 | // UL 10 | input s_ul_clk, 11 | input s_ul_aresetn, 12 | 13 | input txdma_active, 14 | 15 | input [15:0] cfg_pcie_reqid, 16 | 17 | // AXIs PCIe TX (completion) 18 | output s_axis_rx_tready, 19 | input [63:0] s_axis_rx_tdata, 20 | input [7:0] s_axis_rx_tkeep, 21 | input s_axis_rx_tlast, 22 | input s_axis_rx_tvalid, 23 | 24 | input m_axis_tx_tready, 25 | output reg [63:0] m_axis_tx_tdata, 26 | output reg [7:0] m_axis_tx_tkeep, 27 | output reg m_axis_tx_tlast, 28 | output reg m_axis_tx_tvalid, 29 | 30 | // RAM interface 31 | output [63:0] m_ram_tdata, 32 | output [LOW_ADDDR_BITS-1:0] m_ram_taddr, 33 | output m_ram_tvalid, 34 | 35 | // Request & notify 36 | input ul_ml_rvalid, 37 | output ul_ml_rready, 38 | input [LOW_ADDDR_BITS+3-1:3] ul_ml_rlocaddr, 39 | input [31:3] ul_ml_rbusaddr, 40 | input [8:0] ul_ml_rlength, 41 | input [4:0] ul_ml_rtag, 42 | 43 | output ul_ml_tvalid, 44 | input ul_ml_tready, 45 | output [4:0] ul_ml_ttag 46 | ); 47 | 48 | localparam REQ_TAG_BITS = 5; 49 | 50 | wire [LOW_ADDDR_BITS-1:0] buffer_burst_cpld_addr; 51 | 52 | wire pcie_rtag_rd_latch; 53 | wire [4:0] pcie_rtag_rd; // cpld TAG 54 | 55 | ram32xsdp #(.WIDTH(LOW_ADDDR_BITS)) tag_waddr( 56 | .wclk(s_ul_clk), 57 | .we(ul_ml_rvalid), 58 | .waddr(ul_ml_rtag), 59 | .datai(ul_ml_rlocaddr), 60 | .raddr(pcie_rtag_rd), 61 | .datao(buffer_burst_cpld_addr) 62 | ); 63 | 64 | localparam ST_W0 = 0; 65 | localparam ST_W1 = 1; 66 | reg state; 67 | 68 | assign ul_ml_rready = m_axis_tx_tready && state; 69 | 70 | wire [31:2] pcie_addr = { ul_ml_rbusaddr, 1'b0 }; 71 | wire [7:0] pcie_tag = ul_ml_rtag; 72 | wire [9:0] pcie_length = { ul_ml_rlength + 1'b1, 1'b0 }; 73 | 74 | wire [1:0] cfg_pcie_attr = 0; 75 | 76 | always @(posedge s_ul_clk) begin 77 | if (~s_ul_aresetn) begin 78 | state <= 1'b0; 79 | m_axis_tx_tvalid <= 1'b0; 80 | end else begin 81 | 82 | case (state) 83 | ST_W0: begin 84 | if (ul_ml_rvalid && (!m_axis_tx_tvalid || m_axis_tx_tvalid && m_axis_tx_tready) ) begin 85 | m_axis_tx_tdata[63:32] <= { cfg_pcie_reqid, pcie_tag, 8'hff}; 86 | m_axis_tx_tdata[31:0] <= { 16'h00_00, 2'b00, cfg_pcie_attr, pcie_length }; 87 | m_axis_tx_tkeep <= 8'hff; 88 | m_axis_tx_tlast <= 1'b0; 89 | m_axis_tx_tvalid <= 1'b1; 90 | state <= state + 1; 91 | end else if (m_axis_tx_tvalid && m_axis_tx_tready) begin 92 | m_axis_tx_tvalid <= 1'b0; 93 | end 94 | end 95 | 96 | ST_W1: begin 97 | if (m_axis_tx_tready) begin 98 | m_axis_tx_tdata[31:0] <= {pcie_addr, 2'b0}; 99 | m_axis_tx_tkeep <= 8'h0f; 100 | m_axis_tx_tlast <= 1'b1; 101 | m_axis_tx_tvalid <= 1'b1; 102 | state <= state + 1; 103 | end 104 | end 105 | 106 | endcase 107 | 108 | end 109 | end 110 | 111 | 112 | assign ul_ml_tvalid = pcie_rtag_rd_latch; 113 | assign ul_ml_ttag = pcie_rtag_rd; 114 | 115 | 116 | localparam CPL_FMT_TYPE = 7'b00_01010; // 3DW 117 | localparam CPL_DATA_FMT_TYPE = 7'b10_01010; // 3DW + data 118 | localparam MEM_WR32_FMT_TYPE = 7'b10_00000; // 3DW + data 119 | 120 | localparam ST_RX_TLP_HDR = 0; 121 | localparam ST_RX_TLP_W0 = 1; 122 | localparam ST_RX_TLP_WBULK = 2; 123 | localparam ST_RX_TLP_SKIP = 3; 124 | 125 | 126 | reg [1:0] dma_rx_state; 127 | 128 | reg [31:0] tmp_axis_rx_data_wrap; 129 | 130 | wire [6:0] tlp_type = s_axis_rx_tdata[30:24]; 131 | wire tlp_ep = s_axis_rx_tdata[14]; 132 | wire tlp_dp = s_axis_rx_tdata[15]; 133 | wire [3:0] tlp_ldwbe = s_axis_rx_tdata[39:36]; 134 | wire [3:0] tlp_fdwbe = s_axis_rx_tdata[35:32]; 135 | wire [2:0] cpld_status_bits = s_axis_rx_tdata[47:45]; 136 | 137 | reg first_word; 138 | 139 | assign s_axis_rx_tready = 1'b1; 140 | 141 | 142 | reg pcie_last_cpld_packet; 143 | 144 | assign pcie_rtag_rd = s_axis_rx_tdata[REQ_TAG_BITS - 1 + 8:8]; 145 | wire pcie_rtag_rd_pres = (dma_rx_state == ST_RX_TLP_W0) && s_axis_rx_tvalid && s_axis_rx_tready; 146 | assign pcie_rtag_rd_latch = pcie_rtag_rd_pres && pcie_last_cpld_packet; 147 | 148 | //reg buffer_burst_cpld_lastreq_reg; 149 | reg [10:1] data_remain; 150 | reg last_burst_in_buffer; 151 | 152 | wire [63:0] pcie_to_fifo; 153 | bsswap bs0(.in(s_axis_rx_tdata[31:0]), .out(pcie_to_fifo[31:0])); 154 | bsswap bs1(.in(s_axis_rx_tdata[63:32]), .out(pcie_to_fifo[63:32])); 155 | 156 | 157 | reg [7:0] invalid_cpld; 158 | reg [7:0] cpl_stat_ur; 159 | reg [7:0] cpl_stat_csr; 160 | reg [7:0] cpl_stat_ca; 161 | 162 | localparam CPL_UR = 3'b001; 163 | localparam CPL_CSR = 3'b010; 164 | localparam CPL_CA = 3'b100; 165 | 166 | reg [LOW_ADDDR_BITS-1:0] fifo_wr_addr; 167 | reg [63:0] fifo_data_in; 168 | reg fifo_wr_en_rx; 169 | 170 | reg pcie_cpl_trans; 171 | 172 | always @(posedge s_ul_clk) begin 173 | if (txdma_active) begin 174 | fifo_wr_addr <= 0; 175 | 176 | fifo_wr_en_rx <= 1'b0; 177 | 178 | dma_rx_state <= ST_RX_TLP_HDR; 179 | 180 | invalid_cpld <= 0; 181 | cpl_stat_ur <= 0; 182 | cpl_stat_csr <= 0; 183 | cpl_stat_ca <= 0; 184 | end else begin 185 | case (dma_rx_state) 186 | ST_RX_TLP_HDR: begin 187 | //pcie_rx_valid <= 1'b0; 188 | fifo_wr_en_rx <= 1'b0; 189 | 190 | if (s_axis_rx_tready && s_axis_rx_tvalid) begin 191 | // Last CplD packet is when Length == ByteCount >> 2, garbage on MemWr 192 | pcie_last_cpld_packet <= (s_axis_rx_tdata[9:0] == s_axis_rx_tdata[32+2+9:32+2]); 193 | data_remain[9:1] <= s_axis_rx_tdata[32+2+9:32+2+1]; 194 | data_remain[10] <= (s_axis_rx_tdata[32+2+9:32+2+1] == 9'b0) ? 1'b1 : 1'b0; 195 | //pcie_rx_length_qw[9:1]<= s_axis_rx_tdata[9:1]; 196 | 197 | if (tlp_ep == 1'b0 && 198 | (/*fifo_dma_en &&*/ tlp_type == CPL_DATA_FMT_TYPE || /*~fifo_dma_en &&*/ tlp_fdwbe == 4'hF && tlp_type == MEM_WR32_FMT_TYPE)) begin 199 | pcie_cpl_trans <= (tlp_type == CPL_DATA_FMT_TYPE); 200 | dma_rx_state <= ST_RX_TLP_W0; 201 | end else begin 202 | // Log type of abortion 203 | if (tlp_type == CPL_FMT_TYPE) begin 204 | if (cpld_status_bits & CPL_UR) begin 205 | cpl_stat_ur <= cpl_stat_ur + 1'b1; 206 | end 207 | if (cpld_status_bits & CPL_CSR) begin 208 | cpl_stat_csr <= cpl_stat_csr + 1'b1; 209 | end 210 | if (cpld_status_bits & CPL_CA) begin 211 | cpl_stat_ca <= cpl_stat_ca + 1'b1; 212 | end 213 | end 214 | 215 | invalid_cpld <= invalid_cpld + 1'b1; 216 | dma_rx_state <= ST_RX_TLP_SKIP; 217 | end 218 | 219 | end 220 | end 221 | 222 | ST_RX_TLP_W0: begin 223 | if (s_axis_rx_tready && s_axis_rx_tvalid) begin 224 | tmp_axis_rx_data_wrap <= pcie_to_fifo[63:32]; 225 | dma_rx_state <= ST_RX_TLP_WBULK; 226 | 227 | // For PCIe write 228 | // load fifo_wr_addr 229 | if (/*~fifo_dma_en*/ ~pcie_cpl_trans) begin 230 | fifo_wr_addr <= s_axis_rx_tdata[LOW_ADDDR_BITS+2:3]; 231 | end else begin 232 | fifo_wr_addr <= buffer_burst_cpld_addr - data_remain; 233 | end 234 | 235 | first_word <= 1'b0; 236 | end 237 | end 238 | 239 | ST_RX_TLP_WBULK: begin 240 | if (s_axis_rx_tready && s_axis_rx_tvalid) begin 241 | fifo_data_in[31:0] <= tmp_axis_rx_data_wrap; 242 | fifo_data_in[63:32] <= pcie_to_fifo[31:0]; 243 | tmp_axis_rx_data_wrap <= pcie_to_fifo[63:32]; 244 | 245 | fifo_wr_en_rx <= 1'b1; 246 | fifo_wr_addr <= fifo_wr_addr + first_word; 247 | first_word <= 1'b1; 248 | if (s_axis_rx_tlast) begin 249 | dma_rx_state <= ST_RX_TLP_HDR; 250 | end 251 | end else begin 252 | fifo_wr_en_rx <= 1'b0; 253 | end 254 | end 255 | 256 | ST_RX_TLP_SKIP: begin 257 | // Write metada for next burst 258 | if (s_axis_rx_tready && s_axis_rx_tvalid && s_axis_rx_tlast) begin 259 | dma_rx_state <= ST_RX_TLP_HDR; 260 | end 261 | end 262 | endcase 263 | 264 | end 265 | end 266 | 267 | 268 | assign m_ram_tdata = fifo_data_in; 269 | assign m_ram_taddr = fifo_wr_addr; 270 | assign m_ram_tvalid = fifo_wr_en_rx; 271 | 272 | endmodule 273 | -------------------------------------------------------------------------------- /lib/i2c/ll_i2c_dmastere.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module ll_i2c_dmastere #( 7 | parameter I2C_SPEED = 100000, 8 | parameter BUS_SPEED = 62500000, 9 | parameter CLK_DIV_BITS = 12, 10 | parameter RD_BITS_MAX = 3 11 | )( 12 | input reset, 13 | input axis_clk, 14 | 15 | // BUS 1 16 | input sda1_in, 17 | output sda1_out_eo, 18 | output scl1_out_eo, 19 | 20 | // BUS 2 21 | input sda2_in, 22 | output sda2_out_eo, 23 | output scl2_out_eo, 24 | 25 | input [7:0] axis_tx_data, 26 | input axis_tx_last, 27 | input axis_tx_valid, 28 | input [RD_BITS_MAX:0] axis_tx_user, 29 | // [3:1] Number of bytes to read 0==1, 1==2, etc. 30 | // [0] Bus number 31 | output axis_tx_ready, 32 | 33 | output [7:0] axis_rx_data, 34 | output axis_rx_last, 35 | output axis_rx_valid, 36 | input axis_rx_ready, 37 | 38 | output reg cmd_error 39 | ); 40 | 41 | reg i2c_bus_sel; 42 | reg dss_bus_sel; 43 | 44 | // Bus logic selector 45 | wire sda_in = (dss_bus_sel) ? sda2_in : sda1_in; 46 | wire sda_out_eo; 47 | wire scl_out_eo; 48 | 49 | localparam SDA_OUT_HIGH = 0; 50 | localparam SDA_OUT_LOW = 1; 51 | 52 | localparam SCL_OUT_HIGH = 0; 53 | localparam SCL_OUT_LOW = 1; 54 | 55 | assign sda1_out_eo = (dss_bus_sel) ? SDA_OUT_HIGH : sda_out_eo; 56 | assign scl1_out_eo = (dss_bus_sel) ? SCL_OUT_HIGH : scl_out_eo; 57 | assign sda2_out_eo = (dss_bus_sel) ? sda_out_eo : SDA_OUT_HIGH; 58 | assign scl2_out_eo = (dss_bus_sel) ? scl_out_eo : SCL_OUT_HIGH; 59 | 60 | // Clock divider block 61 | reg [CLK_DIV_BITS-1:0] clk_div; 62 | reg [1:0] clk_state; 63 | reg clk_state_lo_prev; 64 | 65 | always @(posedge axis_clk) begin 66 | if (reset) begin 67 | clk_div <= 0; 68 | clk_state <= 0; 69 | clk_state_lo_prev <= 0; 70 | end else begin 71 | if (clk_div == ((BUS_SPEED/I2C_SPEED - 1)/4)) begin 72 | clk_state <= clk_state + 1; 73 | clk_div <= 0; 74 | end else begin 75 | clk_div <= clk_div + 1; 76 | end 77 | 78 | clk_state_lo_prev <= clk_state[0]; 79 | end 80 | end 81 | 82 | wire state_strobe = (clk_state_lo_prev != clk_state[0]); 83 | 84 | // Symbol serialyzer block 85 | localparam LLS_IDLE = 0; 86 | localparam LLS_START = 1; 87 | localparam LLS_STOP = 2; 88 | localparam LLS_TX_BIT_0 = 3; 89 | localparam LLS_TX_BIT_1 = 4; 90 | localparam LLS_RX_BIT = 5; 91 | localparam LLS_REPSTART = 6; 92 | 93 | reg scl_out_eo_reg; 94 | reg sda_out_eo_reg; 95 | 96 | 97 | reg [2:0] ll_sym; 98 | wire nxt_sym = (state_strobe && clk_state == 3); 99 | reg ll_rx_cap; // Captured RX-bit 100 | 101 | assign sda_out_eo = sda_out_eo_reg; 102 | assign scl_out_eo = scl_out_eo_reg; 103 | 104 | always @(posedge axis_clk) begin 105 | if (reset) begin 106 | scl_out_eo_reg <= SCL_OUT_HIGH; 107 | sda_out_eo_reg <= SDA_OUT_HIGH; 108 | dss_bus_sel <= 0; 109 | //ll_ready <= 1'b0; 110 | end else if (state_strobe) begin 111 | case (clk_state) 112 | 0: begin 113 | //dss_bus_sel <= i2c_bus_sel; 114 | if (ll_sym == LLS_REPSTART || ll_sym == LLS_TX_BIT_1 || ll_sym == LLS_RX_BIT) begin 115 | sda_out_eo_reg <= SCL_OUT_HIGH; 116 | end else if (ll_sym == LLS_STOP || ll_sym == LLS_TX_BIT_0) begin 117 | sda_out_eo_reg <= SCL_OUT_LOW; 118 | end 119 | end 120 | 121 | 1: begin 122 | if (ll_sym != LLS_IDLE) begin 123 | scl_out_eo_reg <= SCL_OUT_HIGH; 124 | end 125 | end 126 | 127 | 2: begin 128 | if (ll_sym == LLS_START || ll_sym == LLS_REPSTART) begin 129 | sda_out_eo_reg <= SDA_OUT_LOW; 130 | end else if (ll_sym == LLS_STOP) begin 131 | sda_out_eo_reg <= SDA_OUT_HIGH; 132 | end else if (ll_sym == LLS_RX_BIT) begin 133 | ll_rx_cap <= sda_in; 134 | end 135 | end 136 | 137 | 3: begin 138 | dss_bus_sel <= i2c_bus_sel; 139 | if (ll_sym != LLS_STOP && ll_sym != LLS_IDLE) begin 140 | scl_out_eo_reg <= SCL_OUT_LOW; 141 | end 142 | end 143 | 144 | endcase 145 | end 146 | end 147 | 148 | 149 | // Data stream serialyzer 150 | localparam DSS_IDLE = 0; 151 | localparam DSS_START = 1; 152 | localparam DSS_ADDR = 2; 153 | localparam DSS_AACK = 3; // ACK by Device 154 | localparam DSS_WDATA = 4; // Wait for next data frame while waiting for ACK 155 | localparam DSS_TACK = 5; // ACK by Device Analyze and send 7th but 156 | localparam DSS_TXD = 6; 157 | localparam DSS_RXD_RACK = 7; 158 | localparam DSS_RDATA = 8; // Wait for data to be read 159 | localparam DSS_RREP = 9; // ACK by Master 160 | localparam DSS_STOP = 10; 161 | 162 | localparam DSS_FAILED = 11; //Transaction aborted by device 163 | 164 | 165 | reg [2:0] bit_counter; 166 | 167 | reg [3:0] dss_state; 168 | reg dss_mode_r; 169 | reg dss_last_tx; 170 | reg [RD_BITS_MAX-1:0] dss_rx_cntr; 171 | 172 | reg [7:0] rx_data; 173 | reg [7:0] out_data; 174 | assign axis_tx_ready = ~nxt_sym && ((dss_state == DSS_IDLE) || (dss_state == DSS_WDATA) || (dss_state == DSS_FAILED)); 175 | assign axis_rx_data = rx_data; 176 | assign axis_rx_valid = ~nxt_sym && (dss_state == DSS_RDATA); 177 | assign axis_rx_last = (dss_rx_cntr == 0); 178 | 179 | always @(posedge axis_clk) begin 180 | if (reset) begin 181 | dss_state <= DSS_IDLE; 182 | i2c_bus_sel <= 0; // Make debug easier 183 | cmd_error <= 0; 184 | end else begin 185 | if (nxt_sym) begin 186 | case (dss_state) 187 | DSS_IDLE: begin 188 | ll_sym <= LLS_IDLE; 189 | end 190 | 191 | DSS_START: begin 192 | ll_sym <= LLS_START; 193 | dss_state <= DSS_ADDR; 194 | bit_counter <= 0; 195 | cmd_error <= 0; 196 | end 197 | 198 | DSS_ADDR, DSS_TXD: begin 199 | ll_sym <= (out_data[7]) ? LLS_TX_BIT_1 : LLS_TX_BIT_0; 200 | 201 | out_data[7:1] <= out_data[6:0]; 202 | bit_counter <= bit_counter + 1'b1; 203 | 204 | if (bit_counter == 7) begin 205 | if (dss_state == DSS_ADDR) begin 206 | dss_mode_r <= out_data[7]; 207 | end 208 | dss_state <= DSS_AACK; 209 | end 210 | end 211 | 212 | DSS_AACK: begin 213 | ll_sym <= LLS_RX_BIT; 214 | if (dss_mode_r) begin 215 | dss_state <= DSS_TACK; 216 | end else begin 217 | dss_state <= DSS_WDATA; 218 | end 219 | end 220 | 221 | DSS_WDATA, DSS_TACK: begin 222 | if (dss_last_tx && ~dss_mode_r) begin 223 | dss_state <= DSS_IDLE; 224 | ll_sym <= LLS_STOP; 225 | end else if (ll_rx_cap) begin // NACK by device 226 | dss_state <= DSS_FAILED; 227 | ll_sym <= LLS_STOP; 228 | end else if (dss_mode_r) begin 229 | dss_state <= DSS_RXD_RACK; 230 | ll_sym <= LLS_RX_BIT; 231 | end else if (dss_state == DSS_TACK) begin 232 | ll_sym <= LLS_IDLE; 233 | dss_state <= DSS_TXD; 234 | end else begin 235 | ll_sym <= LLS_IDLE; 236 | end 237 | end 238 | 239 | DSS_RXD_RACK: begin 240 | ll_sym <= LLS_RX_BIT; 241 | rx_data[7:0] <= {rx_data[6:0], ll_rx_cap}; 242 | bit_counter <= bit_counter + 1'b1; 243 | 244 | if (bit_counter == 7) begin 245 | if (dss_rx_cntr == 0) begin 246 | ll_sym <= LLS_TX_BIT_1; //NACK by master, stop transaction 247 | end else begin 248 | ll_sym <= LLS_TX_BIT_0; //ACK by master 249 | end 250 | dss_state <= DSS_RDATA; 251 | end 252 | end 253 | 254 | DSS_RDATA: begin 255 | ll_sym <= LLS_IDLE; 256 | end 257 | 258 | DSS_RREP: begin 259 | ll_sym <= LLS_RX_BIT; 260 | dss_state <= DSS_RXD_RACK; 261 | end 262 | 263 | DSS_STOP: begin 264 | ll_sym <= LLS_STOP; 265 | dss_state <= DSS_IDLE; 266 | end 267 | 268 | default: begin 269 | ll_sym <= DSS_IDLE; 270 | cmd_error <= 1'b1; 271 | if (dss_last_tx) begin 272 | if (dss_mode_r) begin 273 | //Raise data ready 274 | dss_rx_cntr <= 0; 275 | dss_state <= DSS_RDATA; 276 | end else begin 277 | dss_state <= DSS_IDLE; 278 | end 279 | end 280 | end 281 | 282 | endcase 283 | end else begin 284 | if (axis_rx_ready && axis_rx_valid) begin 285 | if (dss_rx_cntr == 0) begin 286 | dss_state <= DSS_STOP; 287 | end else begin 288 | dss_state <= DSS_RREP; 289 | end 290 | dss_rx_cntr <= dss_rx_cntr - 1; 291 | end 292 | 293 | if (axis_tx_ready && axis_tx_valid) begin 294 | out_data <= axis_tx_data; 295 | dss_last_tx <= axis_tx_last; 296 | 297 | if (dss_state == DSS_IDLE) begin 298 | dss_state <= DSS_START; 299 | i2c_bus_sel <= axis_tx_user[0]; 300 | dss_rx_cntr <= axis_tx_user[RD_BITS_MAX:1]; 301 | end else begin 302 | dss_state <= DSS_TACK; 303 | end 304 | end 305 | 306 | end 307 | end 308 | end 309 | 310 | 311 | endmodule 312 | -------------------------------------------------------------------------------- /lib/xtrx/xtrxll_regs.vh: -------------------------------------------------------------------------------- 1 | // 2 | // Port constant that used in driver and in FPGA code 3 | // 4 | 5 | //WR 6 | localparam GP_PORT_WR_SPI_LMS7_0 = 0; 7 | localparam GP_PORT_WR_INT_PCIE = 1; 8 | localparam GP_PORT_WR_DAC_SPI = 2; 9 | localparam GP_PORT_WR_TMP102 = 3; 10 | 11 | localparam GP_PORT_WR_UART_TX = 4; 12 | localparam GP_PORT_WR_SIM_TX = 5; 13 | localparam GP_PORT_WR_SIM_CTRL = 6; 14 | localparam GP_PORT_WR_LMS_CTRL = 7; 15 | 16 | localparam GP_PORT_WR_TXDMA_CNF_L = 8; 17 | localparam GP_PORT_WR_TXDMA_CNF_T = 9; 18 | localparam GP_PORT_WR_TCMD_D = 10; 19 | localparam GP_PORT_WR_TCMD_T = 11; 20 | 21 | localparam GP_PORT_WR_RXDMA_CNFRM = 12; 22 | localparam GP_PORT_WR_RXTXDMA = 13; 23 | localparam GP_PORT_WR_TXMMCM = 14; 24 | localparam GP_PORT_WR_RF_SWITCHES = 15; 25 | 26 | localparam GP_PORT_WR_QSPI_EXCMD = 16; 27 | localparam GP_PORT_WR_QSPI_CMD = 17; 28 | localparam GP_PORT_WR_MEM_CTRL = 18; 29 | localparam GP_PORT_WR_USB_CTRL = 19; 30 | 31 | localparam GP_PORT_WR_USB_FIFO_CTRL = 20; 32 | localparam GP_PORT_WR_USB_FIFO_PTRS = 21; 33 | localparam GP_PORT_WR_FE_CMD = 22; 34 | localparam GP_PORT_WR_PPS_CMD = 23; 35 | 36 | localparam GP_PORT_WR_GPIO_FUNC = 24; 37 | localparam GP_PORT_WR_GPIO_DIR = 25; 38 | localparam GP_PORT_WR_GPIO_OUT = 26; 39 | localparam GP_PORT_WR_GPIO_CS = 27; 40 | 41 | localparam GP_PORT_WR_GLOBCMDR0 = 28; 42 | localparam GP_PORT_WR_GLOBCMDR1 = 29; 43 | localparam GP_PORT_WR_GPIO_SPI = 30; 44 | 45 | 46 | //RD 47 | localparam GP_PORT_RD_SPI_LMS7_0 = 0; 48 | localparam GP_PORT_RD_INTERRUPTS = 1; 49 | localparam GP_PORT_RD_ONEPPS = 2; 50 | localparam GP_PORT_RD_TMP102 = 3; 51 | 52 | localparam GP_PORT_RD_UART_RX = 4; 53 | localparam GP_PORT_RD_SIM_RX = 5; 54 | localparam GP_PORT_RD_SIM_STAT = 6; 55 | localparam GP_PORT_RD_MCU_STAT = 7; 56 | 57 | localparam GP_PORT_RD_TXDMA_STAT = 8; 58 | localparam GP_PORT_RD_TXDMA_STATM = 9; 59 | localparam GP_PORT_RD_TXDMA_STATTS= 10; 60 | localparam GP_PORT_RD_TXDMA_ST_CPL= 11; 61 | 62 | localparam GP_PORT_RD_RXDMA_STAT = 12; 63 | localparam GP_PORT_RD_RXDMA_STATTS= 13; 64 | localparam GP_PORT_RD_TXMMCM = 14; 65 | localparam GP_PORT_RD_TCMDSTAT = 15; 66 | 67 | localparam GP_PORT_RD_QSPI_RB = 16; 68 | localparam GP_PORT_RD_QSPI_STAT = 17; 69 | localparam GP_PORT_RD_MEM_RB = 18; 70 | localparam GP_PORT_RD_MCU_DEBUG = 19; 71 | 72 | localparam GP_PORT_RD_REF_OSC = 20; 73 | localparam GP_PORT_RD_RXIQ_MISS = 21; 74 | localparam GP_PORT_RD_RXIQ_ODD = 22; 75 | localparam GP_PORT_RD_GPIO_SPI = 23; 76 | 77 | localparam GP_PORT_RD_USB_RB = 24; 78 | localparam GP_PORT_RD_RXIQ_PERIOD = 25; 79 | localparam GP_PORT_RD_HWCFG = 26; 80 | localparam GP_PORT_RD_GPIO_IN = 27; 81 | 82 | localparam GP_PORT_RD_GTIME_SEC = 28; 83 | localparam GP_PORT_RD_GTIME_FRAC = 29; 84 | localparam GP_PORT_RD_GTIME_OFF = 30; 85 | localparam GP_PORT_RD_USB_DEBUG = 31; 86 | 87 | localparam GP_PORT_RD_USB_EP0_O = 32; 88 | localparam GP_PORT_RD_USB_EP1_O = 32 + 1; 89 | localparam GP_PORT_RD_USB_EP2_O = 32 + 2; 90 | localparam GP_PORT_RD_USB_EP3_O = 32 + 3; 91 | localparam GP_PORT_RD_USB_EP4_O = 32 + 4; 92 | localparam GP_PORT_RD_USB_EP5_O = 32 + 5; 93 | localparam GP_PORT_RD_USB_EP6_O = 32 + 6; 94 | localparam GP_PORT_RD_USB_EP7_O = 32 + 7; 95 | localparam GP_PORT_RD_USB_EP8_O = 32 + 8; 96 | localparam GP_PORT_RD_USB_EP9_O = 32 + 9; 97 | localparam GP_PORT_RD_USB_EP10_O = 32 + 10; 98 | localparam GP_PORT_RD_USB_EP11_O = 32 + 11; 99 | localparam GP_PORT_RD_USB_EP12_O = 32 + 12; 100 | localparam GP_PORT_RD_USB_EP13_O = 32 + 13; 101 | localparam GP_PORT_RD_USB_EP14_O = 32 + 14; 102 | localparam GP_PORT_RD_USB_EP15_O = 32 + 15; 103 | 104 | localparam GP_PORT_RD_USB_EP0_I = 48; 105 | localparam GP_PORT_RD_USB_EP1_I = 48 + 1; 106 | localparam GP_PORT_RD_USB_EP2_I = 48 + 2; 107 | localparam GP_PORT_RD_USB_EP3_I = 48 + 3; 108 | localparam GP_PORT_RD_USB_EP4_I = 48 + 4; 109 | localparam GP_PORT_RD_USB_EP5_I = 48 + 5; 110 | localparam GP_PORT_RD_USB_EP6_I = 48 + 6; 111 | localparam GP_PORT_RD_USB_EP7_I = 48 + 7; 112 | localparam GP_PORT_RD_USB_EP8_I = 48 + 8; 113 | localparam GP_PORT_RD_USB_EP9_I = 48 + 9; 114 | localparam GP_PORT_RD_USB_EP10_I = 48 + 10; 115 | localparam GP_PORT_RD_USB_EP11_I = 48 + 11; 116 | localparam GP_PORT_RD_USB_EP12_I = 48 + 12; 117 | localparam GP_PORT_RD_USB_EP13_I = 48 + 13; 118 | localparam GP_PORT_RD_USB_EP14_I = 48 + 14; 119 | localparam GP_PORT_RD_USB_EP15_I = 48 + 15; 120 | 121 | // WR bus routing 122 | localparam UL_GP_ADDR = 0; 123 | localparam UL_MCU_ADDR = 256; 124 | localparam UL_RXDMA_ADDR = 512; 125 | localparam UL_TXDMA_ADDR = 768; 126 | 127 | localparam UL_RD_MEM_ADDR = 512; 128 | 129 | 130 | // Bits in GP_PORT_LMS_CTRL 131 | localparam GP_PORT_LMS_CTRL_DIGRESET = 0; 132 | localparam GP_PORT_LMS_CTRL_RESET = 1; 133 | localparam GP_PORT_LMS_CTRL_GPWR = 2; 134 | localparam GP_PORT_LMS_CTRL_RXEN = 3; 135 | localparam GP_PORT_LMS_CTRL_TXEN = 4; 136 | 137 | localparam GP_PORT_LMS_FCLK_RX_GEN = 6; 138 | localparam GP_PORT_LMS_RX_TERM_DIS = 7; 139 | 140 | localparam GP_PORT_XTRX_ENBPVIO_N = 8; 141 | localparam GP_PORT_XTRX_ENBP3V3_N = 9; 142 | localparam GP_PORT_XTRX_EXT_CLK = 10; 143 | localparam GP_PORT_XTRX_PD_TCXO = 11; 144 | localparam GP_PORT_XTRX_ENGPS = 12; 145 | localparam GP_PORT_XTRX_VCCSEL = 13; 146 | localparam GP_PORT_XTRX_ENSMDIG = 14; 147 | localparam GP_PORT_XTRX_ALTI2CLUT = 15; 148 | 149 | 150 | // Bits in GP_PORT_RD_SIM_RX / GP_PORT_RD_UART_RX / GP_PORT_RD_SIM_STAT 151 | localparam UART_FIFORX_PARERR = 14; 152 | localparam UART_FIFORX_EMPTY = 15; 153 | 154 | localparam UART_FIFOTX_USED_OFF = 16; 155 | localparam UART_FIFOTX_USED_BITS = 5; 156 | localparam UART_FIFOTX_EMPTY = 21; 157 | 158 | // Bits in GP_PORT_WR_SIM_CTRL 159 | localparam WR_SIM_CTRL_RESET = 0; 160 | localparam WR_SIM_CTRL_ENABLE = 1; 161 | localparam WR_SIM_CTRL_33V = 2; 162 | 163 | // Bits in GP_PORT_WR_TXMMCM 164 | 165 | localparam GP_PORT_DRP_ADDR_OFF = 16; 166 | localparam GP_PORT_DRP_ADDR_BITS = 7; 167 | localparam GP_PORT_DRP_REGEN = 23; 168 | localparam GP_PORT_DRP_REGWR = 24; 169 | localparam GP_PORT_DRP_GPIO_OFF = 25; 170 | localparam GP_PORT_DRP_NUM_OFF = 30; 171 | 172 | //localparam GP_PORT_TXMMCM_REGEN = 23; 173 | //localparam GP_PORT_TXMMCM_REGWR = 24; 174 | //localparam GP_PORT_TXMMCM_CLKSEL = 25; 175 | //localparam GP_PORT_TXMMCM_RESET = 26; 176 | //localparam GP_PORT_TXMMCM_PWRDOWN = 27; 177 | // Bits in GP_PORT_RD_TXMMCM 178 | 179 | //localparam GP_PORT_TXMMCM_LOCKED = 28; 180 | //localparam GP_PORT_TXMMCM_RDY = 29; 181 | //localparam GP_PORT_TXMMCM_STOPPED = 30; 182 | //localparam GP_PORT_TXMMCM_STOPPEDF= 31; 183 | 184 | 185 | localparam GP_PORT_IN_DRP0 = 16; 186 | localparam GP_PORT_IN_DRP1 = 20; 187 | localparam GP_PORT_IN_DRP2 = 24; 188 | localparam GP_PORT_IN_DRP3 = 28; 189 | 190 | localparam GP_PORT_IN_MMCM_LOCKED = 0; 191 | localparam GP_PORT_IN_MMCM_STOPPED = 1; 192 | localparam GP_PORT_IN_MMCM_STOPPEDF= 2; 193 | 194 | localparam GP_PORT_OUT_MMCM_CLKSEL1 = 0; 195 | localparam GP_PORT_OUT_MMCM_RESET = 1; 196 | localparam GP_PORT_OUT_MMCM_PWRDOWN = 2; 197 | 198 | 199 | //localparam GP_PORT_TXMMCM_LOCKED = 28; 200 | //localparam GP_PORT_TXMMCM_RDY = 29; 201 | //localparam GP_PORT_TXMMCM_STOPPED = 30; 202 | //localparam GP_PORT_TXMMCM_STOPPEDF= 31; 203 | 204 | localparam DRP_PORT_MMCM_TX = 0; 205 | localparam DRP_PORT_MMCM_RX = 1; 206 | localparam DRP_PORT_MMCM_PCIE = 2; 207 | 208 | // Formats for RX/TX DMA 209 | localparam FMT_STOP = 0; 210 | localparam FMT_8BIT = 1; 211 | localparam FMT_12BIT = 2; 212 | localparam FMT_16BIT = 3; 213 | 214 | localparam WR_RXDMA_FE_FMT_OFF = 0; 215 | localparam WR_RXDMA_FE_DECIM_OFF = 2; 216 | localparam WR_RXDMA_FE_PAUSED = 4; 217 | localparam WR_RXDMA_FE_RESET = 5; 218 | localparam WR_RXDMA_FE_SISO = 6; 219 | 220 | 221 | localparam GP_PORT_TXDMA_CTRL_MODE_REP = 2; 222 | localparam GP_PORT_TXDMA_CTRL_MODE_SISO = 3; 223 | localparam GP_PORT_TXDMA_CTRL_MODE_INTER_OFF = 4; 224 | localparam GP_PORT_TXDMA_CTRL_RESET_BUFS = 7; 225 | 226 | 227 | localparam GP_PORT_WR_RXTXDMA_RXOFF = 20; 228 | localparam GP_PORT_WR_RXTXDMA_RXV = 30; 229 | localparam GP_PORT_WR_RXTXDMA_TXV = 31; 230 | 231 | 232 | localparam INT_1PPS = 0; 233 | localparam INT_DMA_TX = 1; 234 | localparam INT_DMA_RX = 2; 235 | localparam INT_RFIC0_SPI = 3; 236 | localparam INT_GPS_UART_TX = 4; 237 | localparam INT_GPS_UART_RX = 5; 238 | localparam INT_SIM_UART_TX = 6; 239 | localparam INT_SIM_UART_RX = 7; 240 | localparam INT_I2C = 8; 241 | localparam INT_NCMD = 9; 242 | localparam INT_DMA_RX_OVF = 10; 243 | 244 | localparam INT_COUNT = 11; 245 | 246 | 247 | localparam INT_PCIE_I_FLAG = 15; 248 | 249 | localparam INT_PCIE_E_NO_RX_DMA_FLOW = 24; 250 | localparam INT_PCIE_E_RX_SEP_OVF_INT = 25; 251 | 252 | localparam INT_PCIE_E_OVRD = 30; 253 | localparam INT_PCIE_E_FLAG = 31; 254 | 255 | 256 | //localparam TIMED_COMMANDS 257 | localparam TC_TS_BITS = 30; 258 | localparam TC_ROUTE_BITS = 2; 259 | localparam TC_DATA_BITS = 4; 260 | 261 | 262 | 263 | localparam TC_ROUTE_RX_FRM = 0; 264 | 265 | 266 | localparam RD_TCMDSTAT_FIFOREADY = 5; 267 | 268 | 269 | localparam MCU_CTRL_VALID = 8; 270 | localparam MCU_CTRL_RESET = 9; 271 | localparam MCU_CTRL_SUSP = 10; 272 | localparam MCU_CTRL_REGSEL = 11; 273 | localparam MCU_CTRL_PAGESEL = 16; 274 | 275 | 276 | localparam MCU_STAT_FIFO_EMPTY = 8; 277 | localparam MCU_STAT_CPU_STOP = 9; 278 | localparam MCU_STAT_PC = 10; 279 | 280 | 281 | 282 | -------------------------------------------------------------------------------- /lib/lms7/lms7_rx_frm_brst.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | // Register format 6 | // 0: [1:0] Stop/8bit/12bit/16bit 7 | // 1: [3:0] TX frontend buffering (min) 8 | 9 | module lms7_rx_frm_brst #( 10 | parameter MAX_BURST_BITS = 14, 11 | parameter TS_BITS = 30 12 | )( 13 | input fe_reset, 14 | 15 | // AXI 16 | output reg [7:0] axis_tx_tkeep, 17 | output reg [63:0] axis_tx_tdata, 18 | output reg axis_tx_tvalid, 19 | output reg axis_tx_tlast, 20 | 21 | // Current time in RXFE domain 22 | output [TS_BITS-1:0] ts_current, 23 | 24 | // LMS7 25 | input [11:0] in_sdr_ai, 26 | input [11:0] in_sdr_aq, 27 | input [11:0] in_sdr_bi, 28 | input [11:0] in_sdr_bq, 29 | input in_sdr_valid, 30 | input in_sdr_clk, 31 | 32 | // LEGACY CONFIGURATION 33 | input in_mode_siso, 34 | input [1:0] in_fmt, 35 | input [1:0] decim_rate, 36 | 37 | // Modern configuration port 38 | input [31:0] fe_cmd_data, 39 | input fe_cmd_valid, 40 | output fe_cmd_ready, 41 | 42 | // Cross-clock counter output 43 | input cc_rst, 44 | input cc_clk, 45 | output [31:0] cc_ts_current 46 | ); 47 | 48 | assign fe_cmd_ready = 1'b1; 49 | wire [3:0] fe_cmd_route = fe_cmd_data[31:28]; 50 | wire [27:0] fe_cmd_route_data = fe_cmd_data[27:0]; 51 | 52 | localparam FE_CMD_ROUTE_BURSTER = 0; 53 | localparam FE_CMD_ROUTE_DSP0 = 1; 54 | 55 | reg [MAX_BURST_BITS-1:0] burst_samples_sz; 56 | reg burst_throttle; 57 | reg [7:0] burst_num_send; 58 | reg [7:0] burst_num_skip; 59 | 60 | localparam FE_CMD_ROUTE_BURST_TYPE_OFF = 27; 61 | localparam FE_CMD_ROUTE_BURST_SAMPLES = 1'b0; 62 | localparam FE_CMD_ROUTE_BURST_THROTTLE = 1'b1; 63 | 64 | always @(posedge in_sdr_clk) begin 65 | if (fe_reset) begin 66 | burst_samples_sz <= 511; 67 | burst_throttle <= 0; 68 | end else begin 69 | if (fe_cmd_valid && fe_cmd_ready && (fe_cmd_route == FE_CMD_ROUTE_BURSTER)) begin 70 | case (fe_cmd_route_data[FE_CMD_ROUTE_BURST_TYPE_OFF]) 71 | FE_CMD_ROUTE_BURST_SAMPLES: begin 72 | burst_samples_sz <= fe_cmd_route_data[MAX_BURST_BITS-1:0]; 73 | end 74 | 75 | FE_CMD_ROUTE_BURST_THROTTLE: begin 76 | burst_num_skip <= fe_cmd_route_data[7:0]; 77 | burst_num_send <= fe_cmd_route_data[15:8]; 78 | burst_throttle <= fe_cmd_route_data[16]; 79 | end 80 | endcase 81 | end 82 | end 83 | end 84 | 85 | 86 | reg [MAX_BURST_BITS-1:0] fe_cur_sample; 87 | reg [7:0] fe_cur_burst; 88 | reg fe_cur_burst_state; 89 | 90 | always @(posedge in_sdr_clk) begin 91 | if (fe_reset) begin 92 | fe_cur_sample <= burst_samples_sz; 93 | fe_cur_burst <= 0; 94 | fe_cur_burst_state <= 0; 95 | end else begin 96 | if (in_sdr_valid) begin 97 | fe_cur_sample <= fe_cur_sample - 1; 98 | if (fe_cur_sample == 0) begin 99 | fe_cur_sample <= burst_samples_sz; 100 | 101 | if (burst_throttle) begin 102 | fe_cur_burst <= fe_cur_burst - 1; 103 | 104 | if (fe_cur_burst == 0) begin 105 | fe_cur_burst_state <= ~fe_cur_burst_state; 106 | if (fe_cur_burst_state == 0) begin 107 | fe_cur_burst <= burst_num_skip; 108 | end else begin 109 | fe_cur_burst <= burst_num_send; 110 | end 111 | end 112 | end 113 | end 114 | end 115 | end 116 | end 117 | 118 | wire burster_valid = in_sdr_valid && (~burst_throttle || ~fe_cur_burst_state); 119 | wire burster_last = (fe_cur_sample == 0); 120 | 121 | wire [15:0] acc_ai; 122 | wire [15:0] acc_aq; 123 | wire [15:0] acc_bi; 124 | wire [15:0] acc_bq; 125 | wire out_valid; 126 | wire out_last; 127 | 128 | `ifndef RXDSP_CORE 129 | `define RXDSP_CORE rxdsp_none 130 | `endif 131 | 132 | `RXDSP_CORE rxdsp( 133 | .clk(in_sdr_clk), 134 | .reset(fe_reset), 135 | 136 | .dspcmd_valid(fe_cmd_valid && fe_cmd_ready && (fe_cmd_route == FE_CMD_ROUTE_DSP0)), 137 | .dspcmd_data(fe_cmd_route_data), 138 | 139 | .dspcmd_legacy(decim_rate), 140 | 141 | .in_ai(in_sdr_ai), 142 | .in_aq(in_sdr_aq), 143 | .in_bi(in_sdr_bi), 144 | .in_bq(in_sdr_bq), 145 | .in_valid(burster_valid), 146 | .in_last(burster_last), 147 | 148 | .out_ai(acc_ai), 149 | .out_aq(acc_aq), 150 | .out_bi(acc_bi), 151 | .out_bq(acc_bq), 152 | .out_valid(out_valid), 153 | .out_last(out_last) 154 | ); 155 | 156 | ////////////////////////////// 157 | // Data wire packager 158 | // 159 | reg [31:0] tmp; 160 | 161 | cross_counter #( 162 | .WIDTH(TS_BITS), 163 | .GRAY_BITS(4), 164 | .OUT_WIDTH(32), 165 | .OUT_LOWER_SKIP(0) 166 | ) ts_rx ( 167 | .inrst(fe_reset), 168 | .inclk(in_sdr_clk), 169 | .incmdvalid(out_valid), 170 | .incmdinc(1'b1), 171 | .incnt(ts_current), 172 | 173 | .outrst(cc_rst), 174 | .outclk(cc_clk), 175 | .outcnt(cc_ts_current) 176 | ); 177 | 178 | 179 | reg iq_mux_valid; 180 | reg iq_mux_last; 181 | reg [15:0] iq_mux_d0_i; 182 | reg [15:0] iq_mux_d0_q; 183 | reg [15:0] iq_mux_d1_i; 184 | reg [15:0] iq_mux_d1_q; 185 | reg nxt_pkt; 186 | reg siso_last; 187 | 188 | always @(posedge in_sdr_clk) begin 189 | if (fe_reset) begin 190 | iq_mux_valid <= 0; 191 | siso_last <= 0; 192 | nxt_pkt <= 1'b1; 193 | end else if (out_valid) begin 194 | if (out_last) begin 195 | siso_last <= 0; 196 | nxt_pkt <= 1'b1; 197 | end else begin 198 | siso_last <= ~siso_last; 199 | nxt_pkt <= 1'b0; 200 | end 201 | 202 | if (in_mode_siso) begin 203 | if (~siso_last) begin 204 | iq_mux_d0_i <= acc_ai; 205 | iq_mux_d1_i <= acc_aq; 206 | end else begin 207 | iq_mux_d0_q <= acc_ai; 208 | iq_mux_d1_q <= acc_aq; 209 | end 210 | end else begin 211 | iq_mux_d0_i <= acc_ai; 212 | iq_mux_d0_q <= acc_aq; 213 | iq_mux_d1_i <= acc_bi; 214 | iq_mux_d1_q <= acc_bq; 215 | end 216 | end 217 | 218 | iq_mux_last <= out_last; 219 | iq_mux_valid <= out_valid && (~in_mode_siso || siso_last); 220 | end 221 | 222 | `include "xtrxll_regs.vh" 223 | 224 | wire [15:0] acc_i_8 = { iq_mux_d1_i[11:4], iq_mux_d0_i[11:4] }; 225 | wire [15:0] acc_q_8 = { iq_mux_d1_q[11:4], iq_mux_d0_q[11:4] }; 226 | 227 | wire [23:0] acc_i_12 = { iq_mux_d1_i[11:0], iq_mux_d0_i[11:0] }; 228 | wire [23:0] acc_q_12 = { iq_mux_d1_q[11:0], iq_mux_d0_q[11:0] }; 229 | 230 | wire [31:0] acc_i_16 = { iq_mux_d1_i, iq_mux_d0_i }; 231 | wire [31:0] acc_q_16 = { iq_mux_d1_q, iq_mux_d0_q }; 232 | 233 | wire last_in_burst = iq_mux_last; 234 | 235 | reg [1:0] nxt_transmit_state; 236 | 237 | always @(posedge in_sdr_clk) begin 238 | if (fe_reset) begin 239 | nxt_transmit_state <= 2'b0; 240 | end else begin 241 | if (iq_mux_valid) begin 242 | nxt_transmit_state <= nxt_transmit_state + 1'b1; 243 | end 244 | end 245 | end 246 | 247 | always @(posedge in_sdr_clk) begin 248 | if (in_fmt == FMT_STOP) begin 249 | axis_tx_tlast <= 0; 250 | end else begin 251 | axis_tx_tlast <= last_in_burst; 252 | end 253 | end 254 | 255 | always @(posedge in_sdr_clk) begin 256 | case (in_fmt) 257 | FMT_STOP : begin 258 | axis_tx_tvalid <= 0; 259 | end 260 | 261 | FMT_8BIT: begin 262 | axis_tx_tvalid <= (nxt_transmit_state[0] || last_in_burst) && iq_mux_valid; 263 | 264 | if (nxt_transmit_state[0] == 0) begin 265 | axis_tx_tkeep <= 8'h0f; 266 | axis_tx_tdata[15:0] <= acc_i_8; 267 | axis_tx_tdata[31:16] <= acc_q_8; 268 | end else begin 269 | axis_tx_tkeep <= 8'hff; 270 | axis_tx_tdata[47:32] <= acc_i_8; 271 | axis_tx_tdata[63:48] <= acc_q_8; 272 | end 273 | end 274 | 275 | FMT_12BIT: begin 276 | axis_tx_tvalid <= (nxt_transmit_state != 0 || last_in_burst) && iq_mux_valid; 277 | 278 | case (nxt_transmit_state) 279 | 0: begin 280 | axis_tx_tkeep <= 8'h3f; 281 | axis_tx_tdata[23:0] <= acc_i_12; 282 | axis_tx_tdata[47:24] <= acc_q_12; 283 | end 284 | 285 | 1: begin 286 | axis_tx_tkeep <= 8'hff; 287 | axis_tx_tdata[63:48] <= acc_i_12[15:0]; 288 | tmp[31:0] <= { acc_q_12, acc_i_12[23:16] }; 289 | end 290 | 291 | 2: begin 292 | axis_tx_tkeep <= 8'hff; 293 | axis_tx_tdata[31:0] <= tmp[31:0]; 294 | axis_tx_tdata[55:32] <= acc_i_12; 295 | axis_tx_tdata[63:56] <= acc_q_12[7:0]; 296 | if (iq_mux_valid) 297 | tmp[15:0] <= acc_q_12[23:8]; 298 | end 299 | 300 | 3: begin 301 | axis_tx_tkeep <= 8'hff; 302 | axis_tx_tdata[15:0] <= tmp[15:0]; 303 | axis_tx_tdata[39:16] <= acc_i_12; 304 | axis_tx_tdata[63:40] <= acc_q_12; 305 | end 306 | endcase 307 | end 308 | 309 | FMT_16BIT: begin 310 | axis_tx_tvalid <= iq_mux_valid; 311 | axis_tx_tkeep <= 8'hff; 312 | 313 | axis_tx_tdata[31:0] <= acc_i_16; 314 | axis_tx_tdata[63:32] <= acc_q_16; 315 | end 316 | 317 | endcase 318 | end 319 | 320 | 321 | endmodule 322 | -------------------------------------------------------------------------------- /lib/qspi/ul_qspi_mem.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2020 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | 6 | module ul_qspi_mem #( 7 | parameter MEM_ADDR_BITS = 16 8 | )( 9 | input clk, 10 | input reset, 11 | 12 | /////////////////////////////// 13 | // UL 14 | // 15 | ///// qspi excmd 16 | input qspi_excmd_valid, 17 | input [31:0] qspi_excmd_data, 18 | output qspi_excmd_ready, 19 | 20 | ///// qspi cmd 21 | input qspi_cmd_valid, 22 | input [31:0] qspi_cmd_data, 23 | output qspi_cmd_ready, 24 | 25 | ///// qspi debug Rd 26 | output qspi_rd_valid, 27 | output [31:0] qspi_rd_data, 28 | input qspi_rd_ready, 29 | 30 | ///// qspi status 31 | output qspi_stat_valid, 32 | output [31:0] qspi_stat_data, 33 | input qspi_stat_ready, 34 | 35 | ////////////////////////////// 36 | // Buffer memory interface 37 | // 38 | output [MEM_ADDR_BITS - 1:2] mem_addr, 39 | output reg mem_valid, 40 | output mem_wr, 41 | output [31:0] mem_out_data, 42 | input mem_ready, 43 | 44 | input [31:0] mem_in_data, 45 | input mem_in_valid, 46 | 47 | ////////////////////////////// 48 | // QSPI if 49 | output reg [7:0] flash_cmd_data, 50 | output reg flash_cmd_valid, 51 | input flash_cmd_ready, 52 | output reg flash_cmd_tlast, 53 | 54 | input [7:0] flash_in_data, 55 | input flash_in_valid, 56 | output flash_in_ready, 57 | input flash_in_tlast 58 | ); 59 | 60 | // QSPI command 61 | // [7:0] cmd | [7:0] size | [15:4] addr | memop | [1:0] ecmdsz | wnr 62 | // 63 | localparam UL_QSPI_WRNRD_OFF = 0; 64 | localparam UL_QSPI_EXCMDSZ_OFF = 1; 65 | localparam UL_QSPI_MEMVALID_OFF = 3; 66 | localparam UL_QSPI_MEMADDR_OFF = 4; 67 | localparam UL_QSPI_SZ_OFF = 16; 68 | localparam UL_QSPI_CMD_OFF = 24; 69 | 70 | assign qspi_rd_valid = 1'b1; 71 | 72 | // STAT register 73 | wire qspi_stat_busy; 74 | 75 | assign qspi_stat_valid = 1'b1; 76 | assign qspi_stat_data = { 31'b0, qspi_stat_busy }; 77 | 78 | localparam ST_READY = 0; 79 | localparam ST_CMD = 1; 80 | localparam ST_CMDEX = 2; 81 | localparam ST_DOUT_ADDR = 3; 82 | localparam ST_DOUT = 4; 83 | localparam ST_DIN = 5; 84 | localparam ST_DIN_MEMWR = 6; 85 | localparam ST_FIN = 7; 86 | 87 | reg [2:0] state; 88 | 89 | reg [7:0] byte_count; 90 | reg zero_byte_count; 91 | 92 | reg [MEM_ADDR_BITS - 1:2] mem_addr_op; 93 | reg [31:0] qspi_excmd_data_reg; // serialized in big endian format 94 | reg [31:0] in_qspi_rd; 95 | reg [31:0] mem_in_data_latched; 96 | reg [1:0] in_qspi_byte; 97 | 98 | reg [1:0] state_serialized; 99 | 100 | reg wrnrd; 101 | 102 | assign qspi_rd_data = in_qspi_rd; 103 | 104 | assign qspi_excmd_ready = (state != ST_CMDEX && state != ST_CMD); 105 | 106 | always @(posedge clk) begin 107 | if (reset) begin 108 | qspi_excmd_data_reg <= 0; 109 | end else begin 110 | if (qspi_excmd_valid && qspi_excmd_ready) begin 111 | qspi_excmd_data_reg <= qspi_excmd_data; 112 | end 113 | end 114 | end 115 | 116 | 117 | reg rem_none; 118 | reg mem_oprd; 119 | 120 | assign mem_addr = mem_addr_op; 121 | 122 | always @(posedge clk) begin 123 | if (reset) begin 124 | mem_valid <= 1'b0; 125 | end else begin 126 | if (state == ST_READY && qspi_cmd_valid && qspi_cmd_ready) begin 127 | mem_addr_op <= { qspi_cmd_data[UL_QSPI_MEMADDR_OFF+11:UL_QSPI_MEMADDR_OFF], 2'b0 }; 128 | byte_count <= qspi_cmd_data[UL_QSPI_SZ_OFF+7:UL_QSPI_SZ_OFF]; 129 | rem_none <= 0; 130 | end else begin 131 | if (state == ST_DOUT_ADDR && (flash_cmd_ready || ~flash_cmd_valid) || 132 | state == ST_DIN_MEMWR && mem_valid == 0) begin 133 | mem_valid <= 1'b1; 134 | byte_count <= byte_count - 4; 135 | 136 | end else if (mem_valid && mem_ready) begin 137 | mem_valid <= 1'b0; 138 | mem_addr_op <= mem_addr_op + 1'b1; 139 | rem_none <= (byte_count[7:2] == 0); 140 | end 141 | end 142 | end 143 | end 144 | 145 | reg rd_last; 146 | reg data_out_valid; 147 | wire data_last_processed = (state == ST_DOUT) && (flash_cmd_ready || ~flash_cmd_valid) && (state_serialized == 2'b11 || rem_none); 148 | 149 | 150 | always @(posedge clk) begin 151 | if (reset) begin 152 | data_out_valid <= 1'b0; 153 | end else if (mem_in_valid) begin 154 | mem_in_data_latched <= mem_in_data; 155 | data_out_valid <= 1'b1; 156 | end else if (/*data_out_valid && data_last_processed*/ state != ST_DOUT) begin 157 | data_out_valid <= 1'b0; 158 | end 159 | end 160 | 161 | assign mem_wr = ~wrnrd; 162 | assign mem_out_data = in_qspi_rd; 163 | assign flash_in_ready = (state == ST_DIN); 164 | 165 | assign qspi_stat_busy = (state != ST_READY); 166 | 167 | reg [7:0] cmd; 168 | 169 | localparam QIO_QCFR_0 = 8'h0B; // 3/4 10 1+ 0 170 | localparam QIO_QCFR_1 = 8'h6B; // 3/4 10 1+ 0 171 | localparam QIO_QCFR_2 = 8'hEB; // 3/4 10 1+ 0 172 | localparam QIO_QCFR4B_0 = 8'h0C; // 4 10 1+ 0 173 | localparam QIO_QCFR4B_1 = 8'h6C; // 4 10 1+ 0 174 | localparam QIO_QCFR4B_2 = 8'hEC; // 4 10 1+ 0 175 | localparam QIO_QCPP_0 = 8'h02; // 3/4 0 0 1-256 176 | localparam QIO_QCPP_1 = 8'h32; // 3/4 0 0 1-256 177 | localparam QIO_QCPP_2 = 8'h12; // 3/4 0 0 1-256 178 | 179 | wire data_commands = (qspi_cmd_data[UL_QSPI_CMD_OFF+7:UL_QSPI_CMD_OFF] == QIO_QCFR_0) || 180 | (qspi_cmd_data[UL_QSPI_CMD_OFF+7:UL_QSPI_CMD_OFF] == QIO_QCFR_1) || 181 | (qspi_cmd_data[UL_QSPI_CMD_OFF+7:UL_QSPI_CMD_OFF] == QIO_QCFR_2) || 182 | (qspi_cmd_data[UL_QSPI_CMD_OFF+7:UL_QSPI_CMD_OFF] == QIO_QCFR4B_0) || 183 | (qspi_cmd_data[UL_QSPI_CMD_OFF+7:UL_QSPI_CMD_OFF] == QIO_QCFR4B_1) || 184 | (qspi_cmd_data[UL_QSPI_CMD_OFF+7:UL_QSPI_CMD_OFF] == QIO_QCFR4B_2) || 185 | (qspi_cmd_data[UL_QSPI_CMD_OFF+7:UL_QSPI_CMD_OFF] == QIO_QCPP_0) || 186 | (qspi_cmd_data[UL_QSPI_CMD_OFF+7:UL_QSPI_CMD_OFF] == QIO_QCPP_1) || 187 | (qspi_cmd_data[UL_QSPI_CMD_OFF+7:UL_QSPI_CMD_OFF] == QIO_QCPP_2); 188 | 189 | always @(posedge clk) begin 190 | if (reset) begin 191 | state <= ST_READY; 192 | 193 | flash_cmd_valid <= 1'b0; 194 | flash_cmd_tlast <= 1'b0; 195 | end else begin 196 | case (state) 197 | ST_READY: begin 198 | if (qspi_cmd_valid && qspi_cmd_ready) begin 199 | cmd <= qspi_cmd_data[UL_QSPI_CMD_OFF+7:UL_QSPI_CMD_OFF]; 200 | //byte_count <= qspi_cmd_data[UL_QSPI_SZ_OFF+7:UL_QSPI_SZ_OFF]; 201 | zero_byte_count <= (qspi_cmd_data[UL_QSPI_SZ_OFF+7:UL_QSPI_SZ_OFF] == 0) && ~data_commands; 202 | 203 | mem_oprd <= qspi_cmd_data[UL_QSPI_MEMVALID_OFF]; 204 | state_serialized<= qspi_cmd_data[UL_QSPI_EXCMDSZ_OFF+1:UL_QSPI_EXCMDSZ_OFF]; 205 | wrnrd <= qspi_cmd_data[UL_QSPI_WRNRD_OFF]; 206 | in_qspi_byte <= 0; 207 | state <= ST_CMD; 208 | 209 | flash_cmd_tlast <= 1'b0; 210 | flash_cmd_valid <= 1'b1; 211 | flash_cmd_data <= qspi_cmd_data[UL_QSPI_SZ_OFF+7:UL_QSPI_SZ_OFF]; 212 | end 213 | end 214 | 215 | ST_CMD: begin 216 | if (flash_cmd_ready) begin 217 | flash_cmd_valid <= 1'b1; 218 | flash_cmd_data <= cmd; 219 | if (state_serialized == 0 && zero_byte_count) begin 220 | flash_cmd_tlast <= 1'b1; 221 | state <= ST_FIN; 222 | end else begin 223 | flash_cmd_tlast <= 1'b0; 224 | 225 | if (state_serialized != 0) begin 226 | state <= ST_CMDEX; 227 | end else if (wrnrd) begin 228 | state <= ST_DOUT_ADDR; 229 | end else begin 230 | flash_cmd_tlast <= 1'b1; 231 | state <= ST_DIN; 232 | end 233 | end 234 | end 235 | end 236 | 237 | ST_CMDEX: begin 238 | if (flash_cmd_ready) begin 239 | // previous transfer finished 240 | case (state_serialized) 241 | 2'b00: flash_cmd_data <= qspi_excmd_data_reg[7:0]; 242 | 2'b01: flash_cmd_data <= qspi_excmd_data_reg[15:8]; 243 | 2'b10: flash_cmd_data <= qspi_excmd_data_reg[23:16]; 244 | 2'b11: flash_cmd_data <= qspi_excmd_data_reg[31:24]; 245 | endcase 246 | 247 | if (state_serialized == 0) begin 248 | if (zero_byte_count) begin 249 | flash_cmd_tlast <= 1'b1; 250 | state <= ST_FIN; 251 | end else if (wrnrd) begin 252 | state <= ST_DOUT_ADDR; 253 | end else begin 254 | flash_cmd_tlast <= 1'b1; 255 | state <= ST_DIN; 256 | end 257 | end else begin 258 | state_serialized <= state_serialized - 1'b1; 259 | end 260 | end 261 | end 262 | 263 | ST_DOUT_ADDR: begin 264 | if (flash_cmd_ready || ~flash_cmd_valid) begin 265 | state <= ST_DOUT; 266 | flash_cmd_valid <= 1'b0; 267 | end 268 | end 269 | 270 | ST_DOUT: begin 271 | if (flash_cmd_ready || ~flash_cmd_valid) begin 272 | 273 | if (data_out_valid) begin 274 | case (state_serialized) 275 | 2'b00: flash_cmd_data <= mem_in_data_latched[7:0]; 276 | 2'b01: flash_cmd_data <= mem_in_data_latched[15:8]; 277 | 2'b10: flash_cmd_data <= mem_in_data_latched[23:16]; 278 | 2'b11: flash_cmd_data <= mem_in_data_latched[31:24]; 279 | endcase 280 | 281 | if (rem_none && (byte_count[1:0] == state_serialized + 1'b1)) begin 282 | flash_cmd_tlast <= 1'b1; 283 | state <= ST_FIN; 284 | end else if (state_serialized == 2'b11) begin 285 | state <= ST_DOUT_ADDR; 286 | end 287 | 288 | state_serialized <= state_serialized + 1'b1; 289 | 290 | flash_cmd_valid <= 1'b1; 291 | end else begin 292 | flash_cmd_valid <= 1'b0; 293 | end 294 | end 295 | end 296 | 297 | ST_DIN: begin 298 | if (flash_cmd_ready) begin 299 | flash_cmd_valid <= 1'b0; 300 | end 301 | if (flash_in_valid) begin 302 | case (state_serialized) 303 | 2'b00: in_qspi_rd[7:0] <= flash_in_data; 304 | 2'b01: in_qspi_rd[15:8] <= flash_in_data; 305 | 2'b10: in_qspi_rd[23:16] <= flash_in_data; 306 | 2'b11: in_qspi_rd[31:24] <= flash_in_data; 307 | endcase 308 | 309 | state_serialized <= state_serialized + 1'b1; 310 | rd_last <= flash_in_tlast; 311 | 312 | if (~mem_oprd && flash_in_tlast) begin 313 | state <= ST_READY; 314 | end else if (mem_oprd && (state_serialized == 2'b11 || flash_in_tlast)) begin 315 | state <= ST_DIN_MEMWR; 316 | end 317 | end 318 | end 319 | 320 | ST_DIN_MEMWR: begin 321 | if (mem_valid && mem_ready) begin 322 | if (rd_last) begin 323 | state <= ST_READY; 324 | end else begin 325 | state <= ST_DIN; 326 | end 327 | end 328 | end 329 | 330 | ST_FIN: begin 331 | if (flash_cmd_ready) begin 332 | flash_cmd_valid <= 1'b0; 333 | state <= ST_READY; 334 | end 335 | end 336 | 337 | endcase 338 | end 339 | end 340 | 341 | 342 | assign qspi_cmd_ready = (state == ST_READY); 343 | 344 | 345 | endmodule 346 | -------------------------------------------------------------------------------- /lib/pcie/pcie_to_ul.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016-2019 Fairwaves, Inc. 3 | // SPDX-License-Identifier: CERN-OHL-W-2.0 4 | // 5 | // PCIe to master UL 6 | // 7 | // NOTICE: Read around Write isn't supported right now 8 | 9 | module pcie_to_ul #( 10 | parameter ADDR_WIDTH = 10, 11 | parameter HOST_LE = 1 12 | )( 13 | input clk, 14 | input rst_n, 15 | 16 | // Configuration 17 | input [15:0] cfg_completer_id, 18 | 19 | // AXIs PCIe RX 20 | input [63:0] m_axis_rx_tdata, 21 | input [7:0] m_axis_rx_tkeep, 22 | input m_axis_rx_tlast, 23 | input m_axis_rx_tvalid, 24 | output m_axis_rx_tready, 25 | 26 | // AXIs PCIe TX 27 | input s_axis_tx_tready, 28 | output reg [63:0] s_axis_tx_tdata, 29 | output reg [7:0] s_axis_tx_tkeep, 30 | output reg s_axis_tx_tlast, 31 | output reg s_axis_tx_tvalid, 32 | 33 | ///////////////////////////////////// 34 | // UL Write channel 35 | output reg [ADDR_WIDTH - 1:0] m_ul_waddr, 36 | output [31:0] m_ul_wdata, 37 | output reg m_ul_wvalid, 38 | input m_ul_wready, 39 | 40 | // AXI Read address channel 41 | output reg [ADDR_WIDTH - 1:0] m_ul_araddr, 42 | output reg m_ul_arvalid, 43 | input m_ul_arready, 44 | 45 | // AXI Read data channel signals 46 | input [31:0] m_ul_rdata, 47 | input m_ul_rvalid, 48 | output reg m_ul_rready 49 | ); 50 | 51 | reg [31:0] m_ul_wdata_t; 52 | reg [31:0] readdata_t; 53 | 54 | wire [31:0] readdata; 55 | 56 | genvar i; 57 | generate 58 | if (HOST_LE == 1) begin 59 | assign readdata = readdata_t; 60 | assign m_ul_wdata = m_ul_wdata_t; 61 | end else begin 62 | for (i = 0; i < 4; i=i+1) begin 63 | assign readdata[(i+1)*8-1:i*8] = readdata_t[(4-i)*8-1:(3-i)*8]; 64 | assign m_ul_wdata[(i+1)*8-1:i*8] = m_ul_wdata_t[(4-i)*8-1:(3-i)*8]; 65 | end 66 | end 67 | endgenerate 68 | 69 | 70 | // Memory 71 | localparam MEM_RD32_FMT_TYPE = 7'b00_00000; // 3DW 72 | localparam MEM_RD64_FMT_TYPE = 7'b01_00000; // 4DW 73 | 74 | localparam MEM_RD32_LOCK_FMT_TYPE = 7'b00_00001; // 3DW 75 | localparam MEM_RD64_LOCK_FMT_TYPE = 7'b01_00001; // 4DW 76 | 77 | localparam MEM_WR32_FMT_TYPE = 7'b10_00000; // 3DW + data 78 | localparam MEM_WR64_FMT_TYPE = 7'b11_00000; // 4DW + data 79 | 80 | // IO 81 | localparam IO_RD32_FMT_TYPE = 7'b00_00010; // 3DW 82 | localparam IO_WR32_FMT_TYPE = 7'b10_00010; // 3DW + data 83 | 84 | // Config Type 0/1 85 | localparam CFGT0_RD_FMT_TYPE = 7'b00_00100; // 3DW 86 | localparam CFGT0_WR_FMT_TYPE = 7'b10_00100; // 3DW + data 87 | localparam CFGT1_RD_FMT_TYPE = 7'b00_00101; // 3DW 88 | localparam CFGT1_WR_FMT_TYPE = 7'b10_00101; // 3DW + data 89 | 90 | // Message 91 | localparam MSG_FMT_TYPE = 7'b00_10xxx; // 4DW 92 | localparam MSG_DATA_FMT_TYPE = 7'b10_10xxx; // 4DW + data 93 | 94 | // Completion 95 | localparam CPL_FMT_TYPE = 7'b00_01010; // 3DW 96 | localparam CPL_DATA_FMT_TYPE = 7'b10_01010; // 3DW + data 97 | localparam CPL_LOCK_FMT_TYPE = 7'b00_01011; // 3DW 98 | localparam CPL_LOCK_DATA_FMT_TYPE = 7'b10_01011; // 3DW + data 99 | 100 | 101 | wire sop; // First TLP QWORD 102 | 103 | reg [3:0] state; 104 | localparam STATE_RESET = 0; // Initial TLP header parse 105 | localparam STATE_WR32_AD = 1; // Address & Data on UL 106 | localparam STATE_WR32_D0 = 2; // Next data 107 | localparam STATE_WR32_D1 = 3; // Next data 2 108 | 109 | localparam STATE_RD32_A = 4; 110 | localparam STATE_RD32_STALL = 5; 111 | localparam STATE_RD32_NF = 6; // wait for notification 112 | localparam STATE_RD32_R1 = 7; 113 | localparam STATE_RD32_R2 = 8; 114 | 115 | localparam STATE_SKIP = 9; 116 | 117 | localparam STATE_RD32_ANS = 10; 118 | localparam STATE_RD32_RN = 11; 119 | localparam STATE_RD32_ANS2 = 12; 120 | localparam STATE_RD32_RN2 = 13; 121 | 122 | 123 | reg [15:0] pcie_req_id; 124 | reg [7:0] pcie_tag; 125 | reg [2:0] pcie_tc; 126 | reg [1:0] pcie_attr; 127 | reg [6:2] pcie_low_addr; // For Completion 128 | 129 | reg [7:0] pcie_len_dw; // max 128 DW -> 512 bytes 130 | 131 | // 132 | // req_id[63:48] | tag[47:40] | ldwbe[39:36] fdwbe[35:32] || # fmt_type[30:24] | # tc[22:20] #### | td[15] ep[14] attr[13:12] ## length[9:0] 133 | // data[63:32] || addr[31:2] ## 134 | 135 | 136 | // only valid when SOP is asserted 137 | wire [9:0] tlp_length = m_axis_rx_tdata[9:0]; 138 | // reserved m_axis_rx_tdata[11:10] 139 | wire [1:0] tlp_attr = m_axis_rx_tdata[13:12]; 140 | wire tlp_ep = m_axis_rx_tdata[14]; 141 | wire tlp_dp = m_axis_rx_tdata[15]; 142 | // reserved m_axis_rx_tdata[19:16] 143 | wire [2:0] tlp_tc = m_axis_rx_tdata[22:20]; 144 | // reserved m_axis_rx_tdata[23] 145 | wire [4:0] tlp_type = m_axis_rx_tdata[28:24]; 146 | wire [1:0] tlp_fmt = m_axis_rx_tdata[30:29]; 147 | // reserved m_axis_rx_tdata[31] 148 | wire [3:0] tlp_ldwbe = m_axis_rx_tdata[39:36]; 149 | wire [3:0] tlp_fdwbe = m_axis_rx_tdata[35:32]; 150 | 151 | 152 | assign m_axis_rx_tready = (state == STATE_RESET) || 153 | (state == STATE_RD32_A) || 154 | (state == STATE_SKIP) || 155 | (state == STATE_WR32_AD && (~m_ul_wvalid || m_ul_wready)) || 156 | ((state == STATE_WR32_D0 && ~m_axis_rx_tkeep[7]) || state == STATE_WR32_D1) && m_ul_wready; 157 | 158 | always @( posedge clk ) begin 159 | if (!rst_n) begin 160 | s_axis_tx_tvalid <= 1'b0; 161 | s_axis_tx_tlast <= 1'b0; 162 | s_axis_tx_tkeep <= 8'b0; 163 | 164 | m_ul_wvalid <= 1'b0; 165 | m_ul_arvalid <= 1'b0; 166 | m_ul_rready <= 1'b0; 167 | 168 | state <= STATE_RESET; 169 | end else begin 170 | if (m_ul_wready && m_ul_wvalid && (state != STATE_WR32_AD) && (state != STATE_WR32_D0) && (state != STATE_WR32_D1)) begin 171 | m_ul_wvalid <= 1'b0; 172 | end 173 | 174 | case (state) 175 | STATE_RESET: begin 176 | if (/*m_axis_rx_tready &&*/ m_axis_rx_tvalid) begin 177 | case ({tlp_fmt,tlp_type}) 178 | MEM_RD32_FMT_TYPE : begin 179 | 180 | if (/* tlp_length == 10'h1 && */ // 1-DW 181 | tlp_ep == 1'b0 && // Data isn't poisoned 182 | tlp_fdwbe == 4'hF) // 32-bit transfer 183 | state <= STATE_RD32_A; 184 | else 185 | state <= STATE_SKIP; 186 | 187 | pcie_req_id <= m_axis_rx_tdata[63:48]; 188 | pcie_tag <= m_axis_rx_tdata[47:40]; 189 | pcie_tc <= tlp_tc; 190 | pcie_attr <= tlp_attr; 191 | pcie_len_dw <= tlp_length[7:0]; // holds up to 128DW == 512 Bytes 192 | end 193 | 194 | MEM_WR32_FMT_TYPE : begin 195 | // we accept only 32 bit 1-DW command only 196 | if (/* tlp_length == 10'h1 && */ // 1-DW 197 | tlp_ep == 1'b0 && // Data isn't poisoned 198 | tlp_fdwbe == 4'hF) // 32-bit transfer 199 | state <= STATE_WR32_AD; 200 | else 201 | state <= STATE_SKIP; 202 | end 203 | 204 | default: begin 205 | state <= STATE_SKIP; 206 | end 207 | endcase 208 | end 209 | end // STATE_RESET 210 | 211 | // WRITE STATES 212 | STATE_WR32_AD: begin 213 | if (/*m_axis_rx_tready && */ (~m_ul_wvalid || m_ul_wready) && m_axis_rx_tvalid) begin 214 | m_ul_wdata_t <= m_axis_rx_tdata[63:32]; 215 | m_ul_waddr <= m_axis_rx_tdata[ADDR_WIDTH + 1:2]; 216 | m_ul_wvalid <= 1'b1; 217 | 218 | if (m_axis_rx_tlast) begin 219 | state <= STATE_RESET; 220 | end else begin 221 | state <= STATE_WR32_D0; 222 | end 223 | end else if (m_ul_wready && m_ul_wvalid) begin 224 | m_ul_wvalid <= 1'b0; 225 | end 226 | end 227 | 228 | STATE_WR32_D0: begin 229 | if (/*m_axis_rx_tready && */ m_ul_wready && m_axis_rx_tvalid) begin 230 | m_ul_waddr <= m_ul_waddr + 1'b1; 231 | m_ul_wdata_t <= m_axis_rx_tdata[31:0]; 232 | m_ul_wvalid <= 1'b1; 233 | 234 | if (m_axis_rx_tlast && ~m_axis_rx_tkeep[7]) begin 235 | state <= STATE_RESET; 236 | end else begin 237 | state <= STATE_WR32_D1; 238 | end 239 | end else if (m_ul_wready && m_ul_wvalid) begin 240 | m_ul_wvalid <= 1'b0; 241 | end 242 | end 243 | 244 | STATE_WR32_D1: begin 245 | if (/*m_axis_rx_tready && */ m_ul_wready && m_axis_rx_tvalid) begin 246 | m_ul_waddr <= m_ul_waddr + 1'b1; 247 | m_ul_wdata_t <= m_axis_rx_tdata[63:32]; 248 | m_ul_wvalid <= 1'b1; 249 | 250 | if (m_axis_rx_tlast) begin 251 | state <= STATE_RESET; 252 | end else begin 253 | state <= STATE_WR32_D0; 254 | end 255 | end else if (m_ul_wready && m_ul_wvalid) begin 256 | m_ul_wvalid <= 1'b0; 257 | end 258 | end 259 | 260 | STATE_RD32_A: begin 261 | if (/*m_axis_rx_tready &&*/ m_axis_rx_tvalid) begin 262 | m_ul_araddr <= m_axis_rx_tdata[ADDR_WIDTH + 1:2]; 263 | pcie_low_addr <= m_axis_rx_tdata[6:2]; 264 | 265 | if (m_axis_rx_tlast) begin 266 | m_ul_arvalid <= 1'b1; 267 | state <= STATE_RD32_STALL; 268 | end 269 | end 270 | end 271 | 272 | STATE_RD32_STALL: begin 273 | if (m_ul_arvalid && m_ul_arready) begin 274 | m_ul_arvalid <= 1'b0; 275 | m_ul_rready <= 1'b1; 276 | 277 | state <= STATE_RD32_NF; 278 | end 279 | end 280 | 281 | STATE_RD32_NF: begin 282 | if (m_ul_rvalid && m_ul_rready) begin 283 | m_ul_rready <= 1'b0; 284 | readdata_t <= m_ul_rdata; 285 | state <= STATE_RD32_R1; 286 | 287 | s_axis_tx_tdata <= {cfg_completer_id, 3'b000, 1'b0, { 2'b0, pcie_len_dw, 2'b0 }, 288 | 1'b0, CPL_DATA_FMT_TYPE, 1'b0, pcie_tc, 4'b0, 1'b0, 1'b0, pcie_attr, 2'b0, { 2'b0, pcie_len_dw } }; 289 | s_axis_tx_tkeep <= 8'hFF; 290 | s_axis_tx_tvalid <= 1'b1; 291 | end 292 | end 293 | 294 | STATE_RD32_R1: begin 295 | if (s_axis_tx_tready) begin 296 | s_axis_tx_tdata <= { readdata, 297 | pcie_req_id, pcie_tag, 1'b0, pcie_low_addr, 2'b0 }; 298 | state <= STATE_RD32_R2; 299 | pcie_len_dw <= pcie_len_dw - 1'b1; 300 | if (pcie_len_dw == 8'h1) begin 301 | s_axis_tx_tlast <= 1'b1; 302 | end 303 | end 304 | end 305 | 306 | STATE_RD32_R2: begin 307 | if (s_axis_tx_tready) begin 308 | if (s_axis_tx_tlast) begin 309 | state <= STATE_RESET; 310 | end else begin 311 | m_ul_araddr <= m_ul_araddr + 1'b1; 312 | m_ul_arvalid <= 1'b1; 313 | state <= STATE_RD32_ANS; 314 | end 315 | 316 | s_axis_tx_tlast <= 1'b0; 317 | s_axis_tx_tvalid <= 1'b0; 318 | end 319 | end 320 | 321 | STATE_RD32_ANS: begin 322 | if (m_ul_arvalid && m_ul_arready) begin 323 | m_ul_arvalid <= 1'b0; 324 | m_ul_rready <= 1'b1; 325 | state <= STATE_RD32_RN; 326 | end 327 | end 328 | 329 | STATE_RD32_RN: begin 330 | if (m_ul_rvalid && m_ul_rready) begin 331 | m_ul_rready <= 1'b0; 332 | s_axis_tx_tdata[31:0] <= m_ul_rdata; 333 | s_axis_tx_tkeep <= 8'h0f; 334 | pcie_len_dw <= pcie_len_dw - 1'b1; 335 | if (pcie_len_dw == 8'h1) begin 336 | state <= STATE_RD32_R2; 337 | s_axis_tx_tlast <= 1'b1; 338 | s_axis_tx_tvalid <= 1'b1; 339 | end else begin 340 | state <= STATE_RD32_ANS2; 341 | m_ul_araddr <= m_ul_araddr + 1'b1; 342 | m_ul_arvalid <= 1'b1; 343 | end 344 | end 345 | end 346 | 347 | STATE_RD32_ANS2: begin 348 | if (m_ul_arvalid && m_ul_arready) begin 349 | m_ul_arvalid <= 1'b0; 350 | m_ul_rready <= 1'b1; 351 | state <= STATE_RD32_RN2; 352 | end 353 | end 354 | 355 | STATE_RD32_RN2: begin 356 | if (m_ul_rvalid && m_ul_rready) begin 357 | m_ul_rready <= 1'b0; 358 | s_axis_tx_tdata[63:32] <= m_ul_rdata; 359 | s_axis_tx_tkeep <= 8'hff; 360 | state <= STATE_RD32_R2; 361 | s_axis_tx_tvalid <= 1'b1; 362 | pcie_len_dw <= pcie_len_dw - 1'b1; 363 | if (pcie_len_dw == 8'h1) begin 364 | s_axis_tx_tlast <= 1'b1; 365 | end 366 | end 367 | end 368 | 369 | STATE_SKIP: begin 370 | if (m_axis_rx_tlast && m_axis_rx_tvalid) begin 371 | state <= STATE_RESET; 372 | end 373 | end 374 | endcase 375 | 376 | end 377 | end 378 | 379 | endmodule 380 | --------------------------------------------------------------------------------