ping.v
来自「xilinx官方PCIcore 有详细说明文档」· Verilog 代码 · 共 563 行 · 第 1/2 页
V
563 行
if (!S_CBE[3]) my_mem_reg[31:24] <= ADIO[31:24]; end end assign #TDLY oe_mem_reg = bar1_rd_cs & S_DATA; assign #TDLY ADIO[31:0] = oe_mem_reg ? my_mem_reg : 32'bz; //******************************************************************// // This section contains the MEM64 implementation. // //******************************************************************// reg [63:0] my_wide_reg; wire oe_wide_reg; always @(posedge CLK or posedge RST) begin : write_my_wide_reg if (RST) my_wide_reg <= 64'h6464646464646464; else if (S_DATA_VLD & bar2_wr_cs) begin if (!S_CBE[0]) my_wide_reg[ 7: 0] <= ADIO[ 7: 0]; if (!S_CBE[1]) my_wide_reg[15: 8] <= ADIO[15: 8]; if (!S_CBE[2]) my_wide_reg[23:16] <= ADIO[23:16]; if (!S_CBE[3]) my_wide_reg[31:24] <= ADIO[31:24]; if (!S_CBE[4]) my_wide_reg[39:32] <= ADIO[39:32]; if (!S_CBE[5]) my_wide_reg[47:40] <= ADIO[47:40]; if (!S_CBE[6]) my_wide_reg[55:48] <= ADIO[55:48]; if (!S_CBE[7]) my_wide_reg[63:56] <= ADIO[63:56]; end end assign #TDLY oe_wide_reg = bar2_rd_cs & S_DATA; assign #TDLY ADIO[63:0] = oe_wide_reg ? my_wide_reg : 64'bz; //******************************************************************// // This section contains the initiator logic. // //******************************************************************// parameter IDLE_S = 0; parameter WRITE32_S = 1; parameter READ32_S = 2; parameter WRITE64_S = 3; parameter READ64_S = 4; reg [3:0] xfer_len; reg [2:0] ping_state; reg [2:0] nxt_ping_state; reg xfer_load_delay; reg mdata_delay; reg feedback; reg pre_done; reg reg_preq32; reg reg_preq64; wire ns_done; wire mdata_fell; wire xfer_load; wire start32; wire start64; wire dir; wire cnt3, cnt2, cnt1; wire fin3, fin2, fin1; wire assert_complete; wire hold_complete; // Bus addresses are obtained from the MEM32 register. // Direction is from IO32[31] and burst length is IO32[3:0]. // A general purpose register file is used for the source // or destination depending on the data transfer direction. always @(ping_state or start32 or start64 or mdata_fell or dir) begin : ping_fsm case (ping_state) // IDLE_S is the idle state. If the state machine is // signaled to start, proceed to the next state. IDLE_S : begin if (start64 & dir) nxt_ping_state = WRITE64_S; else if (start64 & !dir) nxt_ping_state = READ64_S; else if (start32 & dir) nxt_ping_state = WRITE32_S; else if (start32 & !dir) nxt_ping_state = READ32_S; else nxt_ping_state = IDLE_S; end // WRITE64_S stays put until it sees a deassertion of // the M_DATA signal indicating that a transfer is over. // More elaborate FSMs may check error conditions at // the time mdata_fell is asserted. WRITE64_S : begin if (mdata_fell) nxt_ping_state = IDLE_S; else nxt_ping_state = WRITE64_S; end // WRITE32_S stays put until it sees a deassertion of // the M_DATA signal indicating that a transfer is over. // More elaborate FSMs may check error conditions at // the time mdata_fell is asserted. WRITE32_S : begin if (mdata_fell) nxt_ping_state = IDLE_S; else nxt_ping_state = WRITE32_S; end // READ64_S stays put until it sees a deassertion of // the M_DATA signal indicating that a transfer is over. // More elaborate FSMs may check error conditions at // the time mdata_fell is asserted. READ64_S : begin if (mdata_fell) nxt_ping_state = IDLE_S; else nxt_ping_state = READ64_S; end // READ32_S stays put until it sees a deassertion of // the M_DATA signal indicating that a transfer is over. // More elaborate FSMs may check error conditions at // the time mdata_fell is asserted. READ32_S : begin if (mdata_fell) nxt_ping_state = IDLE_S; else nxt_ping_state = READ32_S; end // Include a default state just in case we have any accidents // with the state machine. default : nxt_ping_state = IDLE_S; endcase end always @(posedge CLK or posedge RST) begin : ping_fsm_seq if (RST) ping_state <= IDLE_S; else ping_state <= nxt_ping_state; end // Need a delayed version of M_DATA and also // a delayed version of the transfer length // counter load signal. always @(posedge CLK or posedge RST) begin : misc_signals if (RST) begin mdata_delay <= 1'b0; xfer_load_delay <= 1'b0; pre_done <= 1'b0; reg_preq32 <= 1'b0; reg_preq64 <= 1'b0; end else begin mdata_delay <= M_DATA; xfer_load_delay <= xfer_load; pre_done <= ns_done; reg_preq32 <= PING_REQUEST32; reg_preq64 <= PING_REQUEST64; end end // This is the "set/reset" implementation for // the COMPLETE logic. always @(posedge CLK or posedge RST) begin : hold_it if (RST) feedback <= 1'b0; else if (mdata_fell) feedback <= 1'b0; else if (assert_complete) feedback <= 1'b1; end // This is the transfer length counter. // Transfer lengths may be anywhere from // one to sixteen data phases. always @(posedge CLK or posedge RST) begin : transfer_counter if (RST) xfer_len <= 4'h0; else if (xfer_load) xfer_len <= my_io_reg[3:0]; else if (M_DATA_VLD) xfer_len <= xfer_len - 4'h1; end // Decoded some things for the complete logic. assign #TDLY cnt3 = (xfer_len == 4'h3); assign #TDLY cnt2 = (xfer_len == 4'h2); assign #TDLY cnt1 = (xfer_len == 4'h1); assign #TDLY fin3 = cnt3 & M_DATA_VLD; assign #TDLY fin2 = cnt2 & mdata_delay; assign #TDLY fin1 = cnt1 & xfer_load_delay; // Generate some internal signals. assign #TDLY start32 = reg_preq32; assign #TDLY start64 = reg_preq64; assign #TDLY dir = my_io_reg[31]; assign #TDLY mdata_fell = !M_DATA & mdata_delay; assign #TDLY xfer_load = ((start32 | start64) & (ping_state == IDLE_S)); assign #TDLY assert_complete = fin1 | fin2 | fin3; assign #TDLY hold_complete = feedback; assign #TDLY ns_done = (ping_state != IDLE_S) & mdata_fell; // Drive outputs to the PCI interface. assign #TDLY REQUEST = (ping_state == IDLE_S) & start32; assign #TDLY REQUEST64 = (ping_state == IDLE_S) & start64; assign #TDLY COMPLETE = assert_complete | hold_complete; assign #TDLY M_WRDN = dir; assign #TDLY ADIO[63:0] = M_ADDR_N ? 64'bz : {32'b0,my_mem_reg}; assign #TDLY M_CBE = M_ADDR_N ? 8'h00 : {4'b0000,my_io_reg[7:5], dir}; assign #TDLY PING_DONE = pre_done; // A simple 64-bit register for data transfer. reg [63:0] my_init_reg; wire oe_init_reg; wire xlr, xlw, xhr; assign #TDLY xlr = (ping_state == READ32_S) | (ping_state == READ64_S); assign #TDLY xlw = (ping_state == WRITE32_S) | (ping_state == WRITE64_S); assign #TDLY xhr = (ping_state == READ64_S); always @(posedge CLK or posedge RST) begin : write_my_init_reg if (RST) my_init_reg <= 64'h0000000000000000; else if (M_DATA_VLD) begin if (xlr) my_init_reg[ 7: 0] <= ADIO[ 7: 0]; if (xlr) my_init_reg[15: 8] <= ADIO[15: 8]; if (xlr) my_init_reg[23:16] <= ADIO[23:16]; if (xlr) my_init_reg[31:24] <= ADIO[31:24]; if (xhr) my_init_reg[39:32] <= ADIO[39:32]; if (xhr) my_init_reg[47:40] <= ADIO[47:40]; if (xhr) my_init_reg[55:48] <= ADIO[55:48]; if (xhr) my_init_reg[63:56] <= ADIO[63:56]; end end assign #TDLY oe_init_reg = M_DATA & xlw; assign #TDLY ADIO[63:0] = oe_init_reg ? my_init_reg : 64'bz; //******************************************************************// // This section contains unused signals. // //******************************************************************// assign #TDLY C_TERM = 1'b1; assign #TDLY C_READY = 1'b1; assign #TDLY KEEPOUT = 1'b0; assign #TDLY CFG_SELF = 1'b0; assign #TDLY REQUESTHOLD = 1'b0; assign #TDLY SUB_DATA = 32'h00000000; reg S_TERM_reg; reg S_READY_reg; reg M_READY_reg; reg INTR_N_reg; always @(posedge CLK or posedge RST) begin : dont_optimize_please if (RST) begin INTR_N_reg <= 1'b0; S_TERM_reg <= 1'b1; S_READY_reg <= 1'b0; M_READY_reg <= 1'b0; end else begin INTR_N_reg <= 1'b1; S_TERM_reg <= 1'b0; S_READY_reg <= 1'b1; M_READY_reg <= 1'b1; end end assign #TDLY INTR_N = INTR_N_reg; assign #TDLY S_TERM = S_TERM_reg; assign #TDLY S_READY = S_READY_reg; assign #TDLY S_ABORT = S_CYCLE64 & ADDR[2]; assign #TDLY M_READY = M_READY_reg; assign #TDLY SLOT64 = !my_cfg_reg[0];endmodule
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?