summaryrefslogtreecommitdiff
path: root/rtl/cpu/cpu_imc.sv
blob: 2dfca60e760c874e0c5588d07c8ef44317c464df (plain)
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
//
// Copyright (c) 2026, Apollo Telephone Laboratories.
// Provided under the BSD-3 clause.
//

`include "bus/ari.svh"

//
// The integrated memory controller (IMC) is responsible for making
// bus transactions using the address operation tag.
//
module cpu_imc (
    input wire clk_i,
    input wire reset_i,
    input wire write_en_i,
    input wire req_i,
    input wire [PMA_XLEN-1:0] ad_i,
    input wire [63:0] data_i,

    output AriFrame mb_r_tap_o,
    output logic op_done_o
);
    parameter FSM_STAGE_REQUEST = 0;
    parameter FSM_STAGE_TX_REQ  = 1;
    parameter FSM_STAGE_WAIT0   = 2;
    parameter FSM_STAGE_WAIT1   = 3;
    parameter FSM_STAGE_WAIT2   = 4;
    parameter FSM_STAGE_WAIT3   = 5;
    parameter FSM_STAGE_DONE    = 6;

    logic [3:0] fsm_stage;
    logic [3:0] seq;
    AriAdop adop;
    AriFrame frame;

    always_ff @(posedge clk_i) begin
        if (reset_i) begin
            frame        <= 0;
            fsm_stage    <= 0;
            mb_r_tap_o   <= 0;
            op_done_o    <= 0;
            seq          <= 0;
        end else if (req_i || fsm_stage > FSM_STAGE_REQUEST) begin
            case (fsm_stage)
                FSM_STAGE_REQUEST: begin
                    frame.tag       <= ARI_ADOP;
                    frame.seq       <= seq;
                    frame.payload   <= adop;
                    fsm_stage       <= FSM_STAGE_TX_REQ;
                end
                FSM_STAGE_TX_REQ: begin
                    mb_r_tap_o <= frame;
                    fsm_stage  <= FSM_STAGE_WAIT0;
                end

                // Four cycle wait period as per the spec
                FSM_STAGE_WAIT0: fsm_stage <= FSM_STAGE_WAIT1;
                FSM_STAGE_WAIT1: fsm_stage <= FSM_STAGE_WAIT2;
                FSM_STAGE_WAIT2: fsm_stage <= FSM_STAGE_WAIT3;
                FSM_STAGE_WAIT3: fsm_stage <= FSM_STAGE_DONE;

                FSM_STAGE_DONE: begin
                    mb_r_tap_o  <= 0;
                    op_done_o   <= 1;
                    if (!req_i) begin
                        fsm_stage   <= FSM_STAGE_REQUEST;
                        op_done_o   <= 0;
                    end
                end
            endcase
        end
    end

    // Continous assignments
    assign adop.ad       = ad_i;
    assign adop.data     = write_en_i ? data_i : 0;
    assign adop.write_en = write_en_i;
    assign adop.reserved = 0;
endmodule