diff --git a/elink/hdl/ecfg.v b/elink/hdl/ecfg.v new file mode 100644 index 0000000..2836f96 --- /dev/null +++ b/elink/hdl/ecfg.v @@ -0,0 +1,357 @@ +/* + Copyright (C) 2013 Adapteva, Inc. + Contributed by Andreas Olofsson + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version.This program is distributed in the hope + that it will be useful,but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. You should have received a copy + of the GNU General Public License along with this program (see the file + COPYING). If not, see . +*/ +/* + ######################################################################## + EPIPHANY CONFIGURATION REGISTER + ######################################################################## +------------------------------------------------------------- + ESYSRESET ***Elink reset*** + [0] 0 - elink active + 1 - elink in reset +------------------------------------------------------------- + ESYSCFGTX ***Elink transmitter configuration*** + [0] 0 - link TX disable + 1 - link TX enable + [1] 0 - normal pass through transaction mode + 1 - mmu mode + [3:2] 00 - normal mode + 01 - gpio mode + 10 - auto-increment 64-bit address/data pairs + 11 - reserved + [7:4] Transmit control mode for eMesh + [11:8] 0000 - No division, full speed + 0001 - Divide by 2 + Others - Reserved + ------------------------------------------------------------- + ESYSCFGRX ***Elink receiver configuration*** + [0] 0 - link RX disable + 1 - link RX enable + [1] 0 - normal transaction mode + 1 - mmu mode + [3:2] 00 - normal mode + 01 - GPIO mode (drive rd wait pins from registers) + 10 - loopback mode (loops TX-->RX) + 11 - reserved + [4] 0 - set monitor to count traffic + 1 - set monitor to count congestion + ------------------------------------------------------------- + ESYSCFGCLK ***Epiphany clock frequency setting*** + [3:0] Output divider + 0000 - Clock turned off + 0001 - CLKIN/64 + 0010 - CLKIN/32 + 0011 - CLKIN/16 + 0100 - CLKIN/8 + 0101 - CLKIN/4 + 0110 - CLKIN/2 + 0111 - CLKIN/1 (full speed) + 1XXX - RESERVED + [7:4] PLL settings (TBD) + ------------------------------------------------------------- + ESYSCOREID ***CORE ID*** + [5:0] Column ID-->default at powerup/reset + [11:6] Row ID + ------------------------------------------------------------- + ESYSVERSION ***Version number (read only)*** + [7:0] Revision #, incremented in each change (match git?) + [15:8] Type (features included in FPGA load, same board) + [23:16] Board platform # + [31:24] Generation # (needed??) + ------------------------------------------------------------- + ESYSDATAIN ***Data on elink input pins + [7:0] rx_data[7:0] + [8] tx_frame + [9] tx_wait_rd + [10] tx_wait_wr + ------------------------------------------------------------- + ESYSDATAOUT ***Data on eLink output pins + [7:0] tx_data[7:0] + [8] tx_frame + [9] rx_wait_rd + [10] rx_wait_wr + ------------------------------------------------------------- + ESYSDEBUG ***Various debug signals from elink + [31:0] (design specific, generic inferface for now) + included: + -all wait signals, (4) + -fifo fulls, + -fifo emptys + -axi access, ready signals for master/slave + -frame signals (in and out) + ######################################################################## + */ + +// These are WORD addresses (bits 11:2) +`define E_REG_SYSRESET 10'h010 +`define E_REG_SYSCFGTX 10'h011 +`define E_REG_SYSCFGRX 10'h012 +`define E_REG_SYSCFGCLK 10'h013 +`define E_REG_SYSCOREID 10'h014 +`define E_REG_SYSVERSION 10'h015 +`define E_REG_SYSDATAIN 10'h016 +`define E_REG_SYSDATAOUT 10'h017 +`define E_REG_SYSDEBUG 10'h018 + +module ecfg (/*AUTOARG*/ + // Outputs + mi_dout, ecfg_reset, ecfg_tx_enable, ecfg_tx_mmu_mode, + ecfg_tx_gpio_mode, ecfg_tx_tp_mode, ecfg_tx_ctrl_mode, + ecfg_tx_clkdiv, ecfg_rx_enable, ecfg_rx_mmu_mode, + ecfg_rx_gpio_mode, ecfg_cclk_en, ecfg_cclk_div, ecfg_cclk_pllcfg, + ecfg_coreid, ecfg_dataout, + // Inputs + mi_clk, mi_en, mi_we, mi_addr, mi_din, hw_reset, ecfg_datain, + ecfg_debug_signals + ); + //Register file parameters + +/* + ##################################################################### + COMPILE TIME PARAMETERS + ###################################################################### + */ + parameter COREID = 12'h808; + parameter VERSION = 32'h00_00_00_00; // FPGA (gen:plat:type:rev) + parameter IDW = 12; // Elink ID (row,column coordinate) + parameter RFAW = 12; // Register file address width + + // NB: The BRAM interface seems to provide BYTE addresses! + + /******************************/ + /*HARDWARE RESET (POR/BUTTON) */ + /******************************/ + input hw_reset; + + /*****************************/ + /*SIMPLE MEMORY INTERFACE */ + /*****************************/ + input mi_clk; + input mi_en; + input mi_we; //Single we, must write full words! + input [RFAW-1:0] mi_addr; + input [31:0] mi_din; + output [31:0] mi_dout; + + + /*****************************/ + /*ELINK CONTROL SIGNALS */ + /*****************************/ + //RESET + output ecfg_reset; + + //tx + output ecfg_tx_enable; //enable signal for TX + output ecfg_tx_mmu_mode; //enables MMU on transmit path + output ecfg_tx_gpio_mode; //forces TX output pins to constants + output ecfg_tx_tp_mode; //auto-generates TX transactions + output [3:0] ecfg_tx_ctrl_mode; //value for emesh ctrlmode tag + output [3:0] ecfg_tx_clkdiv; //transmit clock divider + + //rx + output ecfg_rx_enable; //enable signal for rx + output ecfg_rx_mmu_mode; //enables MMU on rx path + output ecfg_rx_gpio_mode; //forces rx wait pins to constants + + + //cclk + output ecfg_cclk_en; //cclk enable + output [3:0] ecfg_cclk_div; //cclk divider setting + output [3:0] ecfg_cclk_pllcfg; //pll configuration + + //coreid + output [11:0] ecfg_coreid; //core-id of fpga elink + + //gpio + input [10:0] ecfg_datain; // data from elink inputs + output [10:0] ecfg_dataout; //data for elink outputs {rd_wait,wr_wait,frame,data[7:0]} + + //debug + input [31:0] ecfg_debug_signals;//various signals for debugging the elink hardware + + + /*------------------------BODY CODE---------------------------------------*/ + + //registers + reg [11:0] ecfg_cfgtx_reg; + reg [4:0] ecfg_cfgrx_reg; + reg [7:0] ecfg_cfgclk_reg; + reg [11:0] ecfg_coreid_reg; + reg ecfg_reset_reg; + reg [11:0] ecfg_datain_reg; + reg [11:0] ecfg_dataout_reg; + reg [31:0] mi_dout; + + //wires + wire ecfg_read; + wire ecfg_write; + wire ecfg_reset_match; + wire ecfg_cfgtx_match; + wire ecfg_cfgrx_match; + wire ecfg_cfgclk_match; + wire ecfg_coreid_match; + wire ecfg_datain_match; + wire ecfg_dataout_match; + wire ecfg_match; + wire ecfg_regmux; + wire [31:0] ecfg_reg_mux; + wire ecfg_cfgtx_write; + wire ecfg_cfgrx_write; + wire ecfg_cfgclk_write; + wire ecfg_coreid_write; + wire ecfg_dataout_write; + wire ecfg_rx_monitor_mode; + wire ecfg_reset_write; + + /*****************************/ + /*ADDRESS DECODE LOGIC */ + /*****************************/ + + //read/write decode + assign ecfg_write = mi_en & mi_we; + assign ecfg_read = mi_en & ~mi_we; + + //address match signals + assign ecfg_reset_match = mi_addr[RFAW-1:2]==`E_REG_SYSRESET; + assign ecfg_cfgtx_match = mi_addr[RFAW-1:2]==`E_REG_SYSCFGTX; + assign ecfg_cfgrx_match = mi_addr[RFAW-1:2]==`E_REG_SYSCFGRX; + assign ecfg_cfgclk_match = mi_addr[RFAW-1:2]==`E_REG_SYSCFGCLK; + assign ecfg_coreid_match = mi_addr[RFAW-1:2]==`E_REG_SYSCOREID; + assign ecfg_version_match = mi_addr[RFAW-1:2]==`E_REG_SYSVERSION; + assign ecfg_datain_match = mi_addr[RFAW-1:2]==`E_REG_SYSDATAIN; + assign ecfg_dataout_match = mi_addr[RFAW-1:2]==`E_REG_SYSDATAOUT; + + assign ecfg_match = ecfg_reset_match | + ecfg_cfgtx_match | + ecfg_cfgrx_match | + ecfg_cfgclk_match | + ecfg_coreid_match | + ecfg_version_match | + ecfg_datain_match | + ecfg_dataout_match; + + //Write enables + assign ecfg_reset_write = ecfg_reset_match & ecfg_write; + assign ecfg_cfgtx_write = ecfg_cfgtx_match & ecfg_write; + assign ecfg_cfgrx_write = ecfg_cfgrx_match & ecfg_write; + assign ecfg_cfgclk_write = ecfg_cfgclk_match & ecfg_write; + assign ecfg_coreid_write = ecfg_coreid_match & ecfg_write; + assign ecfg_dataout_write = ecfg_dataout_match & ecfg_write; + + + //########################### + //# ESYSCFGTX + //########################### + always @ (posedge mi_clk) + if(hw_reset) + ecfg_cfgtx_reg[11:0] <= 12'b0; + else if (ecfg_cfgtx_write) + ecfg_cfgtx_reg[11:0] <= mi_din[11:0]; + + assign ecfg_tx_enable = ecfg_cfgtx_reg[0]; + assign ecfg_tx_mmu_mode = ecfg_cfgtx_reg[1]; + assign ecfg_tx_gpio_mode = ecfg_cfgtx_reg[3:2]==2'b01; + assign ecfg_tx_tp_mode = ecfg_cfgtx_reg[3:2]==2'b10; + assign ecfg_tx_ctrl_mode[3:0] = ecfg_cfgtx_reg[7:4]; + assign ecfg_tx_clkdiv[3:0] = ecfg_cfgtx_reg[11:8]; + + //########################### + //# ESYSCFGRX + //########################### + always @ (posedge mi_clk) + if(hw_reset) + ecfg_cfgrx_reg[4:0] <= 5'b0; + else if (ecfg_cfgrx_write) + ecfg_cfgrx_reg[4:0] <= mi_din[4:0]; + + assign ecfg_rx_enable = ecfg_cfgrx_reg[0]; + assign ecfg_rx_mmu_mode = ecfg_cfgrx_reg[1]; + assign ecfg_rx_gpio_mode = ecfg_cfgrx_reg[3:2]==2'b01; + assign ecfg_rx_loopback_mode = ecfg_cfgrx_reg[3:2]==2'b10; + assign ecfg_rx_monitor_mode = ecfg_cfgrx_reg[4]; + + //########################### + //# ESYSCFGCLK + //########################### + always @ (posedge mi_clk) + if(hw_reset) + ecfg_cfgclk_reg[7:0] <= 8'b0; + else if (ecfg_cfgclk_write) + ecfg_cfgclk_reg[7:0] <= mi_din[7:0]; + + assign ecfg_cclk_en = ~(ecfg_cfgclk_reg[3:0]==4'b0000); + assign ecfg_cclk_div[3:0] = ecfg_cfgclk_reg[3:0]; + assign ecfg_cclk_pllcfg[3:0] = ecfg_cfgclk_reg[7:4]; + + //########################### + //# ESYSCOREID + //########################### + always @ (posedge mi_clk) + if(hw_reset) + ecfg_coreid_reg[IDW-1:0] <= PARAM_COREID; + else if (ecfg_coreid_write) + ecfg_coreid_reg[IDW-1:0] <= mi_din[IDW-1:0]; + + assign ecfg_coreid[IDW-1:0] = ecfg_coreid_reg[IDW-1:0]; + + //########################### + //# ESYSDATAIN + //########################### + always @ (posedge mi_clk) + ecfg_datain_reg <= ecfg_datain; + + //########################### + //# ESYSDATAOUT + //########################### + always @ (posedge mi_clk) + if(hw_reset) + ecfg_dataout_reg <= 'd0; + else if (ecfg_dataout_write) + ecfg_dataout_reg <= mi_din[10:0]; + + assign ecfg_dataout[10:0] = ecfg_dataout_reg[10:0]; + + //########################### + //# ESYSRESET + //########################### + always @ (posedge mi_clk) + if(hw_reset) + ecfg_reset_reg <= 1'b0; + else if (ecfg_reset_write) + ecfg_reset_reg <= mi_din[0]; + + assign ecfg_reset = ecfg_reset_reg | hw_reset; + + //############################### + //# DATA READBACK MUX + //############################### + + //Pipelineing readback + always @ (posedge mi_clk) + if(ecfg_read) + case(mi_addr[RFAW-1:2]) + `E_REG_SYSRESET: mi_dout[31:0] <= {31'b0, ecfg_reset_reg}; + `E_REG_SYSCFGTX: mi_dout[31:0] <= {20'b0, ecfg_cfgtx_reg[11:0]}; + `E_REG_SYSCFGRX: mi_dout[31:0] <= {27'b0, ecfg_cfgrx_reg[4:0]}; + `E_REG_SYSCFGCLK: mi_dout[31:0] <= {24'b0, ecfg_cfgclk_reg[7:0]}; + `E_REG_SYSCOREID: mi_dout[31:0] <= {{(32-IDW){1'b0}}, ecfg_coreid_reg[IDW-1:0]}; + `E_REG_SYSVERSION: mi_dout[31:0] <= VERSION; + `E_REG_SYSDATAIN: mi_dout[31:0] <= {20'b0, ecfg_datain_reg[11:0]}; + `E_REG_SYSDATAOUT: mi_dout[31:0] <= {20'b0, ecfg_dataout_reg[11:0]}; + `E_REG_SYSDEBUG: mi_dout[31:0] <= ecfg_debug_signals[31:0]; + default: mi_dout[31:0] <= 32'd0; + endcase + +endmodule // e_cfg + diff --git a/elink/hdl/eclock.v b/elink/hdl/eclock.v new file mode 100644 index 0000000..2b67718 --- /dev/null +++ b/elink/hdl/eclock.v @@ -0,0 +1,255 @@ +/* + Copyright (C) 2014 Adapteva, Inc. + Contributed by Fred Huettig + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version.This program is distributed in the hope + that it will be useful,but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. You should have received a copy + of the GNU General Public License along with this program (see the file + COPYING). If not, see . +*/ + +/*########################################################################### + # Function: Generates clocks for eLink module: + # clk_n/p - Epiphany Core Clock, Differential, must be connected + # directly to IO pins. + # + # txlclk_p - Parallel data clock, at bit rate / 8 + # + # txlclk_s - Serial DDR data clock, at bit rate / 2 + # + # txlclk_out - DDR "Clock" clock, to generate LCLK output + # At bit rate / 2, 90deg shifted from lclk_s + # + # Inputs: + # ecfg_cclk_en - Enable the CCLK output + # ecfg_cclk_div - CCLK divider + # ecfg_cclk_pllcfg - PLL configuration (not implemented) + # + # Notes: Uses Xilinx macros throughout + # + ############################################################################ + */ + +`timescale 1ns/1ps + +module eclock (/*AUTOARG*/ + // Outputs + cclk_p, cclk_n, txlclk_s, txlclk_out, txlclk_p, + // Inputs + clkin, reset, ecfg_cclk_en, ecfg_cclk_div, ecfg_cclk_pllcfg + ); + + // Parameters must be set as follows: + // PFD input frequency = 1/CLKIN1_PERIOD / DIVCLK_DIVIDE (10-450MHz) + // VCO frequency = PFD input frequency * CLKFBOUT_MULT (800-1600MHz) + // Output frequency = VCO frequency / CLKOUTn_DIVIDE + parameter CLKIN_PERIOD = 10.000; // ns -> 100MHz + parameter CLKIN_DIVIDE = 1; + parameter VCO_MULT = 12; // VCO = 1200MHz + parameter CCLK_DIVIDE = 2; // CCLK = 600MHz (at /1 setting) + parameter LCLK_DIVIDE = 4; // LCLK = 300MHz (600MB/s eLink, 75MW/s parallel) + parameter FEATURE_CCLK_DIV = 1'b1; + parameter IOSTD_ELINK = "LVDS_25"; + + // input clock & reset + input clkin; + input reset; + + // From configuration register + input ecfg_cclk_en; //cclk enable + input [3:0] ecfg_cclk_div; //cclk divider setting + input [3:0] ecfg_cclk_pllcfg; //pll configuration TODO: ?? + + //epiphany clock + output cclk_p, cclk_n; + + //clocks for elink transmitter + output txlclk_s; + output txlclk_out; + output txlclk_p; + + // Wires + wire cclk_src; + wire cclk_base; + wire cclk_p_src; + wire cclk_p; + wire cclk; + wire lclk_s_src; + wire lclk_out_src; + wire lclk_p_src; + wire clkfb; + + // PLL Primitive + PLLE2_BASE + #( + .BANDWIDTH("OPTIMIZED"), // OPTIMIZED, HIGH, LOW + .CLKFBOUT_MULT(VCO_MULT), // Multiply value for all CLKOUT, (2-64) + .CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB, (-360.000-360.000). + .CLKIN1_PERIOD(CLKIN_PERIOD),// Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz). + // CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: Divide amount for each CLKOUT (1-128) + .CLKOUT0_DIVIDE(CCLK_DIVIDE), + .CLKOUT1_DIVIDE(LCLK_DIVIDE), + .CLKOUT2_DIVIDE(LCLK_DIVIDE), + .CLKOUT3_DIVIDE(LCLK_DIVIDE * 4), + .CLKOUT4_DIVIDE(CCLK_DIVIDE * 4), + .CLKOUT5_DIVIDE(128), + // CLKOUT0_DUTY_CYCLE - CLKOUT5_DUTY_CYCLE: Duty cycle for each CLKOUT (0.001-0.999). + .CLKOUT0_DUTY_CYCLE(0.5), + .CLKOUT1_DUTY_CYCLE(0.5), + .CLKOUT2_DUTY_CYCLE(0.5), + .CLKOUT3_DUTY_CYCLE(0.5), + .CLKOUT4_DUTY_CYCLE(0.5), + .CLKOUT5_DUTY_CYCLE(0.5), + // CLKOUT0_PHASE - CLKOUT5_PHASE: Phase offset for each CLKOUT (-360.000-360.000). + .CLKOUT0_PHASE(0.0), + .CLKOUT1_PHASE(0.0), + .CLKOUT2_PHASE(90.0), + .CLKOUT3_PHASE(0.0), + .CLKOUT4_PHASE(0.0), + .CLKOUT5_PHASE(0.0), + .DIVCLK_DIVIDE(CLKIN_DIVIDE),// Master division value, (1-56) + .REF_JITTER1(0.01), // Reference input jitter in UI, (0.000-0.999). + .STARTUP_WAIT("FALSE") // Delay DONE until PLL Locks, ("TRUE"/"FALSE") + ) eclk_pll + ( + // Clock Outputs: 1-bit (each) output: User configurable clock outputs + .CLKOUT0(cclk_src), // 1-bit output: CLKOUT0 + .CLKOUT1(lclk_s_src), // 1-bit output: CLKOUT1 + .CLKOUT2(lclk_out_src), // 1-bit output: CLKOUT2 + .CLKOUT3(lclk_p_src), // 1-bit output: CLKOUT3 + .CLKOUT4(cclk_p_src), // 1-bit output: CLKOUT4 + .CLKOUT5(), // 1-bit output: CLKOUT5 + // Feedback Clocks: 1-bit (each) output: Clock feedback ports + .CLKFBOUT(clkfb), // 1-bit output: Feedback clock + .LOCKED(), // 1-bit output: LOCK + .CLKIN1(clkin), // 1-bit input: Input clock + // Control Ports: 1-bit (each) inpu: PLL control ports + .PWRDWN(1'b0), // 1-bit input: Power-down + .RST(1'b0), // 1-bit input: Reset + // Feedback Clocks: 1-bit (each) input: Clock feedback ports + .CLKFBIN(clkfb) // 1-bit input: Feedback clock + ); + + // Output buffering + + BUFG cclk_buf + (.O (cclk_base), + .I (cclk_src)); + + BUFG cclk_p_buf + (.O (cclk_p), + .I (cclk_p_src)); + + BUFG lclk_s_buf + (.O (txlclk_s), + .I (lclk_s_src)); + + BUFG lclk_out_buf + (.O (txlclk_out), + .I (lclk_out_src)); + + BUFG lclk_p_buf + (.O (txlclk_p), + .I (lclk_p_src)); + +generate + if( FEATURE_CCLK_DIV ) begin : gen_cclk_div + + // Create adjustable (but fast) CCLK + wire rxi_cclk_out; + reg [8:1] cclk_pattern; + reg [3:0] clk_div_sync; + reg enb_sync; + + always @ (posedge cclk_p) begin // Might need x-clock TIG here + + clk_div_sync <= ecfg_cclk_div; + enb_sync <= ecfg_cclk_en; + + if(enb_sync) + case(clk_div_sync) + 4'h0: cclk_pattern <= 8'd0; // Clock OFF + 4'h7: cclk_pattern <= 8'b10101010; // Divide by 1 + 4'h6: cclk_pattern <= 8'b11001100; // Divide by 2 + 4'h5: cclk_pattern <= 8'b11110000; // Divide by 4 + default: cclk_pattern <= {8{~cclk_pattern[1]}}; // /8 + endcase + else + cclk_pattern <= 8'b00000000; + + end // always @ (posedge lclk_p) + + OSERDESE2 + #( + .DATA_RATE_OQ("DDR"), // DDR, SDR + .DATA_RATE_TQ("SDR"), // DDR, BUF, SDR + .DATA_WIDTH(8), // Parallel data width (2-8,10,14) + .INIT_OQ(1'b0), // Initial value of OQ output (1'b0,1'b1) + .INIT_TQ(1'b0), // Initial value of TQ output (1'b0,1'b1) + .SERDES_MODE("MASTER"), // MASTER, SLAVE + .SRVAL_OQ(1'b0), // OQ output value when SR is used (1'b0,1'b1) + .SRVAL_TQ(1'b0), // TQ output value when SR is used (1'b0,1'b1) + .TBYTE_CTL("FALSE"), // Enable tristate byte operation (FALSE, TRUE) + .TBYTE_SRC("FALSE"), // Tristate byte source (FALSE, TRUE) + .TRISTATE_WIDTH(1) // 3-state converter width (1,4) + ) OSERDESE2_inst + ( + .OFB(), // 1-bit output: Feedback path for data + .OQ(cclk), // 1-bit output: Data path output + .SHIFTOUT1(), // SHIFTOUTn: 1-bit (each): Data output expansion + .SHIFTOUT2(), + .TBYTEOUT(), // 1-bit output: Byte group tristate + .TFB(), // 1-bit output: 3-state control + .TQ(), // 1-bit output: 3-state control + .CLK(cclk_base), // 1-bit input: High speed clock + .CLKDIV(cclk_p), // 1-bit input: Divided clock + .D1(cclk_pattern[1]), // D1 - D8: Parallel data inputs (1-bit each) + .D2(cclk_pattern[2]), + .D3(cclk_pattern[3]), + .D4(cclk_pattern[4]), + .D5(cclk_pattern[5]), + .D6(cclk_pattern[6]), + .D7(cclk_pattern[7]), + .D8(cclk_pattern[8]), + .OCE(1'b1), // 1-bit input: Output data clock enable + .RST(reset), // 1-bit input: Reset + .SHIFTIN1(1'b0), // SHIFTINn: Data input expansion (1-bit each) + .SHIFTIN2(1'b0), + .T1(1'b0), // T1 - T4: Parallel 3-state inputs + .T2(1'b0), + .T3(1'b0), + .T4(1'b0), + .TBYTEIN(1'b0), // 1-bit input: Byte group tristate + .TCE(1'b0) // 1-bit input: 3-state clock enable + ); + + end else begin : gen_fixed_cclk // Non-dividable CCLK + + reg enb_sync; + + always @ (posedge cclk_p) + enb_sync <= ecfg_cclk_en; + + // The following does not result in timing failures, + // but doesn't seem glitch-safe + assign cclk = cclk_base & enb_sync; + + end +endgenerate + + // xilinx OBUFDS instantiation + // + OBUFDS + #(.IOSTANDARD (IOSTD_ELINK)) + obufds_cclk_inst + (.O (cclk_p), + .OB (cclk_n), + .I (cclk)); + +endmodule // eclock + diff --git a/elink/hdl/elink.v b/elink/hdl/elink.v new file mode 100644 index 0000000..2c30829 --- /dev/null +++ b/elink/hdl/elink.v @@ -0,0 +1,654 @@ +/* + Copyright (C) 2014 Adapteva, Inc. + + Contributed by Fred Huettig + Contributed by Andreas Olofsson + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version.This program is distributed in the hope + that it will be useful,but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. You should have received a copy + of the GNU General Public License along with this program (see the file + COPYING). If not, see . + */ + +module e_link(/*AUTOARG*/ + // Outputs + rowid, colid, reset_n, cclk_p, cclk_n, rx_wr_wait_p, rx_wr_wait_n, + rx_rd_wait_p, rx_rd_wait_n, tx_lclk_p, tx_lclk_n, tx_frame_p, + tx_frame_n, tx_data_p, tx_data_n, embox_not_empty, embox_full, + m_axi_araddr, m_axi_arburst, m_axi_arcache, m_axi_arid, + m_axi_arlen, m_axi_arlock, m_axi_arprot, m_axi_arqos, m_axi_arsize, + m_axi_arvalid, m_axi_awaddr, m_axi_awburst, m_axi_awcache, + m_axi_awid, m_axi_awlen, m_axi_awlock, m_axi_awprot, m_axi_awqos, + m_axi_awsize, m_axi_awvalid, m_axi_bready, m_axi_rready, + m_axi_wdata, m_axi_wlast, m_axi_wstrb, m_axi_wvalid, s_axi_arready, + s_axi_awready, s_axi_bid, s_axi_bresp, s_axi_bvalid, s_axi_rdata, + s_axi_rid, s_axi_rlast, s_axi_rresp, s_axi_rvalid, s_axi_wready, + s_axicfg_arready, s_axicfg_awready, s_axicfg_bresp, + s_axicfg_bvalid, s_axicfg_rdata, s_axicfg_rresp, s_axicfg_rvalid, + s_axicfg_wready, + // Inputs + hw_reset, clkin, rx_lclk_p, rx_lclk_n, rx_frame_p, rx_frame_n, + rx_data_p, rx_data_n, tx_wr_wait_p, tx_wr_wait_n, tx_rd_wait_p, + tx_rd_wait_n, m_axi_aclk, m_axi_aresetn, m_axi_arready, + m_axi_awready, m_axi_bid, m_axi_bresp, m_axi_bvalid, m_axi_rdata, + m_axi_rid, m_axi_rlast, m_axi_rresp, m_axi_rvalid, m_axi_wready, + s_axi_aclk, s_axi_aresetn, s_axi_araddr, s_axi_arburst, + s_axi_arcache, s_axi_arid, s_axi_arlen, s_axi_arlock, s_axi_arprot, + s_axi_arqos, s_axi_arregion, s_axi_arsize, s_axi_arvalid, + s_axi_awaddr, s_axi_awburst, s_axi_awcache, s_axi_awid, + s_axi_awlen, s_axi_awlock, s_axi_awprot, s_axi_awqos, + s_axi_awregion, s_axi_awsize, s_axi_awvalid, s_axi_bready, + s_axi_rready, s_axi_wdata, s_axi_wlast, s_axi_wstrb, s_axi_wvalid, + s_axicfg_araddr, s_axicfg_arprot, s_axicfg_arvalid, + s_axicfg_awaddr, s_axicfg_awprot, s_axicfg_awvalid, + s_axicfg_bready, s_axicfg_rready, s_axicfg_wdata, s_axicfg_wstrb, + s_axicfg_wvalid + ); + parameter COREID = `CFG_COREID; + + + /****************************/ + /*BASIC SIGNALS */ + /****************************/ + input hw_reset; //active high asynchronous hardware reset + input clkin; //primary clock input + + /*****************************/ + /*EPIPHANY BASIC INTERFACE */ + /*****************************/ + output [3:0] rowid; //row id to drive out to Epiphany + output [3:0] colid; //col id to drive out to Epiphany + output reset_n; //reset signal for Epiphany (active low) + output cclk_p; //high speed core clock (1GHz) to Epiphany + output cclk_n; + + /*****************************/ + /*ELINK INTERFACE (I/O PINS) */ + /*****************************/ + //Receiver + input rx_lclk_p; //linkh speed clock input (up to 500MHz) + input rx_lclk_n; + input rx_frame_p; //transaction frame signal + input rx_frame_n; + input [7:0] rx_data_p; //receive data (dual data rate) + input [7:0] rx_data_n; + output rx_wr_wait_p; //outgoing pushback on write transactions + output rx_wr_wait_n; + output rx_rd_wait_p; //outgoing pushback on read transactions + output rx_rd_wait_n; + + //Transmitter + output tx_lclk_p; //hlink clock output (up to 500MHz) + output tx_lclk_n; + output tx_frame_p; //transaction frame signal + output tx_frame_n; + output [7:0] tx_data_p; //transmit data (dual data rate) + output [7:0] tx_data_n; + input tx_wr_wait_p; //incoming pushback on write transactions + input tx_wr_wait_n; + input tx_rd_wait_p; //incoming pushback on read transactions + input tx_rd_wait_n; + + /*****************************/ + /*MAILBOX */ + /*****************************/ + output embox_not_empty; + output embox_full; + + /*****************************/ + /*AXI master interface */ + /*****************************/ + //Clock and reset + input m_axi_aclk; + input m_axi_aresetn; + + //Read address channel + output [31:0] m_axi_araddr; //read address + output [1:0] m_axi_arburst; //burst type + output [3:0] m_axi_arcache; //memory type + output [0:0] m_axi_arid; //address ID + output [7:0] m_axi_arlen; //burst length (number of data transfers) + output [0:0] m_axi_arlock; //lock type (atomic characteristics) + output [2:0] m_axi_arprot; //protection type + output [3:0] m_axi_arqos; //quality of service (setting?) + input m_axi_arready; //read ready + output [2:0] m_axi_arsize; //burst size (the size of each transfer) + output m_axi_arvalid; //write address valid + + //Write address channel + output [31:0] m_axi_awaddr; + output [1:0] m_axi_awburst; + output [3:0] m_axi_awcache; + output [0:0] m_axi_awid; + output [7:0] m_axi_awlen; + output [0:0] m_axi_awlock; + output [2:0] m_axi_awprot; + output [3:0] m_axi_awqos; + input m_axi_awready; + output [2:0] m_axi_awsize; + output m_axi_awvalid; + + //Buffered write response channel + input [0:0] m_axi_bid; //response tag + output m_axi_bready; + input [1:0] m_axi_bresp; + input m_axi_bvalid; + + //Read channel + input [63:0] m_axi_rdata; + input [0:0] m_axi_rid; //read id tag + input m_axi_rlast; //indicates last transfer of a burst + output m_axi_rready; //read ready signal + input [1:0] m_axi_rresp; + input m_axi_rvalid; + + //Write channel + output [63:0] m_axi_wdata; + output m_axi_wlast; //indicates last transfer of a burs + input m_axi_wready; //response ready + output [7:0] m_axi_wstrb; + output m_axi_wvalid; + + /*****************************/ + /*AXI slave interface */ + /*****************************/ + //Clock and reset + input s_axi_aclk; + input s_axi_aresetn; + + //Read address channel + input [29:0] s_axi_araddr; + input [1:0] s_axi_arburst; + input [3:0] s_axi_arcache; + input [11:0] s_axi_arid; + input [7:0] s_axi_arlen; + input [0:0] s_axi_arlock; + input [2:0] s_axi_arprot; + input [3:0] s_axi_arqos; + output s_axi_arready; + input [3:0] s_axi_arregion; + input [2:0] s_axi_arsize; + input s_axi_arvalid; + + //Write address channel + input [29:0] s_axi_awaddr; + input [1:0] s_axi_awburst; + input [3:0] s_axi_awcache; + input [11:0] s_axi_awid; + input [7:0] s_axi_awlen; + input [0:0] s_axi_awlock; + input [2:0] s_axi_awprot; + input [3:0] s_axi_awqos; + output s_axi_awready; + input [3:0] s_axi_awregion; + input [2:0] s_axi_awsize; + input s_axi_awvalid; + + //Buffered write response channel + output [11:0] s_axi_bid; + input s_axi_bready; + output [1:0] s_axi_bresp; + output s_axi_bvalid; + + //Read channel + output [31:0] s_axi_rdata; + output [11:0] s_axi_rid; + output s_axi_rlast; + input s_axi_rready; + output [1:0] s_axi_rresp; + output s_axi_rvalid; + + //Write channel + input [31:0] s_axi_wdata; + input s_axi_wlast; + output s_axi_wready; + input [3:0] s_axi_wstrb; + input s_axi_wvalid; + + /*****************************/ + /*AXI config slave interface */ + /*****************************/ + + //read address channel + input [12:0] s_axicfg_araddr; + input [2:0] s_axicfg_arprot; + output s_axicfg_arready; + input s_axicfg_arvalid; + + //write address channel + input [12:0] s_axicfg_awaddr; + input [2:0] s_axicfg_awprot; + output s_axicfg_awready; + input s_axicfg_awvalid; + + //buffered read response channel + input s_axicfg_bready; + output [1:0] s_axicfg_bresp; + output s_axicfg_bvalid; + + //read channel + output [31:0] s_axicfg_rdata; + input s_axicfg_rready; + output [1:0] s_axicfg_rresp; + output s_axicfg_rvalid; + + //write channel + input [31:0] s_axicfg_wdata; + output s_axicfg_wready; + input [3:0] s_axicfg_wstrb; + input s_axicfg_wvalid; + + //wires + wire [31:0] mi_rd_data; + wire [31:0] mi_dout_ecfg; + wire [31:0] mi_dout_embox; + wire [31:0] mi_dout_rx; + wire [31:0] mi_dout_tx; + + /*AUTOINPUT*/ + + /*AUTOOUTPUT*/ + + /*AUTOWIRE*/ + // Beginning of automatic wires (for undeclared instantiated-module outputs) + wire [3:0] ecfg_cclk_div; // From ecfg of ecfg.v + wire ecfg_cclk_en; // From ecfg of ecfg.v + wire [3:0] ecfg_cclk_pllcfg; // From ecfg of ecfg.v + wire [11:0] ecfg_coreid; // From ecfg of ecfg.v + wire [8:0] ecfg_datain; // From erx of erx.v + wire [10:0] ecfg_dataout; // From ecfg of ecfg.v + wire [15:0] ecfg_rx_debug_signals; // From erx of erx.v + wire ecfg_rx_enable; // From ecfg of ecfg.v + wire ecfg_rx_gpio_mode; // From ecfg of ecfg.v + wire ecfg_rx_mmu_mode; // From ecfg of ecfg.v + wire [3:0] ecfg_tx_clkdiv; // From ecfg of ecfg.v + wire [3:0] ecfg_tx_ctrl_mode; // From ecfg of ecfg.v + wire [15:0] ecfg_tx_debug_signals; // From etx of etx.v + wire ecfg_tx_enable; // From ecfg of ecfg.v + wire ecfg_tx_gpio_mode; // From ecfg of ecfg.v + wire ecfg_tx_mmu_mode; // From ecfg of ecfg.v + wire ecfg_tx_tp_mode; // From ecfg of ecfg.v + wire emaxi_emrq_empty; // From erx of erx.v + wire [102:0] emaxi_emrq_rd_data; // From erx of erx.v + wire emaxi_emrq_rd_en; // From emaxi of emaxi.v + wire emaxi_emrr_full; // From etx of etx.v + wire emaxi_emrr_prog_full; // From etx of etx.v + wire [102:0] emaxi_emrr_wr_data; // From emaxi of emaxi.v + wire emaxi_emrr_wr_en; // From emaxi of emaxi.v + wire emaxi_emwr_empty; // From erx of erx.v + wire [102:0] emaxi_emwr_rd_data; // From erx of erx.v + wire emaxi_emwr_rd_en; // From emaxi of emaxi.v + wire esaxi_emrq_full; // From etx of etx.v + wire esaxi_emrq_prog_full; // From etx of etx.v + wire [102:0] esaxi_emrq_wr_data; // From esaxi of esaxi.v + wire esaxi_emrq_wr_en; // From esaxi of esaxi.v + wire esaxi_emrr_empty; // From erx of erx.v + wire [102:0] esaxi_emrr_rd_data; // From erx of erx.v + wire esaxi_emrr_rd_en; // From esaxi of esaxi.v + wire esaxi_emwr_full; // From etx of etx.v + wire esaxi_emwr_prog_full; // From etx of etx.v + wire [102:0] esaxi_emwr_wr_data; // From esaxi of esaxi.v + wire esaxi_emwr_wr_en; // From esaxi of esaxi.v + wire [RFAW-1:0] mi_addr; // From esaxilite of esaxilite.v + wire mi_clk; // From esaxilite of esaxilite.v + wire [31:0] mi_din; // From esaxilite of esaxilite.v + wire mi_en; // From esaxilite of esaxilite.v + wire mi_we; // From esaxilite of esaxilite.v + wire reset; // From ecfg of ecfg.v + wire txlclk_out; // From eclock of eclock.v + wire txlclk_p; // From eclock of eclock.v + wire txlclk_s; // From eclock of eclock.v + // End of automatics + + + + /***********************************************************/ + /*AXI MASTER */ + /***********************************************************/ + /*emaxi AUTO_TEMPLATE ( + // Outputs + .m00_\(.*\) (m_\1[]), + .em\(.*\) (emaxi_em\1[]), + ); + */ + + + emaxi emaxi(/*AUTOINST*/ + // Outputs + .emwr_rd_en (emaxi_emwr_rd_en), // Templated + .emrq_rd_en (emaxi_emrq_rd_en), // Templated + .emrr_wr_data (emaxi_emrr_wr_data[102:0]), // Templated + .emrr_wr_en (emaxi_emrr_wr_en), // Templated + .m00_axi_awid (m_axi_awid[0:0]), // Templated + .m00_axi_awaddr (m_axi_awaddr[31:0]), // Templated + .m00_axi_awlen (m_axi_awlen[7:0]), // Templated + .m00_axi_awsize (m_axi_awsize[2:0]), // Templated + .m00_axi_awburst (m_axi_awburst[1:0]), // Templated + .m00_axi_awlock (m_axi_awlock), // Templated + .m00_axi_awcache (m_axi_awcache[3:0]), // Templated + .m00_axi_awprot (m_axi_awprot[2:0]), // Templated + .m00_axi_awqos (m_axi_awqos[3:0]), // Templated + .m00_axi_awvalid (m_axi_awvalid), // Templated + .m00_axi_wdata (m_axi_wdata[31:0]), // Templated + .m00_axi_wstrb (m_axi_wstrb[3:0]), // Templated + .m00_axi_wlast (m_axi_wlast), // Templated + .m00_axi_wvalid (m_axi_wvalid), // Templated + .m00_axi_bready (m_axi_bready), // Templated + .m00_axi_arid (m_axi_arid[0:0]), // Templated + .m00_axi_araddr (m_axi_araddr[31:0]), // Templated + .m00_axi_arlen (m_axi_arlen[7:0]), // Templated + .m00_axi_arsize (m_axi_arsize[2:0]), // Templated + .m00_axi_arburst (m_axi_arburst[1:0]), // Templated + .m00_axi_arlock (m_axi_arlock), // Templated + .m00_axi_arcache (m_axi_arcache[3:0]), // Templated + .m00_axi_arprot (m_axi_arprot[2:0]), // Templated + .m00_axi_arqos (m_axi_arqos[3:0]), // Templated + .m00_axi_arvalid (m_axi_arvalid), // Templated + .m00_axi_rready (m_axi_rready), // Templated + // Inputs + .emwr_rd_data (emaxi_emwr_rd_data[102:0]), // Templated + .emwr_empty (emaxi_emwr_empty), // Templated + .emrq_rd_data (emaxi_emrq_rd_data[102:0]), // Templated + .emrq_empty (emaxi_emrq_empty), // Templated + .emrr_full (emaxi_emrr_full), // Templated + .emrr_prog_full (emaxi_emrr_prog_full), // Templated + .m00_axi_aclk (m_axi_aclk), // Templated + .m00_axi_aresetn (m_axi_aresetn), // Templated + .m00_axi_awready (m_axi_awready), // Templated + .m00_axi_wready (m_axi_wready), // Templated + .m00_axi_bid (m_axi_bid[0:0]), // Templated + .m00_axi_bresp (m_axi_bresp[1:0]), // Templated + .m00_axi_bvalid (m_axi_bvalid), // Templated + .m00_axi_arready (m_axi_arready), // Templated + .m00_axi_rid (m_axi_rid[0:0]), // Templated + .m00_axi_rdata (m_axi_rdata[31:0]), // Templated + .m00_axi_rresp (m_axi_rresp[1:0]), // Templated + .m00_axi_rlast (m_axi_rlast), // Templated + .m00_axi_rvalid (m_axi_rvalid)); // Templated + + /***********************************************************/ + /*AXI SLAVE */ + /***********************************************************/ + /*esaxi AUTO_TEMPLATE ( + // Outputs + .s00_\(.*\) (s_\1[]), + .em\(.*\) (esaxi_em\1[]), + ); + */ + + esaxi esaxi(/*AUTOINST*/ + // Outputs + .emwr_wr_data (esaxi_emwr_wr_data[102:0]), // Templated + .emwr_wr_en (esaxi_emwr_wr_en), // Templated + .emrq_wr_data (esaxi_emrq_wr_data[102:0]), // Templated + .emrq_wr_en (esaxi_emrq_wr_en), // Templated + .emrr_rd_en (esaxi_emrr_rd_en), // Templated + .s00_axi_awready (s_axi_awready), // Templated + .s00_axi_wready (s_axi_wready), // Templated + .s00_axi_bid (s_axi_bid[0:0]), // Templated + .s00_axi_bresp (s_axi_bresp[1:0]), // Templated + .s00_axi_bvalid (s_axi_bvalid), // Templated + .s00_axi_arready (s_axi_arready), // Templated + .s00_axi_rid (s_axi_rid[0:0]), // Templated + .s00_axi_rdata (s_axi_rdata[31:0]), // Templated + .s00_axi_rresp (s_axi_rresp[1:0]), // Templated + .s00_axi_rlast (s_axi_rlast), // Templated + .s00_axi_rvalid (s_axi_rvalid), // Templated + // Inputs + .emwr_full (esaxi_emwr_full), // Templated + .emwr_prog_full (esaxi_emwr_prog_full), // Templated + .emrq_full (esaxi_emrq_full), // Templated + .emrq_prog_full (esaxi_emrq_prog_full), // Templated + .emrr_rd_data (esaxi_emrr_rd_data[102:0]), // Templated + .emrr_empty (esaxi_emrr_empty), // Templated + .ecfg_tx_ctrl_mode (ecfg_tx_ctrl_mode[3:0]), + .ecfg_coreid (ecfg_coreid[11:0]), + .s00_axi_aclk (s_axi_aclk), // Templated + .s00_axi_aresetn (s_axi_aresetn), // Templated + .s00_axi_awid (s_axi_awid[0:0]), // Templated + .s00_axi_awaddr (s_axi_awaddr[29:0]), // Templated + .s00_axi_awlen (s_axi_awlen[7:0]), // Templated + .s00_axi_awsize (s_axi_awsize[2:0]), // Templated + .s00_axi_awburst (s_axi_awburst[1:0]), // Templated + .s00_axi_awlock (s_axi_awlock), // Templated + .s00_axi_awcache (s_axi_awcache[3:0]), // Templated + .s00_axi_awprot (s_axi_awprot[2:0]), // Templated + .s00_axi_awqos (s_axi_awqos[3:0]), // Templated + .s00_axi_awregion (s_axi_awregion[3:0]), // Templated + .s00_axi_awvalid (s_axi_awvalid), // Templated + .s00_axi_wdata (s_axi_wdata[31:0]), // Templated + .s00_axi_wstrb (s_axi_wstrb[3:0]), // Templated + .s00_axi_wlast (s_axi_wlast), // Templated + .s00_axi_wvalid (s_axi_wvalid), // Templated + .s00_axi_bready (s_axi_bready), // Templated + .s00_axi_arid (s_axi_arid[0:0]), // Templated + .s00_axi_araddr (s_axi_araddr[29:0]), // Templated + .s00_axi_arlen (s_axi_arlen[7:0]), // Templated + .s00_axi_arsize (s_axi_arsize[2:0]), // Templated + .s00_axi_arburst (s_axi_arburst[1:0]), // Templated + .s00_axi_arlock (s_axi_arlock), // Templated + .s00_axi_arcache (s_axi_arcache[3:0]), // Templated + .s00_axi_arprot (s_axi_arprot[2:0]), // Templated + .s00_axi_arqos (s_axi_arqos[3:0]), // Templated + .s00_axi_arregion (s_axi_arregion[3:0]), // Templated + .s00_axi_arvalid (s_axi_arvalid), // Templated + .s00_axi_rready (s_axi_rready)); // Templated + + /***********************************************************/ + /*AXI CONFIGURATION SLAVE (LITE) */ + /***********************************************************/ + + esaxilite esaxilite( + /*AUTOINST*/ + // Outputs + .s_axicfg_arready(s_axicfg_arready), + .s_axicfg_awready(s_axicfg_awready), + .s_axicfg_bresp (s_axicfg_bresp[1:0]), + .s_axicfg_bvalid(s_axicfg_bvalid), + .s_axicfg_rdata (s_axicfg_rdata[31:0]), + .s_axicfg_rresp (s_axicfg_rresp[1:0]), + .s_axicfg_rvalid(s_axicfg_rvalid), + .s_axicfg_wready(s_axicfg_wready), + .mi_clk (mi_clk), + .mi_en (mi_en), + .mi_we (mi_we), + .mi_addr (mi_addr[RFAW-1:0]), + .mi_din (mi_din[31:0]), + // Inputs + .s_axicfg_araddr(s_axicfg_araddr[15:0]), + .s_axicfg_arprot(s_axicfg_arprot[2:0]), + .s_axicfg_arvalid(s_axicfg_arvalid), + .s_axicfg_awaddr(s_axicfg_awaddr[15:0]), + .s_axicfg_awprot(s_axicfg_awprot[2:0]), + .s_axicfg_awvalid(s_axicfg_awvalid), + .s_axicfg_bready(s_axicfg_bready), + .s_axicfg_rready(s_axicfg_rready), + .s_axicfg_wdata (s_axicfg_wdata[31:0]), + .s_axicfg_wstrb (s_axicfg_wstrb[3:0]), + .s_axicfg_wvalid(s_axicfg_wvalid), + .mi_rd_data (mi_rd_data[31:0])); + + /***********************************************************/ + /*ELINK CLOCK GENERATOR */ + /***********************************************************/ + + eclock eclock(/*AUTOINST*/ + // Outputs + .cclk_p (cclk_p), + .cclk_n (cclk_n), + .txlclk_s (txlclk_s), + .txlclk_out (txlclk_out), + .txlclk_p (txlclk_p), + // Inputs + .clkin (clkin), + .reset (reset), + .ecfg_cclk_en (ecfg_cclk_en), + .ecfg_cclk_div (ecfg_cclk_div[3:0]), + .ecfg_cclk_pllcfg (ecfg_cclk_pllcfg[3:0])); + + + /***********************************************************/ + /*RECEIVER */ + /***********************************************************/ + + erx erx(.mi_dout (mi_dout_rx[DW-1:0]), + /*AUTOINST*/ + // Outputs + .ecfg_rx_debug_signals (ecfg_rx_debug_signals[15:0]), + .ecfg_datain (ecfg_datain[8:0]), + .emaxi_emwr_empty (emaxi_emwr_empty), + .emaxi_emwr_rd_data (emaxi_emwr_rd_data[102:0]), + .emaxi_emrq_empty (emaxi_emrq_empty), + .emaxi_emrq_rd_data (emaxi_emrq_rd_data[102:0]), + .esaxi_emrr_empty (esaxi_emrr_empty), + .esaxi_emrr_rd_data (esaxi_emrr_rd_data[102:0]), + .rx_wr_wait_p (rx_wr_wait_p), + .rx_wr_wait_n (rx_wr_wait_n), + .rx_rd_wait_p (rx_rd_wait_p), + .rx_rd_wait_n (rx_rd_wait_n), + // Inputs + .reset (reset), + .s_axi_aclk (s_axi_aclk), + .m_axi_aclk (m_axi_aclk), + .ecfg_rx_enable (ecfg_rx_enable), + .ecfg_rx_mmu_mode (ecfg_rx_mmu_mode), + .ecfg_rx_gpio_mode (ecfg_rx_gpio_mode), + .ecfg_dataout (ecfg_dataout[10:0]), + .emaxi_emwr_rd_en (emaxi_emwr_rd_en), + .emaxi_emrq_rd_en (emaxi_emrq_rd_en), + .esaxi_emrr_rd_en (esaxi_emrr_rd_en), + .rx_lclk_p (rx_lclk_p), + .rx_lclk_n (rx_lclk_n), + .rx_frame_p (rx_frame_p), + .rx_frame_n (rx_frame_n), + .rx_data_p (rx_data_p[7:0]), + .rx_data_n (rx_data_n[7:0]), + .mi_clk (mi_clk), + .mi_en (mi_en), + .mi_we (mi_we), + .mi_addr (mi_addr[RFAW-1:0]), + .mi_din (mi_din[31:0])); + + + /***********************************************************/ + /*TRANSMITTER */ + /***********************************************************/ + etx etx(.mi_dout (mi_dout_tx[DW-1:0]), + /*AUTOINST*/ + // Outputs + .ecfg_tx_debug_signals (ecfg_tx_debug_signals[15:0]), + .esaxi_emrq_full (esaxi_emrq_full), + .esaxi_emrq_prog_full (esaxi_emrq_prog_full), + .esaxi_emwr_full (esaxi_emwr_full), + .esaxi_emwr_prog_full (esaxi_emwr_prog_full), + .emaxi_emrr_full (emaxi_emrr_full), + .emaxi_emrr_prog_full (emaxi_emrr_prog_full), + .tx_lclk_p (tx_lclk_p), + .tx_lclk_n (tx_lclk_n), + .tx_frame_p (tx_frame_p), + .tx_frame_n (tx_frame_n), + .tx_data_p (tx_data_p[7:0]), + .tx_data_n (tx_data_n[7:0]), + // Inputs + .reset (reset), + .txlclk_out (txlclk_out), + .txlclk_p (txlclk_p), + .txlclk_s (txlclk_s), + .s_axi_aclk (s_axi_aclk), + .m_axi_aclk (m_axi_aclk), + .ecfg_tx_clkdiv (ecfg_tx_clkdiv[3:0]), + .ecfg_tx_enable (ecfg_tx_enable), + .ecfg_tx_gpio_mode (ecfg_tx_gpio_mode), + .ecfg_tx_mmu_mode (ecfg_tx_mmu_mode), + .ecfg_dataout (ecfg_dataout[10:0]), + .ecfg_tx_tp_mode (ecfg_tx_tp_mode), + .esaxi_emrq_wr_en (esaxi_emrq_wr_en), + .esaxi_emrq_wr_data (esaxi_emrq_wr_data[102:0]), + .esaxi_emwr_wr_en (esaxi_emwr_wr_en), + .esaxi_emwr_wr_data (esaxi_emwr_wr_data[102:0]), + .emaxi_emrr_wr_en (emaxi_emrr_wr_en), + .emaxi_emrr_wr_data (emaxi_emrr_wr_data[102:0]), + .tx_wr_wait_p (tx_wr_wait_p), + .tx_wr_wait_n (tx_wr_wait_n), + .tx_rd_wait_p (tx_rd_wait_p), + .tx_rd_wait_n (tx_rd_wait_n)); + + + /***********************************************************/ + /*ELINK CONFIGURATION REGISTERES */ + /***********************************************************/ + + /*ecfg AUTO_TEMPLATE ( + // Outputs + .ecfg_reset (reset), + .ecfg_debug_signals ({embox_full, embox_not_empty, ecfg_rx_debug_signals[13:0],ecfg_tx_debug_signals[15:0]}), + ); + */ + + + ecfg ecfg(.mi_dout (mi_dout_ecfg[DW-1:0]), + /*AUTOINST*/ + // Outputs + .ecfg_reset (reset), // Templated + .ecfg_tx_enable (ecfg_tx_enable), + .ecfg_tx_mmu_mode (ecfg_tx_mmu_mode), + .ecfg_tx_gpio_mode (ecfg_tx_gpio_mode), + .ecfg_tx_tp_mode (ecfg_tx_tp_mode), + .ecfg_tx_ctrl_mode (ecfg_tx_ctrl_mode[3:0]), + .ecfg_tx_clkdiv (ecfg_tx_clkdiv[3:0]), + .ecfg_rx_enable (ecfg_rx_enable), + .ecfg_rx_mmu_mode (ecfg_rx_mmu_mode), + .ecfg_rx_gpio_mode (ecfg_rx_gpio_mode), + .ecfg_cclk_en (ecfg_cclk_en), + .ecfg_cclk_div (ecfg_cclk_div[3:0]), + .ecfg_cclk_pllcfg (ecfg_cclk_pllcfg[3:0]), + .ecfg_coreid (ecfg_coreid[11:0]), + .ecfg_dataout (ecfg_dataout[10:0]), + // Inputs + .hw_reset (hw_reset), + .mi_clk (mi_clk), + .mi_en (mi_en), + .mi_we (mi_we), + .mi_addr (mi_addr[RFAW-1:0]), + .mi_din (mi_din[31:0]), + .ecfg_datain (ecfg_datain[10:0]), + .ecfg_debug_signals ({embox_full, embox_not_empty, ecfg_rx_debug_signals[13:0],ecfg_tx_debug_signals[15:0]})); // Templated + + + /***********************************************************/ + /*GENERAL PURPOSE MAILBOX */ + /***********************************************************/ + + embox embox(.clk (mi_clk), + .mi_dout (mi_dout_embox[DW-1:0]), + /*AUTOINST*/ + // Outputs + .embox_full (embox_full), + .embox_not_empty (embox_not_empty), + // Inputs + .reset (reset), + .mi_en (mi_en), + .mi_we (mi_we), + .mi_addr (mi_addr[RFAW-1:0]), + .mi_din (mi_din[DW-1:0])); + + /***********************************************************/ + /*AXI-LITE READBACK */ + /***********************************************************/ + //TODO: fix decode logic + + assign mi_rd_data[31:0] = (mi_addr[15:14]==2'b00) ? mi_dout_ecfg[31:0] : + (mi_addr[15:14]==2'b01) ? mi_dout_embox[31:0] : + (mi_addr[15:14]==2'b10) ? mi_dout_rx[31:0] : + mi_dout_tx[31:0] ; + +endmodule // elink +// Local Variables: +// verilog-library-directories:("." "../../embox/hdl" "../../erx/hdl" "../../etx/hdl" "../../emaxi/hdl" "../../esaxi/hdl" "../../esaxilite/hdl" ) +// End: +