148 lines
4.2 KiB
Systemverilog
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
|