422 lines
17 KiB
Verilog
422 lines
17 KiB
Verilog
`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
|