File: pcie_axi_wb_conv.v

package info (click to toggle)
uhd 3.13.1.0-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 207,120 kB
  • sloc: cpp: 167,245; ansic: 86,841; vhdl: 53,420; python: 40,839; xml: 13,167; tcl: 5,688; makefile: 2,167; sh: 1,719; pascal: 230; csh: 94; asm: 20; perl: 11
file content (199 lines) | stat: -rw-r--r-- 7,223 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
//
// Copyright 2013 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//


module pcie_axi_wb_conv #(
    parameter WB_ADDRW  = 16,
    parameter WB_DATAW  = 32
)(
    input                   clk, 
    input                   rst,

    input                   wb_stb_i,
    input                   wb_we_i,
    input  [WB_ADDRW-1:0]   wb_adr_i,
    input  [WB_DATAW-1:0]   wb_dat_i,
    output                  wb_ack_o,
    output [WB_DATAW-1:0]   wb_dat_o,

    input  [63:0]           msgi_tdata,
    input                   msgi_tvalid,
    output                  msgi_tready,

    output [63:0]           msgo_tdata,
    output                  msgo_tvalid,
    input                   msgo_tready,
    
    output                  wb_monitor_active,
    output reg              wb_req_pending,
    output reg              wb_resp_pending,
    output reg              pcie_resp_pending
);

    localparam SB_ADDRW                 = 4;
    localparam SB_DATAW                 = 32;
    localparam MONITOR_TIMEOUTW         = 20;   //20bits@175MHz ~ 6ms

    localparam SR_PCIE_DATA_REG         = 4'd0;
    localparam SR_PCIE_CTRL_REG         = 4'd1;
    localparam RB_PCIE_DATA_REG         = 4'd0;
    localparam RB_PCIE_CTRL_REG         = 4'd1;
    localparam RB_PCIE_RESP_DATA_REG    = 4'd2;
    localparam RB_PCIE_STATUS_REG       = 4'd3;

    //------------------------------------------
    // Settings and readback bus
    //
    wire [SB_DATAW-1:0]     set_data, rb_data;
    wire [SB_ADDRW-1:0]     set_addr, rb_addr;
    wire                    set_stb, rb_stb;

    settings_bus #(.AWIDTH(WB_ADDRW), .DWIDTH(WB_DATAW)) settings_bus (
        .wb_clk(clk), .wb_rst(rst),
        .wb_adr_i(wb_adr_i), .wb_dat_i(wb_dat_i),
        .wb_stb_i(wb_stb_i), .wb_we_i(wb_we_i), .wb_ack_o(wb_ack_o),
        .strobe(set_stb), .addr(set_addr), .data(set_data)
    );

    settings_readback #(.AWIDTH(WB_ADDRW), .DWIDTH(WB_DATAW), .RB_ADDRW(SB_ADDRW)) settings_readback (
        .wb_clk(clk), .wb_rst(rst), 
        .wb_adr_i(wb_adr_i), .wb_stb_i(wb_stb_i), .wb_we_i(wb_we_i),
        .rb_data(rb_data), .rb_addr(rb_addr), .rb_rd_stb(rb_stb),
        .wb_dat_o(wb_dat_o)
    );
    //------------------------------------------
    
    //------------------------------------------
    // Settings/Readback Registers
    //
    wire [31:0]     axi_out_data, axi_out_ctrl;
    wire            axi_out_stb;

    setting_reg #(.my_addr(SR_PCIE_DATA_REG), .awidth(SB_ADDRW), .width(SB_DATAW)) set_pcie_out_data_reg (
        .clk(clk), .rst(rst),
        .strobe(set_stb), .addr(set_addr), .in(set_data),
        .out(axi_out_data)
    );

    setting_reg #(.my_addr(SR_PCIE_CTRL_REG), .awidth(SB_ADDRW), .width(SB_DATAW)) set_pcie_out_ctrl_reg (
        .clk(clk), .rst(rst),
        .strobe(set_stb), .addr(set_addr), .in(set_data),
        .out(axi_out_ctrl), .changed(axi_out_stb)
    );

    reg [31:0]      axi_in_data_reg, axi_in_ctrl_reg, axi_in_resp_reg;
    wire            msgo_fifo_tready;

    // Readback MUX
    assign rb_data = (
        (rb_addr == RB_PCIE_STATUS_REG)    ? {27'h0, ~msgo_fifo_tready, 1'b0, wb_resp_pending, wb_req_pending, pcie_resp_pending} : (
        (rb_addr == RB_PCIE_RESP_DATA_REG) ? axi_in_resp_reg : (
        (rb_addr == RB_PCIE_DATA_REG)      ? axi_in_data_reg : (
        (rb_addr == RB_PCIE_CTRL_REG)      ? axi_in_ctrl_reg : 32'h0))));
    //------------------------------------------

    //------------------------------------------
    // Output message handler
    //
    wire [63:0]     msgo_fifo_tdata;
    wire            axi_out_rd, axi_out_wr, axi_out_rr;

    assign msgo_fifo_tdata = {axi_out_ctrl, axi_out_data};

    axi_fifo_short #(.WIDTH(64)) wb_out_msg_fifo (
        .clk(clk), .reset(rst), .clear(1'b0),
        .i_tdata(msgo_fifo_tdata), .i_tvalid(axi_out_stb), .i_tready(msgo_fifo_tready),
        .o_tdata(msgo_tdata), .o_tvalid(msgo_tvalid), .o_tready(msgo_tready),
        .space(), .occupied());

    ioport2_msg_decode axi_out_decoder (
        .message(msgo_fifo_tdata),
        .rd_response(axi_out_rr), .wr_request(axi_out_wr), .rd_request(axi_out_rd)
    );
    //------------------------------------------
    
    //------------------------------------------
    // Input message handler
    //
    wire [63:0]     msgi_fifo_tdata;
    wire            axi_in_valid, axi_in_stb;

    wire [31:0]     axi_in_data, axi_in_ctrl;
    wire            axi_in_rd, axi_in_wr, axi_in_rr;
    
    axi_fifo_short #(.WIDTH(64)) wb_in_msg_fifo (
        .clk(clk), .reset(rst), .clear(1'b0),
        .i_tdata(msgi_tdata), .i_tvalid(msgi_tvalid), .i_tready(msgi_tready),
        .o_tdata(msgi_fifo_tdata), .o_tvalid(axi_in_valid), .o_tready(axi_in_stb),
        .space(), .occupied());

    ioport2_msg_decode axi_in_decoder (
        .message(msgi_fifo_tdata),
        .rd_response(axi_in_rr), .wr_request(axi_in_wr), .rd_request(axi_in_rd),
        .data(axi_in_data), .control(axi_in_ctrl)
    );

    assign axi_in_stb = axi_in_valid & (axi_in_rr | ((axi_in_wr | axi_in_rd) &  ~(wb_req_pending | wb_resp_pending)));

    always @(posedge clk) begin
        if (rst) begin
            axi_in_data_reg     <= 32'h0;
            axi_in_ctrl_reg     <= 32'h0;
            axi_in_resp_reg     <= 32'h0;
        end else begin
            if (axi_in_stb & axi_in_rr) begin
                axi_in_resp_reg <= axi_in_data;
            end else if (axi_in_stb & (axi_in_wr | axi_in_rd)) begin
                axi_in_data_reg <= axi_in_data;
                axi_in_ctrl_reg <= axi_in_ctrl;
            end
        end
    end
    //------------------------------------------
    
    //------------------------------------------
    // State handler
    //
    //wb_monitor_active
    reg [MONITOR_TIMEOUTW-1:0]  wb_monitor_timeout;
    assign wb_monitor_active = (wb_monitor_timeout != {(MONITOR_TIMEOUTW){1'b0}});
    always @(posedge clk) begin
        if (rst) 
            wb_monitor_timeout  <= {(MONITOR_TIMEOUTW){1'b0}}; //Monitor disabled on rst
        else if (rb_stb && (rb_addr == RB_PCIE_STATUS_REG)) 
            wb_monitor_timeout  <= {(MONITOR_TIMEOUTW){1'b1}}; //Reset counter when the ZPU queries the status reg
        else if (wb_monitor_active)
            wb_monitor_timeout  <= wb_monitor_timeout - 1;  //Decrement counter when idle
    end

    //wb_req_pending
    always @(posedge clk) begin
        if (rst || (rb_stb && (rb_addr == RB_PCIE_CTRL_REG)))
            wb_req_pending  <= 1'b0;
        else if (axi_in_stb & (axi_in_rd | axi_in_wr)) 
            wb_req_pending  <= 1'b1;
    end
    
    //wb_resp_pending
    always @(posedge clk) begin
        if (rst | (axi_out_stb & msgo_fifo_tready & axi_out_rr))
            wb_resp_pending  <= 1'b0;
        else if (axi_in_stb & axi_in_rd) 
            wb_resp_pending  <= 1'b1;
    end

    //pcie_resp_pending
    always @(posedge clk) begin
        if (rst | (axi_in_stb & axi_in_rr))
            pcie_resp_pending  <= 1'b0;
        else if (axi_out_stb & msgo_fifo_tready & axi_out_rd) 
            pcie_resp_pending  <= 1'b1;
    end
    //------------------------------------------


endmodule