File size: 3,233 Bytes
a8baeed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
// Behavioral Memory Model for Simulation
// Provides a simple synchronous memory with configurable read latency

module behavioral_memory #(
  parameter int ADDR_WIDTH = 64,
  parameter int WORD_WIDTH = 64,
  parameter int WORD_BYTES = WORD_WIDTH / 8,
  parameter int READ_LATENCY = 2,
  parameter string INIT_FILE = ""
) (
  input  logic                         clk,
  input  logic                         reset,

  // Memory Request Interface
  input  logic                         req_valid,
  output logic                         req_ready,
  input  logic [ADDR_WIDTH-1:0]        addr,
  input  logic                         is_read,
  input  logic                         is_write,
  input  logic [WORD_BYTES-1:0]        wstrb,
  input  logic [WORD_WIDTH-1:0]        wdata,

  // Memory Response Interface
  output logic                         rvalid,
  output logic [WORD_WIDTH-1:0]        rdata,
  output logic                         fault
);

  // Memory array: 64K words (512KB total)
  logic [WORD_WIDTH-1:0] memory [0:65535];

  // Read pipeline for latency emulation
  logic [READ_LATENCY-1:0] read_valid_pipe;
  logic [WORD_WIDTH-1:0] read_data_pipe [0:READ_LATENCY-1];
  logic [ADDR_WIDTH-1:0] read_addr_pipe [0:READ_LATENCY-1];

  initial begin
    if (INIT_FILE != "") begin
      $readmemh(INIT_FILE, memory);
    end else begin
      for (int i = 0; i < 65536; i++) begin
        memory[i] = 64'h0;
      end
    end
  end

  // Request handling
  always_ff @(posedge clk or negedge reset) begin
    if (!reset) begin
      req_ready <= 1'b1;
      rvalid <= 1'b0;
      rdata <= 64'h0;
      fault <= 1'b0;
      for (int i = 0; i < READ_LATENCY; i++) begin
        read_valid_pipe[i] <= 1'b0;
        read_data_pipe[i] <= 64'h0;
      end
    end else begin
      // Always ready to accept requests
      req_ready <= 1'b1;

      // Handle write operations immediately
      if (req_valid && is_write) begin
        // Word-aligned write at address / 8
        logic [ADDR_WIDTH-1:0] word_addr = addr >> 3;
        if (word_addr < 65536) begin
          // Apply write strobes (byte enables)
          for (int i = 0; i < WORD_BYTES; i++) begin
            if (wstrb[i]) begin
              memory[word_addr][i*8 +: 8] <= wdata[i*8 +: 8];
            end
          end
        end
      end

      // Handle read operations (pipeline)
      read_valid_pipe[0] <= req_valid && is_read;
      if (req_valid && is_read) begin
        logic [ADDR_WIDTH-1:0] word_addr = addr >> 3;
        read_addr_pipe[0] <= word_addr;
        if (word_addr < 65536) begin
          read_data_pipe[0] <= memory[word_addr];
        end else begin
          read_data_pipe[0] <= 64'hDEADBEEFDEADBEEF;  // Fault marker
        end
      end

      // Pipeline shift for READ_LATENCY cycles
      for (int i = 1; i < READ_LATENCY; i++) begin
        read_valid_pipe[i] <= read_valid_pipe[i-1];
        read_data_pipe[i] <= read_data_pipe[i-1];
        read_addr_pipe[i] <= read_addr_pipe[i-1];
      end

      // Output from pipeline
      rvalid <= read_valid_pipe[READ_LATENCY-1];
      rdata <= read_data_pipe[READ_LATENCY-1];
      fault <= 1'b0;  // No faults in this simple model
    end
  end

endmodule : behavioral_memory