1//
2// Copyright 2013 Ettus Research LLC
3// Copyright 2018 Ettus Research, a National Instruments Company
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6//
7
8
9module pcie_basic_regs #(
10    parameter SIGNATURE = 32'h0,
11    parameter CLK_FREQ  = 32'h0
12) (
13    input           clk,
14    input           reset,
15
16    input [63:0]    regi_tdata,
17    input           regi_tvalid,
18    output          regi_tready,
19    output [63:0]   rego_tdata,
20    output          rego_tvalid,
21    input           rego_tready,
22
23    input [31:0]    misc_status
24);
25    localparam PCIE_FPGA_SIG_VAL                = SIGNATURE;
26    localparam PCIE_FPGA_COUNTER_FREQ           = CLK_FREQ;
27
28    localparam PCIE_REG_ADDR_MASK               = 20'h001FF;
29
30    localparam PCIE_FPGA_SIG_REG_ADDR           = 20'h00000;    //32-bit
31    localparam PCIE_FPGA_COUNTER_LO_REG_ADDR    = 20'h00004;    //32-bit
32    localparam PCIE_FPGA_COUNTER_HI_REG_ADDR    = 20'h00008;    //32-bit
33    localparam PCIE_FPGA_COUNTER_FREQ_ADDR      = 20'h0000C;    //32-bit
34    localparam PCIE_FPGA_SCRATCH0_ADDR          = 20'h00010;    //32-bit
35    localparam PCIE_FPGA_SCRATCH1_ADDR          = 20'h00014;    //32-bit
36    localparam PCIE_FPGA_MISC_STATUS_ADDR       = 20'h00020;    //32-bit
37    localparam PCIE_FPGA_USR_SIG_REG_ADDR       = 20'h00030;    //128-bit
38
39    wire            regi_wr, regi_rd;
40    wire [19:0]     regi_addr, regi_addr_local;
41    wire [31:0]     regi_payload;
42    reg  [31:0]     rego_payload;
43
44    ioport2_msg_decode regi_decoder (
45        .message(regi_tdata), .wr_request(regi_wr), .rd_request(regi_rd),
46        .address(regi_addr), .data(regi_payload)
47    );
48
49    ioport2_msg_encode  rego_encoder (
50        .rd_response(1'b1), .data(rego_payload), .message(rego_tdata)
51    );
52
53    assign regi_tready = (regi_tvalid & regi_wr) | rego_tready;
54    assign rego_tvalid = regi_tvalid & regi_rd;
55    assign regi_addr_local = regi_addr & PCIE_REG_ADDR_MASK;
56
57    //Counter counting bus_clk cycles
58    reg [63:0]  bus_counter;
59    always @(posedge clk) begin
60        if (reset)  bus_counter <= 64'h0;
61        else        bus_counter <= bus_counter + 1;
62    end
63
64    //Scratch registers
65    reg [63:0]  scratch;
66    always @(posedge clk) begin
67        if (reset)
68            scratch <= 64'h0;
69        else if (regi_tvalid & regi_tready & regi_wr)
70            if (regi_addr_local == PCIE_FPGA_SCRATCH0_ADDR)
71                scratch[31:0]  <= regi_payload;
72            else if (regi_addr_local == PCIE_FPGA_SCRATCH1_ADDR)
73                scratch[63:32] <= regi_payload;
74    end
75
76    //User signature register
77    reg [127:0]  usr_signature;
78    always @(posedge clk) begin
79        if (reset)
80            usr_signature <= 128'h0;
81        else if (regi_tvalid & regi_tready & regi_wr)
82            if (regi_addr_local == (PCIE_FPGA_USR_SIG_REG_ADDR + 20'h00000))
83                usr_signature[31:0]  <= regi_payload;
84            else if (regi_addr_local == (PCIE_FPGA_USR_SIG_REG_ADDR + 20'h00004))
85                usr_signature[63:32]  <= regi_payload;
86            else if (regi_addr_local == (PCIE_FPGA_USR_SIG_REG_ADDR + 20'h00008))
87                usr_signature[95:64]  <= regi_payload;
88            else if (regi_addr_local == (PCIE_FPGA_USR_SIG_REG_ADDR + 20'h0000C))
89                usr_signature[127:96]  <= regi_payload;
90    end
91
92    always @(*) begin
93        case (regi_addr_local)
94            PCIE_FPGA_SIG_REG_ADDR:                 rego_payload = PCIE_FPGA_SIG_VAL;
95            PCIE_FPGA_COUNTER_LO_REG_ADDR:          rego_payload = bus_counter[31:0];
96            PCIE_FPGA_COUNTER_HI_REG_ADDR:          rego_payload = bus_counter[63:32];
97            PCIE_FPGA_COUNTER_FREQ_ADDR:            rego_payload = PCIE_FPGA_COUNTER_FREQ;
98            PCIE_FPGA_SCRATCH0_ADDR:                rego_payload = scratch[31:0];
99            PCIE_FPGA_SCRATCH1_ADDR:                rego_payload = scratch[63:32];
100            PCIE_FPGA_MISC_STATUS_ADDR:             rego_payload = misc_status;
101            PCIE_FPGA_USR_SIG_REG_ADDR + 20'h00000: rego_payload = usr_signature[31:0];
102            PCIE_FPGA_USR_SIG_REG_ADDR + 20'h00004: rego_payload = usr_signature[63:32];
103            PCIE_FPGA_USR_SIG_REG_ADDR + 20'h00008: rego_payload = usr_signature[95:64];
104            PCIE_FPGA_USR_SIG_REG_ADDR + 20'h0000C: rego_payload = usr_signature[127:96];
105            default:                                rego_payload = 32'hFFFFFFFF;
106        endcase
107    end
108
109endmodule
110