v6 bmd 接收注释

//--------------------------------------------------------------------------------
//--
//-- This file is owned and controlled by Xilinx and must be used solely
//-- for design, simulation, implementation and creation of design files
//-- limited to Xilinx devices or technologies. Use with non-Xilinx
//-- devices or technologies is expressly prohibited and immediately
//-- terminates your license.
//--
//-- Xilinx products are not intended for use in life support
//-- appliances, devices, or systems. Use in such applications is
//-- expressly prohibited.
//--
//--            **************************************
//--            ** Copyright (C) 2005, Xilinx, Inc. **
//--            ** All Rights Reserved.             **
//--            **************************************
//--
//--------------------------------------------------------------------------------
//-- Filename: BMD_64_RX_ENGINE.v
//--
//-- Description: 64 bit Local-Link Receive Unit.
//--
//--------------------------------------------------------------------------------

`timescale 1ns/1ns

`define BMD_64_RX_RST            8'b00000001
`define BMD_64_RX_MEM_RD32_QW1   8'b00000010
`define BMD_64_RX_MEM_RD32_WT    8'b00000100
`define BMD_64_RX_MEM_WR32_QW1   8'b00001000
`define BMD_64_RX_MEM_WR32_WT    8'b00010000
`define BMD_64_RX_CPL_QW1        8'b00100000
`define BMD_64_RX_CPLD_QW1       8'b01000000
`define BMD_64_RX_CPLD_QWN       8'b10000000

`define BMD_MEM_RD32_FMT_TYPE    7'b00_00000
`define BMD_MEM_WR32_FMT_TYPE    7'b10_00000
`define BMD_CPL_FMT_TYPE         7'b00_01010
`define BMD_CPLD_FMT_TYPE        7'b10_01010

module BMD_RX_ENGINE (
    clk,
    rst_n,
    //Initiator reset
    init_rst_i,
              
    //Receive local link interface from PCIe core                
    trn_rd,  
    trn_rrem_n,
    trn_rsof_n,
    trn_reof_n,
    trn_rsrc_rdy_n,
    trn_rsrc_dsc_n,
    trn_rdst_rdy_n,
    trn_rbar_hit_n,
                               
    /*
     * Memory Read data handshake with Completion 
     * transmit unit. Transmit unit reponds to 
     * req_compl assertion and responds with compl_done
     * assertion when a Completion w/ data is transmitted. 
     */
    req_compl_o,
    compl_done_i,
                         
    addr_o,                    // Memory Read Address
    req_tc_o,                  // Memory Read TC
    req_td_o,                  // Memory Read TD
    req_ep_o,                  // Memory Read EP
    req_attr_o,                // Memory Read Attribute
    req_len_o,                 // Memory Read Length (1DW)
    req_rid_o,                 // Memory Read Requestor ID
    req_tag_o,                 // Memory Read Tag
    req_be_o,                  // Memory Read Byte Enables
                                 
    /* 
     * Memory interface used to save 1 DW data received 
     * on Memory Write 32 TLP. Data extracted from
     * inbound TLP is presented to the Endpoint memory
     * unit. Endpoint memory unit reacts to wr_en_o
     * assertion and asserts wr_busy_i when it is 
     * processing written information.
     */
                           
    wr_be_o,                   // Memory Write Byte Enable
    wr_data_o,                 // Memory Write Data
    wr_en_o,                   // Memory Write Enable
    wr_busy_i,                 // Memory Write Busy
       
    /*
     * Completion no Data
     */
    cpl_ur_found_o,
    cpl_ur_tag_o,
                            
    /*
     * Completion with Data
     */                   
    cpld_data_i,
    cpld_found_o,
    cpld_data_size_o,
    cpld_malformed_o,
    cpld_data_err_o                     
);


//1,BMD_RX_ENGINE的设计:这个模块的作用就是接受来自PC的TLP包(trn_rd[63:0]),
//并根据不同的情况对包进行拆解,首先根据trn_rd[62:56]位判断包的类型,
//如果是32位地址读请求(BMD_MEM_RD32_FMT_TYPE),
//那么就转到32位读对应的状态(BMD_64_RX_MEM_RD32_QW1)
//如果是32位地址写请求(BMD_MEM_WR32_FMT_TYPE)
//那么久转到32位写对应的状态(BMD_64_RX_MEM_WR32_QW1)
//如果是不带数据的完成类型(BMD_CPL_FMT_TYPE)
//那么就转到完成请求对应的状态(BMD_64_RX_CPL_QW1)
//如果是带数据的完成类型(BMD_CPLD_FMT_TYPE)
//那么就转到带数据完成对应的状态(BMD_64_RX_CPLD_QW1)
//原文:https://blog.csdn.net/buyi_shizi/article/details/51244966 
//版权声明:本文为博主原创文章,转载请附上博文链接!


//上面是状态机的第一次过渡
//下面看状态的第二次过渡
//在状态是BMD_MEM_RD32_FMT_QW1时
//这个时候TLP包的第二个DWORD已经传来
//从第二个DWORD中可以得到读请求的地址addr_o
//这个地址是输入到memory模块下用于读出对应地址下的数据的
//然后过渡到下一个状态(BMD_64_RX_MEM_32_WT)
//在这个状态下,RX模块会一直检测从TX返回的compl_done_i信号
//当读请求申请的对应地址下的数据由TX发送出去时
//compl_done_i信号就为1
//这个时候RX就会返回到RST状态.

//当状态是BMD_MEM_WR32_FMT_QW1时
//这个时候RX也接受到了TLP包的第二个DWORD
//从这个DWORD中可以拆分出地址(addr_o)和要写的数据(wr_data_o)
//同时在这个状态写使能值为有效(we_en_o)
//然后过渡到下一个状态(BMD_64_RX_MEM_WR32_WT)
//在这一个状态,RX会一直检测从memory模块出来的信号(wr_busy_i)是不是为0
//如果为0,说明写操作完成
//RX回到RST状态.


//当状态是BMD_64_RX_CPL_QW1的时候,
//说明这是一个不带数据的完成
//其他并没有什么操作
//当状态是BMD_64_RX_CPLD_QW1时
//说明这是一个带数据的完成
//为什么完成信号要携带数据呢
//原因就是为了检验传输的数据是否正确
//在这个状态下以及它的过渡状态中
//RX会一次检测传输到PC端的数据和设备内存的数据是否相同
//如果不相同,说明数据传输失败,
//返回失败传输信号(cpld_malformed)

//从上面的描述可以看出,BMD中的RX是不支持连续的写数据的(往设备内存写数据)
//所以往设备内存写数据的DMA操作,xapp1052是不支持的,
//那么这里发送和接收的数据到底是什么呢
//其实这里RX并不是要发送和接收存储数据
//而是发送和接收配置数据,即DMA的配置数据


    input              clk;
    input              rst_n;
    input              init_rst_i;
    input [63:0]       trn_rd;
    input [7:0]        trn_rrem_n;
    input              trn_rsof_n;
    input              trn_reof_n;
    input              trn_rsrc_rdy_n;
    input              trn_rsrc_dsc_n;
    output             trn_rdst_rdy_n;
    input [6:0]        trn_rbar_hit_n;
 
    output             req_compl_o;
    input              compl_done_i;

    output [10:0]      addr_o;

    output [2:0]       req_tc_o;
    output             req_td_o;
    output             req_ep_o;
    output [1:0]       req_attr_o;
    output [9:0]       req_len_o;
    output [15:0]      req_rid_o;
    output [7:0]       req_tag_o;
    output [7:0]       req_be_o;

    output [7:0]       wr_be_o;
    output [31:0]      wr_data_o;
    output             wr_en_o;
    input              wr_busy_i;

    output [7:0]       cpl_ur_found_o;
    output [7:0]       cpl_ur_tag_o;

    input  [31:0]      cpld_data_i;
    output [31:0]      cpld_found_o;
    output [31:0]      cpld_data_size_o;
    output             cpld_malformed_o;
    output             cpld_data_err_o;

    // Local wire

    wire   [31:0]      cpld_data_i_sw = {cpld_data_i[07:00],
                                         cpld_data_i[15:08],
                                         cpld_data_i[23:16],
                                         cpld_data_i[31:24]};

    // Local Registers

    reg [7:0]          bmd_64_rx_state;

    reg                trn_rdst_rdy_n;

    reg                req_compl_o;

    reg [2:0]          req_tc_o;
    reg                req_td_o;
    reg                req_ep_o;
    reg [1:0]          req_attr_o;
    reg [9:0]          req_len_o;
    reg [15:0]         req_rid_o;
    reg [7:0]          req_tag_o;
    reg [7:0]          req_be_o;

    reg [10:0]         addr_o;
    reg [7:0]          wr_be_o;
    reg [31:0]         wr_data_o;
    reg                wr_en_o;

    reg [7:0]          cpl_ur_found_o;
    reg [7:0]          cpl_ur_tag_o;

    reg [31:0]         cpld_found_o;
    reg [31:0]         cpld_data_size_o;
    reg                cpld_malformed_o;
    reg                cpld_data_err_o;

    //reg [9:0]          cpld_real_size;
    //reg [9:0]          cpld_tlp_size;
    reg [6:0]          cpld_real_size;
    reg [6:0]          cpld_tlp_size;

    reg [7:0]          bmd_64_rx_state_q;
    reg [63:0]         trn_rd_q;
    reg [7:0]          trn_rrem_n_q;
    reg                trn_reof_n_q;
    reg                trn_rsrc_rdy_n_q;

always @( posedge clk ) begin      
    if( !rst_n ) begin
        bmd_64_rx_state   <= `BMD_64_RX_RST;
        trn_rdst_rdy_n <= 1'b0;
        req_compl_o    <= 1'b0;
        req_tc_o       <= 2'b0;
        req_td_o       <= 1'b0;
        req_ep_o       <= 1'b0;
        req_attr_o     <= 2'b0;
        req_len_o      <= 10'b0;
        req_rid_o      <= 16'b0;
        req_tag_o      <= 8'b0;
        req_be_o       <= 8'b0;
        addr_o         <= 31'b0;
               
        wr_be_o        <= 8'b0;
        wr_data_o      <= 31'b0;
        wr_en_o        <= 1'b0;
            
        cpl_ur_found_o   <= 8'b0;
        cpl_ur_tag_o     <= 8'b0;
              
        cpld_found_o     <= 32'b0;
        cpld_data_size_o <= 32'b0;
        cpld_malformed_o <= 1'b0;
                  
        cpld_real_size   <= 7'b0;
        cpld_tlp_size    <= 7'b0;  
               
        bmd_64_rx_state_q <= `BMD_64_RX_RST;
        trn_rd_q          <= 64'b0;
        trn_rrem_n_q      <= 8'b0;
        trn_reof_n_q      <= 1'b1;
        trn_rsrc_rdy_n_q  <= 1'b1;
    end else begin
        wr_en_o        <= 1'b0;
        req_compl_o    <= 1'b0;
        trn_rdst_rdy_n <= 1'b0;
                    
        if( init_rst_i ) begin
            bmd_64_rx_state  <= `BMD_64_RX_RST;
            cpl_ur_found_o   <= 8'b0;
            cpl_ur_tag_o     <= 8'b0;
                  
            cpld_found_o     <= 32'b0;
            cpld_data_size_o <= 32'b0;
            cpld_malformed_o <= 1'b0;
                      
            cpld_real_size   <= 7'b0;
            cpld_tlp_size    <= 7'b0;
                       
            bmd_64_rx_state_q <= `BMD_64_RX_RST;
            trn_rd_q          <= 64'b0;
            trn_rrem_n_q      <= 8'b0;
            trn_reof_n_q      <= 1'b1;
            trn_rsrc_rdy_n_q  <= 1'b1;
        end
             
        bmd_64_rx_state_q <= `BMD_64_RX_RST;
        trn_rd_q          <= 64'b0;
        trn_rrem_n_q      <= 8'b0;
        trn_reof_n_q      <= 1'b1;
        trn_rsrc_rdy_n_q  <= 1'b1;
               
        case( bmd_64_rx_state )
          `BMD_64_RX_RST: begin
          if( (!trn_rsof_n) && 
              //接收引擎接收tlp包开始信号  i
              (!trn_rsrc_rdy_n) && 
              //源端准备好信号  i
              (!trn_rdst_rdy_n) ) begin
              //目的端准备好信号  o
              case (trn_rd[62:56]) 
                `BMD_MEM_RD32_FMT_TYPE: begin
                //读32位模式
                if( trn_rd[41:32] == 10'b1 ) begin
                    req_tc_o     <= trn_rd[54:52];  
                    req_td_o     <= trn_rd[47];
                    req_ep_o     <= trn_rd[46]; 
                    req_attr_o   <= trn_rd[45:44]; 
                    req_len_o    <= trn_rd[41:32]; 
                    req_rid_o    <= trn_rd[31:16]; 
                    req_tag_o    <= trn_rd[15:08]; 
                    req_be_o     <= trn_rd[07:00];     
                    bmd_64_rx_state <= `BMD_64_RX_MEM_RD32_QW1;
                end else begin
                    bmd_64_rx_state <= `BMD_64_RX_RST;
                end
                end
                     
                `BMD_MEM_WR32_FMT_TYPE : begin
                //40000001 0000000f
                //写32位模式
                if( trn_rd[41:32] == 10'b1 ) begin
                    wr_be_o      <= trn_rd[07:00];
                    bmd_64_rx_state <= `BMD_64_RX_MEM_WR32_QW1;
                end else begin
                    bmd_64_rx_state <= `BMD_64_RX_RST;
                end
                end
                    
                `BMD_CPL_FMT_TYPE : begin
                if( trn_rd[15:12] != 3'b000 ) begin
                    cpl_ur_found_o <= cpl_ur_found_o + 1'b1;
                    bmd_64_rx_state   <= `BMD_64_RX_CPL_QW1;
                end else begin
                    bmd_64_rx_state   <= `BMD_64_RX_RST;
                end
                end
                    
                `BMD_CPLD_FMT_TYPE: begin
                //带数据的完成类型
                cpld_data_size_o <= cpld_data_size_o + trn_rd[41:32];
                cpld_tlp_size    <= trn_rd[38:32];
                cpld_found_o     <= cpld_found_o  + 1'b1;
                cpld_real_size   <= 7'b0;
                bmd_64_rx_state  <= `BMD_64_RX_CPLD_QW1;
                end
                    
                default: begin
                bmd_64_rx_state   <= `BMD_64_RX_RST;
                end
              endcase
          end else begin
              bmd_64_rx_state   <= `BMD_64_RX_RST;
          end
          end
              
          `BMD_64_RX_MEM_RD32_QW1: begin
          //进入读32bit模式的查询与等待状态
          if( (!trn_reof_n) && 
              (!trn_rsrc_rdy_n) && 
              (!trn_rdst_rdy_n) ) begin
              addr_o            <= trn_rd[63:34];
              //取读地址 4字节对齐
              req_compl_o       <= 1'b1;
              //请求完成信号置1
              trn_rdst_rdy_n    <= 1'b1;
              bmd_64_rx_state   <= `BMD_64_RX_MEM_RD32_WT;
          end else begin
              bmd_64_rx_state   <= `BMD_64_RX_MEM_RD32_QW1;
          end
          end
               
          `BMD_64_RX_MEM_RD32_WT: begin
          //读32位数据模式等待态
          trn_rdst_rdy_n <= 1'b1;
          if( compl_done_i ) begin
              //等待完成信号置1
              bmd_64_rx_state   <= `BMD_64_RX_RST;
          end else begin
              req_compl_o       <= 1'b1;
              trn_rdst_rdy_n    <= 1'b1;
              bmd_64_rx_state   <= `BMD_64_RX_MEM_RD32_WT;
          end
          end
                 
          `BMD_64_RX_MEM_WR32_QW1: begin
          if( (!trn_reof_n) && 
              (!trn_rsrc_rdy_n) && 
              (!trn_rdst_rdy_n) ) begin
              addr_o           <= trn_rd[44:34];
              //从tlp包中提取地址 bit32-31忽略,4字节对齐
              wr_data_o        <= trn_rd[31:00];
              //从tlp包中提取32bit数据
              wr_en_o          <= 1'b1;
              trn_rdst_rdy_n   <= 1'b1;
              bmd_64_rx_state  <= `BMD_64_RX_MEM_WR32_WT;
          end else begin
              bmd_64_rx_state  <= `BMD_64_RX_MEM_WR32_QW1;
          end
          end
              
          `BMD_64_RX_MEM_WR32_WT: begin
          trn_rdst_rdy_n <= 1'b1;
          //等待写忙状态位
          if( !wr_busy_i ) begin
              //闲,进入接收复位态
              bmd_64_rx_state  <= `BMD_64_RX_RST;
          end else begin
              //忙,维持在本状态
              bmd_64_rx_state  <= `BMD_64_RX_MEM_WR32_WT;
          end
          end
                  
          `BMD_64_RX_CPL_QW1: begin
          if( (!trn_reof_n) && 
              (!trn_rsrc_rdy_n) && 
              (!trn_rdst_rdy_n) ) begin
              cpl_ur_tag_o     <= trn_rd[47:40];
              bmd_64_rx_state  <= `BMD_64_RX_RST;
          end else begin
              bmd_64_rx_state  <= `BMD_64_RX_CPL_QW1;
          end
          end
               
          `BMD_64_RX_CPLD_QW1: begin
          bmd_64_rx_state_q <= bmd_64_rx_state;
          trn_rd_q          <= trn_rd;
          trn_rrem_n_q      <= trn_rrem_n;
          trn_reof_n_q      <= trn_reof_n;
          trn_rsrc_rdy_n_q  <= trn_rsrc_rdy_n;
          if( (!trn_reof_n) && 
              (!trn_rsrc_rdy_n) && 
              (!trn_rdst_rdy_n) ) begin
              cpld_real_size  <= cpld_real_size  + 1'b1;
              if( cpld_tlp_size != 1'b1 ) begin
                  cpld_malformed_o <= 1'b1;
              end
              if( trn_rrem_n != 8'h00 ) begin
                  cpld_malformed_o <= 1'b1;
              end
              bmd_64_rx_state  <= `BMD_64_RX_RST;
          end else if( (!trn_rsrc_rdy_n) && 
                       (!trn_rdst_rdy_n) ) begin
              cpld_real_size <= cpld_real_size + 1'b1;
              bmd_64_rx_state  <= `BMD_64_RX_CPLD_QWN;
          end else begin
              bmd_64_rx_state <= `BMD_64_RX_CPLD_QW1;
          end
          end
                
          `BMD_64_RX_CPLD_QWN: begin
          bmd_64_rx_state_q <= bmd_64_rx_state;
          trn_rd_q          <= trn_rd;
          trn_rrem_n_q      <= trn_rrem_n;
          trn_reof_n_q      <= trn_reof_n;
          trn_rsrc_rdy_n_q  <= trn_rsrc_rdy_n;
          if( (!trn_reof_n) && 
              (!trn_rsrc_rdy_n) && 
              (!trn_rdst_rdy_n) ) begin
              if( trn_rrem_n == 8'h0F ) begin
                  cpld_real_size <= cpld_real_size + 1'h1;
                  if( cpld_tlp_size != cpld_real_size + 1'h1 ) begin
                      cpld_malformed_o <= 1'b1;
                  end
              end else begin
                  cpld_real_size <= cpld_real_size + 2'h2;            
                  if( cpld_tlp_size != cpld_real_size + 2'h2 ) begin         
                      cpld_malformed_o <= 1'b1;
                  end
              end 
              bmd_64_rx_state  <= `BMD_64_RX_RST;
          end else if( (!trn_rsrc_rdy_n) && 
                       (!trn_rdst_rdy_n) ) begin
              cpld_real_size  <= cpld_real_size + 2'h2;
              bmd_64_rx_state <= `BMD_64_RX_CPLD_QWN;
          end else begin
              bmd_64_rx_state   <= `BMD_64_RX_CPLD_QWN;
          end
          end
        endcase
    end   
end    


    

always @( posedge clk ) begin      
    if( !rst_n ) begin
        cpld_data_err_o <= 1'b0;
    end else begin
        if( init_rst_i ) begin
            cpld_data_err_o <= 1'b0;
        end else begin
            case( bmd_64_rx_state_q )
              `BMD_64_RX_CPLD_QW1: begin
              if( cpld_data_err_o == 1'b0 ) begin
                  if( trn_rd_q[31:00] != cpld_data_i_sw ) begin
                      //pc端发送下来的数据与我们设置的读寄存器的值比较
                      cpld_data_err_o <= 1'b1;
                  end
              end
              end
                  
              `BMD_64_RX_CPLD_QWN: begin
              if( !trn_reof_n_q ) begin
                  if( trn_rrem_n_q == 8'h0F ) begin
                      if( cpld_data_err_o == 1'b0 ) begin
                          if( trn_rd_q[63:32] != cpld_data_i_sw ) begin
                              cpld_data_err_o <= 1'b1;
                          end
                      end
                  end else if( trn_rrem_n_q == 8'h00 ) begin
                      if( cpld_data_err_o == 1'b0 ) begin
                          if( trn_rd_q != {cpld_data_i_sw, cpld_data_i_sw} ) begin
                              cpld_data_err_o <= 1'b1;
                          end
                      end
                  end else begin
                      //Invalid remainder
                      cpld_data_err_o <= 1'b1;
                  end
              end else begin
                  if( cpld_data_err_o == 1'b0 ) begin
                      if( trn_rd_q != {cpld_data_i_sw, cpld_data_i_sw} ) begin
                          cpld_data_err_o <= 1'b1;
                      end
                  end
              end
              end
            endcase
        end
    end
end

     
/*
///////////////////////////////////////////////////////////////////////
//chipscope xilinx

wire [35:0]   CONTROL0;
wire [255:0]  TRIG0;

my_debug_ctrl icon_debug (
    .CONTROL0(CONTROL0) 
);

my_debug ila_filter_debug (
    .CONTROL(CONTROL0), 
    .CLK(clk),     
    .TRIG0(TRIG0)     
     
);     

  
 

assign TRIG0[0]      = trn_rsof_n;
assign TRIG0[1]      = trn_reof_n;
assign TRIG0[2]      = trn_rsrc_rdy_n;
assign TRIG0[3]      = trn_rdst_rdy_n;
assign TRIG0[4]     = wr_en_o;
assign TRIG0[5]     = wr_busy_i;
assign TRIG0[6]     = req_compl_o;
assign TRIG0[7]     = compl_done_i;

assign TRIG0[39:8]   = wr_data_o[31:0];
assign TRIG0[50:40]  = addr_o[10:0];
assign TRIG0[58:51]  = wr_be_o[7:0];
assign TRIG0[122:59]     = trn_rd[63:0];
assign TRIG0[154:123]     = cpld_data_i[31:0];

*/


              
endmodule // BMD_64_RX_ENGINE
 

你可能感兴趣的:(v6 bmd 接收注释)