`timescale 1ns / 100ps ////////////////////////////////////////////////////////////////////////////////// // Company: Beijing Institute of Technology // Engineer: FanHao // // Create Date: 02/08/2023 04:40:51 PM // Design Name: // Module Name: axi_lite // Project Name: // Target Devices: // Tool Versions: 2022.2 // Description: An axi-lite wrap for register configuration // // Dependencies: up_axi // // Revision: // [0.0-01] - Initial Version: Add asynchronized clock support. // [0.0-00] - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module phy_control #( parameter ASYNC_CLK = 1, // parameter REG_SPACE_ADDR_WIDTH = 5, parameter AXI_ADDRESS_WIDTH = 5 ) ( /********************************************************************************/ /************************** Slave AXI-LITE interface ****************************/ /********************************************************************************/ //--- DO NOT MODIFY FOLLOWING CONTANT (* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME ACLK, PHASE 0.000" *) (* X_INTERFACE_INFO = "xilinx.com:signal:clock:1.0 ACLK CLK" *) input s_axi_aclk, (* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME ARESETN, POLARITY ACTIVE_LOW" *) (* X_INTERFACE_INFO = "xilinx.com:signal:reset:1.0 ARESETN RST" *) input s_axi_aresetn, (* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME S_AXI, CLK_DOMAIN ACLK, DATA_WIDTH 32, PROTOCOL AXI4LITE, READ_WRITE_MODE READ_WRITE" *) (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI AWVALID" *) input s_axi_awvalid, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI AWADDR" *) input [AXI_ADDRESS_WIDTH-1:0] s_axi_awaddr, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI AWREADY" *) output s_axi_awready, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI AWPROT" *) input [ 2:0] s_axi_awprot, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI WVALID" *) input s_axi_wvalid, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI WDATA" *) input [ 31:0] s_axi_wdata, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI WSTRB" *) input [ 3:0] s_axi_wstrb, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI WREADY" *) output s_axi_wready, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI BVALID" *) output s_axi_bvalid, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI BRESP" *) output [ 1:0] s_axi_bresp, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI BREADY" *) input s_axi_bready, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI ARVALID" *) input s_axi_arvalid, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI ARADDR" *) input [AXI_ADDRESS_WIDTH-1:0] s_axi_araddr, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI ARREADY" *) output s_axi_arready, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI ARPROT" *) input [ 2:0] s_axi_arprot, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI RVALID" *) output s_axi_rvalid, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI RREADY" *) input s_axi_rready, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI RRESP" *) output [ 1:0] s_axi_rresp, (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 S_AXI RDATA" *) output [ 31:0] s_axi_rdata, //--- DO NOT MODIFY CONTANT ABOVE /********************************************************************************/ /******************************** User Interface ********************************/ /********************************************************************************/ //--- ADD YOUR OWN PORTS START // main clock input clk, // can be floating if ASYNC_CLK == 0 // resetn (should synchronised with "clk") input rstn, // can be floating if ASYNC_CLK == 0 // control sigal output wire phy_rst, output wire phy_tx_test_flag, output wire phy_tx_iq_reverse, output wire phy_rx_iq_reverse, // tdma parameters output wire tdma_flag_is_master, output wire [31:0] tdma_slot_len, output wire [31:0] tdma_tic_2_ps, output wire [31:0] tdma_id_cfg, output wire tdma_recv_cur_slot_id_valid, output wire [ 7:0] tdma_recv_cur_slot_id, output wire [31:0] tdma_frame_sync_tic //--- ADD YOUR OWN PORTS END ); // MODULE_VERSION[31:24] Major Version // MODULE_VERSION[23:16] Minor Version // MODULE_VERSION[15: 0] Revision localparam MODULE_VERSION = 'h000001; /********************************************************************************/ /******************************** Interface Logic *******************************/ /********************************************************************************/ //--- DO NOT MODIFY FOLLOWING CONTANT // Module internal signals wire local_clk; wire local_rstn; wire up_rreq_s; reg [ 31:0] up_rdata_ff = 'd0; reg up_rack_ff = 1'b0; wire up_wreq_s; wire [ 31:0] up_wdata_s; reg up_wack_ff = 1'b0; wire [(AXI_ADDRESS_WIDTH-3):0] up_waddr_s; wire [(AXI_ADDRESS_WIDTH-3):0] up_raddr_s; // up_axi interface signals wire up_rack; wire up_rreq; wire [ 31:0] up_rdata; wire up_wack; wire up_wreq; wire [ 31:0] up_wdata; wire [(AXI_ADDRESS_WIDTH-3):0] up_waddr; wire [(AXI_ADDRESS_WIDTH-3):0] up_raddr; // following signals indicate corresponding rep/ack were received. wire up_rreq_rcv; wire up_wreq_rcv; wire up_rack_rcv; wire up_wack_rcv; generate if (ASYNC_CLK) begin assign local_clk = clk; assign local_rstn = rstn; // read channel synchronisation reg up_rreq_send = 1'b0; always @(posedge s_axi_aclk) begin if (s_axi_aresetn == 1'b0) begin up_rreq_send <= 1'b0; end else if (up_rreq) begin up_rreq_send <= 1'b1; end else if (up_rreq_rcv) begin up_rreq_send <= 1'b0; end end xpm_cdc_handshake #( .DEST_EXT_HSK(0), .DEST_SYNC_FF(2), .INIT_SYNC_FF(1), .SIM_ASSERT_CHK(1), .SRC_SYNC_FF(2), .WIDTH((AXI_ADDRESS_WIDTH - 2)) // raddr ) i_rd_req_xpm_cdc ( .dest_clk(local_clk), .dest_req(up_rreq_s), .dest_out({up_raddr_s[(AXI_ADDRESS_WIDTH-3):0]}), .src_clk (s_axi_aclk), .src_send(up_rreq_send), .src_rcv (up_rreq_rcv), .src_in ({up_raddr[(AXI_ADDRESS_WIDTH-3):0]}) ); reg up_rack_send = 1'b0; always @(posedge local_clk) begin if (local_rstn == 1'b0) begin up_rack_send <= 1'b0; end else if (up_rack_ff) begin up_rack_send <= 1'b1; end else if (up_rack_rcv) begin up_rack_send <= 1'b0; end end xpm_cdc_handshake #( .DEST_EXT_HSK(0), .DEST_SYNC_FF(2), .INIT_SYNC_FF(1), .SIM_ASSERT_CHK(1), .SRC_SYNC_FF(2), .WIDTH(32) //rdata ) i_rd_rsp_xpm_cdc ( .dest_clk(s_axi_aclk), .dest_req(up_rack), .dest_out({up_rdata[31:0]}), .src_clk (local_clk), .src_send(up_rack_send), .src_rcv (up_rack_rcv), .src_in ({up_rdata_ff[31:0]}) ); // write channel synchronisation reg up_wreq_send = 1'b0; always @(posedge s_axi_aclk) begin if (s_axi_aresetn == 1'b0) begin up_wreq_send <= 1'b0; end else if (up_wreq) begin up_wreq_send <= 1'b1; end else if (up_wreq_rcv) begin up_wreq_send <= 1'b0; end end xpm_cdc_handshake #( .DEST_EXT_HSK(0), .DEST_SYNC_FF(2), .INIT_SYNC_FF(1), .SIM_ASSERT_CHK(1), .SRC_SYNC_FF(2), .WIDTH((AXI_ADDRESS_WIDTH - 2) + 32) //waddr + wdata ) i_wr_req_ctrl_xpm_cdc ( .dest_clk(local_clk), .dest_req(up_wreq_s), .dest_out({up_waddr_s[(AXI_ADDRESS_WIDTH-3):0], up_wdata_s[31:0]}), .src_clk (s_axi_aclk), .src_send(up_wreq_send), .src_rcv (up_wreq_rcv), .src_in ({up_waddr[(AXI_ADDRESS_WIDTH-3):0], up_wdata[31:0]}) ); reg up_wack_send = 1'b0; always @(posedge local_clk) begin if (local_rstn == 1'b0) begin up_wack_send <= 1'b0; end else if (up_wack_ff) begin up_wack_send <= 1'b1; end else if (up_wack_rcv) begin up_wack_send <= 1'b0; end end xpm_cdc_handshake #( .DEST_EXT_HSK(0), .DEST_SYNC_FF(2), .INIT_SYNC_FF(1), .SIM_ASSERT_CHK(1), .SRC_SYNC_FF(2), .WIDTH(1) // wack ) i_wr_rsp_data_xpm_cdc ( .dest_clk(s_axi_aclk), .dest_req(up_wack), .src_clk (local_clk), .src_send(up_wack_send), .src_rcv (up_wack_rcv), .src_in (1) ); end else begin assign local_clk = s_axi_aclk; assign local_rstn = s_axi_aresetn; assign up_rack = up_rack_ff; assign up_rreq_s = up_rreq; assign up_rdata = up_rdata_ff; assign up_wack = up_wack_ff; assign up_wreq_s = up_wreq; assign up_wdata_s[31:0] = up_wdata[31:0]; assign up_waddr_s[(AXI_ADDRESS_WIDTH-3):0] = up_waddr[(AXI_ADDRESS_WIDTH-3):0]; assign up_raddr_s = up_raddr[(AXI_ADDRESS_WIDTH-3):0]; assign up_rreq_rcv = up_rreq_s; assign up_wreq_rcv = up_wreq_s; assign up_rack_rcv = up_rack_ff; assign up_wack_rcv = up_wack_ff; end endgenerate // up-axi interface wrapper up_axi #( .AXI_ADDRESS_WIDTH(AXI_ADDRESS_WIDTH) ) i_up_axi ( .up_rstn (s_axi_aresetn), .up_clk (s_axi_aclk), .up_axi_awvalid(s_axi_awvalid), .up_axi_awaddr (s_axi_awaddr), .up_axi_awready(s_axi_awready), .up_axi_wvalid (s_axi_wvalid), .up_axi_wdata (s_axi_wdata), .up_axi_wstrb (s_axi_wstrb), .up_axi_wready (s_axi_wready), .up_axi_bvalid (s_axi_bvalid), .up_axi_bresp (s_axi_bresp), .up_axi_bready (s_axi_bready), .up_axi_arvalid(s_axi_arvalid), .up_axi_araddr (s_axi_araddr), .up_axi_arready(s_axi_arready), .up_axi_rvalid (s_axi_rvalid), .up_axi_rresp (s_axi_rresp), .up_axi_rdata (s_axi_rdata), .up_axi_rready (s_axi_rready), .up_wreq (up_wreq), .up_waddr (up_waddr), .up_wdata (up_wdata), .up_wack (up_wack), .up_rreq (up_rreq), .up_raddr (up_raddr), .up_rdata (up_rdata), .up_rack (up_rack) ); always @(posedge local_clk) begin if (local_rstn == 1'b0) begin up_rack_ff <= 'd0; end else begin up_rack_ff <= up_rreq_s; end end always @(posedge local_clk) begin if (local_rstn == 1'b0) begin up_wack_ff <= 1'b0; end else begin up_wack_ff <= up_wreq_s; end end //--- DO NOT MODIFY CONTANT ABOVE /********************************************************************************/ /********************************** User Logic **********************************/ /********************************************************************************/ // BASIC RULES: // 1. AIX Write operation alwayse has the highet priority. // 2. Every userside operation must use "local_clk" as driving clock // 3. Every regoster must have a perfectely defined access type // you can use the following acronyms to define the register's access type // NOTE: different access types can be combined. // RO Read-only // CLRONRD Readable, clears value on read // CLRONWR Readable, Readable, clears value on write // RAZ Read as zero // RO Read only // RUD Read undefined // RW Normal read/write // RWSO Read/write, set only // WAZ Write as zero // WO Write-only // WTC Readable, write a one to clear // RWSO Read/write, set only // RUD Read undefined // RAZ Read as zero // Z Access (read or write) as zero //--- ADD YOUR OWN LOGIC START //--- EXAMPLE CODE START // Register address definitions // NOTE: 物理层寄存器定义,控制寄存器,状态寄存器 localparam integer PHY_CR = 'h00000000 >> 2; // RW localparam integer PHY_SR = 'h00000004 >> 2; // RW localparam integer TDMA_SLOT_LEN = 'h0000_0008 >> 2; localparam integer TDMA_TIC_2_PS = 'h0000_000C >> 2; localparam integer TDMA_ID_CFG = 'h0000_0010 >> 2; localparam integer TDMA_RECV_ID = 'h0000_0014 >> 2; localparam integer TDMA_FRAME_SYNC_TIC = 'h0000_0018 >> 2; // Register definitions reg [31:0] phy_cr_reg = 32'h0; reg [31:0] phy_sr_reg = 32'h0; reg [31:0] tdma_slot_len_reg = 32'h0; reg [31:0] tdma_tic_2_ps_reg = 32'h0; reg [31:0] tdma_id_cfg_reg = 32'h0; // 2B zero pad, 1B slot num, 1B local id reg [31:0] tdma_recv_id_reg = 32'h0; reg [31:0] tdma_frame_sync_tic_reg = 32'h0; // Register Reading always @(posedge local_clk) begin case (up_raddr_s) PHY_CR: up_rdata_ff <= phy_cr_reg; PHY_SR: up_rdata_ff <= phy_sr_reg; default: up_rdata_ff <= 'h00; endcase end // Main Logic always @(posedge local_clk) begin if (local_rstn == 1'b0) begin phy_cr_reg <= 32'h0; phy_sr_reg <= 32'h0; end else begin // AXI write operation alwayse has the higest priority. if (up_wreq_s == 1'b1) begin case (up_waddr_s) PHY_CR: phy_cr_reg <= up_wdata_s; PHY_SR: phy_sr_reg <= up_wdata_s; TDMA_SLOT_LEN: tdma_slot_len_reg <= up_wdata_s; TDMA_TIC_2_PS: tdma_tic_2_ps_reg <= up_wdata_s; TDMA_ID_CFG: tdma_id_cfg_reg <= up_wdata_s; TDMA_RECV_ID: tdma_recv_id_reg <= up_wdata_s; TDMA_FRAME_SYNC_TIC: tdma_frame_sync_tic_reg <= up_wdata_s; endcase end else begin // self logic if (tdma_recv_id_reg[8] == 1) begin tdma_recv_id_reg[8] <= 0; end end end end // control reg definition assign phy_rst = ~phy_cr_reg[0]; assign phy_tx_test_flag = phy_cr_reg[1]; assign phy_tx_iq_reverse = phy_cr_reg[2]; assign phy_rx_iq_reverse = phy_cr_reg[3]; assign tdma_flag_is_master = phy_cr_reg[4]; // tdma assign tdma_slot_len = tdma_slot_len_reg; assign tdma_tic_2_ps = tdma_tic_2_ps_reg; assign tdma_id_cfg = tdma_id_cfg_reg; // received mac frame assign tdma_recv_cur_slot_id = tdma_recv_id_reg[7:0]; assign tdma_recv_cur_slot_id_valid = tdma_recv_id_reg[8]; // frame sync tic assign tdma_frame_sync_tic = tdma_frame_sync_tic_reg; vio_phy_param u_vio_phy_param ( .clk (local_clk), .probe_in0(phy_cr_reg) ); //--- ADD YOUR OWN LOGIC END endmodule