Files
gps/hardware/fpga/vcu118/rtl/axi4_ram_64.sv
T
2026-07-12 11:01:51 +03:00

148 lines
4.2 KiB
Systemverilog

`timescale 1ns/1ps
module axi4_ram_64 #(
parameter integer ADDR_WIDTH = 32,
parameter integer ID_WIDTH = 4,
parameter integer DEPTH_WORDS = 16384
) (
input wire clk,
input wire reset,
output wire aw_ready,
input wire aw_valid,
input wire [ID_WIDTH-1:0] aw_bits_id,
input wire [ADDR_WIDTH-1:0] aw_bits_addr,
input wire [7:0] aw_bits_len,
input wire [2:0] aw_bits_size,
input wire [1:0] aw_bits_burst,
output wire w_ready,
input wire w_valid,
input wire [63:0] w_bits_data,
input wire [7:0] w_bits_strb,
input wire w_bits_last,
input wire b_ready,
output reg b_valid,
output reg [ID_WIDTH-1:0] b_bits_id,
output wire [1:0] b_bits_resp,
output wire ar_ready,
input wire ar_valid,
input wire [ID_WIDTH-1:0] ar_bits_id,
input wire [ADDR_WIDTH-1:0] ar_bits_addr,
input wire [7:0] ar_bits_len,
input wire [2:0] ar_bits_size,
input wire [1:0] ar_bits_burst,
input wire r_ready,
output reg r_valid,
output reg [ID_WIDTH-1:0] r_bits_id,
output reg [63:0] r_bits_data,
output wire [1:0] r_bits_resp,
output reg r_bits_last
);
localparam integer ADDR_LSB = 3;
localparam integer DEPTH_BITS = $clog2(DEPTH_WORDS);
reg [63:0] mem [0:DEPTH_WORDS-1];
reg wr_active;
reg [ID_WIDTH-1:0] wr_id;
reg [ADDR_WIDTH-1:0] wr_addr;
reg [7:0] wr_beats_left;
reg rd_active;
reg [ID_WIDTH-1:0] rd_id;
reg [ADDR_WIDTH-1:0] rd_addr;
reg [7:0] rd_beats_left;
wire [DEPTH_BITS-1:0] wr_index = wr_addr[ADDR_LSB + DEPTH_BITS - 1:ADDR_LSB];
wire [DEPTH_BITS-1:0] rd_index = rd_addr[ADDR_LSB + DEPTH_BITS - 1:ADDR_LSB];
assign aw_ready = !wr_active && !b_valid;
assign w_ready = wr_active;
assign b_bits_resp = 2'b00;
assign ar_ready = !rd_active && !r_valid;
assign r_bits_resp = 2'b00;
integer i;
always @(posedge clk) begin
if (reset) begin
wr_active <= 1'b0;
b_valid <= 1'b0;
b_bits_id <= {ID_WIDTH{1'b0}};
wr_id <= {ID_WIDTH{1'b0}};
wr_addr <= {ADDR_WIDTH{1'b0}};
wr_beats_left <= 8'd0;
end else begin
if (aw_ready && aw_valid) begin
wr_active <= 1'b1;
wr_id <= aw_bits_id;
wr_addr <= aw_bits_addr;
wr_beats_left <= aw_bits_len;
end
if (w_ready && w_valid) begin
for (i = 0; i < 8; i = i + 1) begin
if (w_bits_strb[i]) begin
mem[wr_index][8*i +: 8] <= w_bits_data[8*i +: 8];
end
end
if (wr_beats_left == 8'd0 || w_bits_last) begin
wr_active <= 1'b0;
b_valid <= 1'b1;
b_bits_id <= wr_id;
end else begin
wr_addr <= wr_addr + ({{(ADDR_WIDTH-1){1'b0}}, 1'b1} << aw_bits_size);
wr_beats_left <= wr_beats_left - 8'd1;
end
end
if (b_valid && b_ready) begin
b_valid <= 1'b0;
end
end
end
always @(posedge clk) begin
if (reset) begin
rd_active <= 1'b0;
r_valid <= 1'b0;
r_bits_id <= {ID_WIDTH{1'b0}};
r_bits_data <= 64'd0;
r_bits_last <= 1'b0;
rd_id <= {ID_WIDTH{1'b0}};
rd_addr <= {ADDR_WIDTH{1'b0}};
rd_beats_left <= 8'd0;
end else begin
if (ar_ready && ar_valid) begin
rd_active <= 1'b1;
rd_id <= ar_bits_id;
rd_addr <= ar_bits_addr;
rd_beats_left <= ar_bits_len;
end
if (rd_active && (!r_valid || r_ready)) begin
r_valid <= 1'b1;
r_bits_id <= rd_id;
r_bits_data <= mem[rd_index];
r_bits_last <= rd_beats_left == 8'd0;
if (rd_beats_left == 8'd0) begin
rd_active <= 1'b0;
end else begin
rd_addr <= rd_addr + 64'd8;
rd_beats_left <= rd_beats_left - 8'd1;
end
end else if (r_valid && r_ready) begin
r_valid <= 1'b0;
r_bits_last <= 1'b0;
end
end
end
endmodule