Skip to content

Instantly share code, notes, and snippets.

@ytbilly3636
Last active February 19, 2019 13:36
Show Gist options
  • Save ytbilly3636/4ef3a5aea93eb72b55e053466c85e648 to your computer and use it in GitHub Desktop.
Save ytbilly3636/4ef3a5aea93eb72b55e053466c85e648 to your computer and use it in GitHub Desktop.
axi_read_write.vよりも簡単な実装法があったンゴ
`timescale 1ns / 1ps
// 1:IP catalogからFirst Word Fall Through FIFO(データ幅32bit,長さは256以上)を生成する(名前はfifo_32bitにする)
// 2:これをTOPモジュールにしてIPを作る
module axi_read_write #
( parameter integer C_M_AXI_ADDR_WIDTH = 32
, parameter integer C_M_AXI_DATA_WIDTH = 32
, parameter integer C_M_AXI_DATA_LENGTH = 256
, parameter integer C_M_AXI_THREAD_ID_WIDTH = 1
)
( input ACLK
, input ARESETN
// GPIO
, input GPI_STT
, input [C_M_AXI_ADDR_WIDTH-1:0] GPI_ADDR
, output GPO_ENA
// AR
, output M_AXI_ARVALID
, input M_AXI_ARREADY
, output [C_M_AXI_ADDR_WIDTH-1:0] M_AXI_ARADDR
, output [8-1:0] M_AXI_ARLEN
, output [3-1:0] M_AXI_ARSIZE
, output [2-1:0] M_AXI_ARBURST
, output [2-1:0] M_AXI_ARLOCK
, output [4-1:0] M_AXI_ARCACHE
, output [3-1:0] M_AXI_ARPROT
, output [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_ARID
, output [4-1:0] M_AXI_ARQOS
, output [4-1:0] M_AXI_ARREGION
, output M_AXI_ARUSER
// R
, input M_AXI_RVALID
, output M_AXI_RREADY
, input M_AXI_RLAST
, input [C_M_AXI_DATA_WIDTH-1:0] M_AXI_RDATA
, input [2-1:0] M_AXI_RRESP
, input [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_RID
, input M_AXI_RUSER
// AW
, output M_AXI_AWVALID
, input M_AXI_AWREADY
, output [C_M_AXI_ADDR_WIDTH-1:0] M_AXI_AWADDR
, output [8-1:0] M_AXI_AWLEN
, output [3-1:0] M_AXI_AWSIZE
, output [2-1:0] M_AXI_AWBURST
, output [2-1:0] M_AXI_AWLOCK
, output [4-1:0] M_AXI_AWCACHE
, output [3-1:0] M_AXI_AWPROT
, output [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_AWID
, output [4-1:0] M_AXI_AWQOS
, output [4-1:0] M_AXI_AWREGION
, output M_AXI_AWUSER
// W
, output M_AXI_WVALID
, input M_AXI_WREADY
, output M_AXI_WLAST
, output [C_M_AXI_DATA_WIDTH-1:0] M_AXI_WDATA
, output [4-1:0] M_AXI_WSTRB
, output M_AXI_WUSER
// B
, input M_AXI_BVALID
, output M_AXI_BREADY
, input [2-1:0] M_AXI_BRESP
, input M_AXI_BID
, input M_AXI_BUSER
);
// fixed ports
localparam LENGTH = C_M_AXI_DATA_LENGTH - 1;
assign M_AXI_ARSIZE = 3'b010;
assign M_AXI_ARBURST = 2'b01;
assign M_AXI_ARLEN = LENGTH[7:0];
assign M_AXI_AWSIZE = 3'b010;
assign M_AXI_AWBURST = 2'b01;
assign M_AXI_AWLEN = LENGTH[7:0];
assign M_AXI_ARLOCK = 2'b00;
assign M_AXI_ARCACHE = 4'b0011;
assign M_AXI_ARPROT = 3'b000;
assign M_AXI_ARID = 1'b0;
assign M_AXI_ARQOS = 4'b0000;
assign M_AXI_ARREGION = 4'b0000;
assign M_AXI_ARUSER = 1'b0;
assign M_AXI_AWLOCK = 2'b00;
assign M_AXI_AWCACHE = 4'b0011;
assign M_AXI_AWPROT = 3'b000;
assign M_AXI_AWID = 1'b0;
assign M_AXI_AWQOS = 4'b0000;
assign M_AXI_AWREGION = 4'b0000;
assign M_AXI_AWUSER = 1'b0;
assign M_AXI_WSTRB = 4'b1111;
assign M_AXI_WUSER = 1'b0;
// registers for AXI
reg r_arvalid;
reg r_awvalid;
reg [C_M_AXI_ADDR_WIDTH-1:0] r_addr;
// fifo
reg r_srst_fifo;
wire [C_M_AXI_DATA_WIDTH-1:0] w_din_fifo;
wire w_wr_en_fifo;
wire w_rd_en_fifo;
wire [C_M_AXI_DATA_WIDTH-1:0] w_dout_fifo;
wire w_full_fifo;
wire w_empty_fifo;
/*
// marseeさんが公開している同期FIFO
// XilinxのIPはシミュレーションのとき重いので
sync_fifo #
( .C_MEMORY_SIZE (512)
, .DATA_BUS_WIDTH (C_M_AXI_DATA_WIDTH)
) fifo
( .clk (ACLK)
, .rst (r_srst_fifo)
, .din (w_din_fifo)
, .wr_en (w_wr_en_fifo)
, .rd_en (w_rd_en_fifo)
, .dout (w_dout_fifo)
, .full (w_full_fifo)
, .empty (w_empty_fifo)
);
*/
fifo_32bit fifo
( .clk (ACLK)
, .srst (r_srst_fifo)
, .din (w_din_fifo)
, .wr_en (w_wr_en_fifo)
, .rd_en (w_rd_en_fifo)
, .dout (w_dout_fifo)
, .full (w_full_fifo)
, .empty (w_empty_fifo)
);
// state machine
localparam IDLE = 3'b000,
STT_AR = 3'b001,
STT_R = 3'b010,
STT_AW = 3'b011,
STT_W = 3'b100;
reg [2:0] r_stt = IDLE;
reg [7:0] r_cnt = 0;
always @(posedge ACLK) begin
if (!ARESETN) begin
r_arvalid <= 0;
r_awvalid <= 0;
r_addr <= 0;
r_srst_fifo <= 1;
r_stt <= IDLE;
r_cnt <= 0;
end
else if (r_stt == IDLE) begin
r_srst_fifo <= 0;
r_cnt <= 0;
if (GPI_STT) begin
r_addr <= GPI_ADDR;
r_arvalid <= 1;
r_stt <= STT_AR;
end
end
else if (r_stt == STT_AR) begin
if (M_AXI_ARREADY) begin
r_arvalid <= 0;
r_stt <= STT_R;
end
end
else if (r_stt == STT_R) begin
if (M_AXI_RLAST && M_AXI_RVALID && M_AXI_RREADY) begin
r_awvalid <= 1;
r_stt <= STT_AW;
end
end
else if (r_stt == STT_AW) begin
if (M_AXI_AWREADY) begin
r_awvalid <= 0;
r_stt <= STT_W;
end
end
else if (r_stt == STT_W) begin
if (M_AXI_WREADY && M_AXI_WVALID)
r_cnt <= r_cnt + 1;
if (M_AXI_BVALID) begin
r_stt <= IDLE;
end
end
end
// GPIO
assign GPO_ENA = (r_stt == IDLE) ? 1 : 0;
// AXI Addr Read
assign M_AXI_ARVALID = r_arvalid;
assign M_AXI_ARADDR = r_addr;
// AXI Read
assign w_din_fifo = M_AXI_RDATA;
assign w_wr_en_fifo = M_AXI_RVALID;
assign M_AXI_RREADY = (!w_full_fifo) && (r_stt == STT_R);
// AXI Addr Write
assign M_AXI_AWVALID = r_awvalid;
assign M_AXI_AWADDR = r_addr;
// AXI Write
assign w_rd_en_fifo = M_AXI_WREADY;
assign M_AXI_WVALID = (!w_empty_fifo) && M_AXI_WREADY;
assign M_AXI_WDATA = w_dout_fifo;
assign M_AXI_WLAST = (r_cnt == LENGTH[7:0]) ? 1 : 0;
// AXI B
assign M_AXI_BREADY = (r_stt == STT_W) ? 1 : 0;
endmodule
`timescale 1ns / 1ps
module test_axi_read_write;
parameter integer C_PERIOD = 2;
parameter integer C_M_AXI_THREAD_ID_WIDTH = 1;
parameter integer C_M_AXI_ADDR_WIDTH = 32;
parameter integer C_M_AXI_DATA_WIDTH = 32;
parameter integer C_M_AXI_DATA_LENGTH = 256;
reg ACLK;
reg ARESETN;
wire M_AXI_ARVALID;
wire M_AXI_ARREADY;
wire [C_M_AXI_ADDR_WIDTH-1:0] M_AXI_ARADDR;
wire [8-1:0] M_AXI_ARLEN;
wire [3-1:0] M_AXI_ARSIZE;
wire [2-1:0] M_AXI_ARBURST;
wire [2-1:0] M_AXI_ARLOCK;
wire [4-1:0] M_AXI_ARCACHE;
wire [3-1:0] M_AXI_ARPROT;
wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_ARID;
wire [4-1:0] M_AXI_ARQOS;
wire [4-1:0] M_AXI_ARREGION;
wire M_AXI_ARUSER;
wire M_AXI_RVALID;
wire M_AXI_RREADY;
wire M_AXI_RLAST;
wire [C_M_AXI_DATA_WIDTH-1:0] M_AXI_RDATA;
wire [2-1:0] M_AXI_RRESP;
wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_RID;
wire M_AXI_RUSER;
wire M_AXI_AWVALID;
wire M_AXI_AWREADY;
wire [C_M_AXI_ADDR_WIDTH-1:0] M_AXI_AWADDR;
wire [8-1:0] M_AXI_AWLEN;
wire [3-1:0] M_AXI_AWSIZE;
wire [2-1:0] M_AXI_AWBURST;
wire [2-1:0] M_AXI_AWLOCK;
wire [4-1:0] M_AXI_AWCACHE;
wire [3-1:0] M_AXI_AWPROT;
wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_AWID;
wire [4-1:0] M_AXI_AWQOS;
wire [4-1:0] M_AXI_AWREGION;
wire M_AXI_AWUSER;
wire M_AXI_WVALID;
wire M_AXI_WREADY;
wire M_AXI_WLAST;
wire [C_M_AXI_DATA_WIDTH-1:0] M_AXI_WDATA;
wire [4-1:0] M_AXI_WSTRB;
wire M_AXI_WUSER;
wire M_AXI_BVALID;
wire M_AXI_BREADY;
wire [2-1:0] M_AXI_BRESP;
wire M_AXI_BID;
wire M_AXI_BUSER;
reg GPI_STT;
reg [C_M_AXI_ADDR_WIDTH-1:0] GPI_ADDR;
wire GPO_ENA;
axi_read_write #
( .C_M_AXI_ADDR_WIDTH (C_M_AXI_ADDR_WIDTH)
, .C_M_AXI_DATA_WIDTH (C_M_AXI_DATA_WIDTH)
, .C_M_AXI_DATA_LENGTH (C_M_AXI_DATA_LENGTH)
, .C_M_AXI_THREAD_ID_WIDTH (C_M_AXI_THREAD_ID_WIDTH)
) master
( .ACLK (ACLK)
, .ARESETN (ARESETN)
, .M_AXI_ARVALID (M_AXI_ARVALID)
, .M_AXI_ARREADY (M_AXI_ARREADY)
, .M_AXI_ARADDR (M_AXI_ARADDR)
, .M_AXI_ARLEN (M_AXI_ARLEN)
, .M_AXI_ARSIZE (M_AXI_ARSIZE)
, .M_AXI_ARBURST (M_AXI_ARBURST)
, .M_AXI_ARLOCK (M_AXI_ARLOCK)
, .M_AXI_ARCACHE (M_AXI_ARCACHE)
, .M_AXI_ARPROT (M_AXI_ARPROT)
, .M_AXI_ARID (M_AXI_ARID)
, .M_AXI_ARQOS (M_AXI_ARQOS)
, .M_AXI_ARREGION (M_AXI_ARREGION)
, .M_AXI_ARUSER (M_AXI_ARUSER)
, .M_AXI_RVALID (M_AXI_RVALID)
, .M_AXI_RREADY (M_AXI_RREADY)
, .M_AXI_RLAST (M_AXI_RLAST)
, .M_AXI_RDATA (M_AXI_RDATA)
, .M_AXI_RRESP (M_AXI_RRESP)
, .M_AXI_RID (M_AXI_RID)
, .M_AXI_RUSER (M_AXI_RUSER)
, .M_AXI_AWVALID (M_AXI_AWVALID)
, .M_AXI_AWREADY (M_AXI_AWREADY)
, .M_AXI_AWADDR (M_AXI_AWADDR)
, .M_AXI_AWLEN (M_AXI_AWLEN)
, .M_AXI_AWSIZE (M_AXI_AWSIZE)
, .M_AXI_AWBURST (M_AXI_AWBURST)
, .M_AXI_AWLOCK (M_AXI_AWLOCK)
, .M_AXI_AWCACHE (M_AXI_AWCACHE)
, .M_AXI_AWPROT (M_AXI_AWPROT)
, .M_AXI_AWID (M_AXI_AWID)
, .M_AXI_AWQOS (M_AXI_AWQOS)
, .M_AXI_AWREGION (M_AXI_AWREGION)
, .M_AXI_AWUSER (M_AXI_AWUSER)
, .M_AXI_WVALID (M_AXI_WVALID)
, .M_AXI_WREADY (M_AXI_WREADY)
, .M_AXI_WLAST (M_AXI_WLAST)
, .M_AXI_WDATA (M_AXI_WDATA)
, .M_AXI_WSTRB (M_AXI_WSTRB)
, .M_AXI_WUSER (M_AXI_WUSER)
, .M_AXI_BVALID (M_AXI_BVALID)
, .M_AXI_BREADY (M_AXI_BREADY)
, .M_AXI_BRESP (M_AXI_BRESP)
, .M_AXI_BID (M_AXI_BID)
, .M_AXI_BUSER (M_AXI_BUSER)
, .GPI_STT (GPI_STT)
, .GPI_ADDR (GPI_ADDR)
, .GPO_ENA (GPO_ENA)
);
axi_slave #
( .C_S_AXI_ADDR_WIDTH (C_M_AXI_ADDR_WIDTH)
, .C_S_AXI_DATA_WIDTH (C_M_AXI_DATA_WIDTH)
, .C_S_AXI_BURST_LEN (C_M_AXI_DATA_LENGTH)
, .WRITE_RANDOM_WAIT (1)
, .READ_RANDOM_WAIT (1)
, .READ_DATA_IS_INCREMENT (0)
, .RANDOM_BVALID_WAIT (1)
, .AWREADY_IS_USUALLY_HIGH (1)
, .ARREADY_IS_USUALLY_HIGH (1)
) slave
( .ACLK (ACLK)
, .ARESETN (ARESETN)
, .S_AXI_AWID (M_AXI_AWID)
, .S_AXI_AWADDR (M_AXI_AWADDR)
, .S_AXI_AWLEN (M_AXI_AWLEN)
, .S_AXI_AWSIZE (M_AXI_AWSIZE)
, .S_AXI_AWBURST (M_AXI_AWBURST)
, .S_AXI_AWLOCK (M_AXI_AWLOCK)
, .S_AXI_AWCACHE (M_AXI_AWCACHE)
, .S_AXI_AWPROT (M_AXI_AWPROT)
, .S_AXI_AWQOS (M_AXI_AWQOS)
, .S_AXI_AWUSER (M_AXI_AWUSER)
, .S_AXI_AWVALID (M_AXI_AWVALID)
, .S_AXI_AWREADY (M_AXI_AWREADY)
, .S_AXI_WDATA (M_AXI_WDATA)
, .S_AXI_WSTRB (M_AXI_WSTRB)
, .S_AXI_WLAST (M_AXI_WLAST)
, .S_AXI_WUSER (M_AXI_WUSER)
, .S_AXI_WVALID (M_AXI_WVALID)
, .S_AXI_WREADY (M_AXI_WREADY)
, .S_AXI_BID (M_AXI_BID)
, .S_AXI_BRESP (M_AXI_BRESP)
, .S_AXI_BUSER (M_AXI_BUSER)
, .S_AXI_BVALID (M_AXI_BVALID)
, .S_AXI_BREADY (M_AXI_BREADY)
, .S_AXI_ARID (M_AXI_ARID)
, .S_AXI_ARADDR (M_AXI_ARADDR)
, .S_AXI_ARLEN (M_AXI_ARLEN)
, .S_AXI_ARSIZE (M_AXI_ARSIZE)
, .S_AXI_ARBURST (M_AXI_ARBURST)
, .S_AXI_ARLOCK (M_AXI_ARLOCK)
, .S_AXI_ARCACHE (M_AXI_ARCACHE)
, .S_AXI_ARPROT (M_AXI_ARPROT)
, .S_AXI_ARQOS (M_AXI_ARQOS)
, .S_AXI_ARUSER (M_AXI_ARUSER)
, .S_AXI_ARVALID (M_AXI_ARVALID)
, .S_AXI_ARREADY (M_AXI_ARREADY)
, .S_AXI_RID (M_AXI_RID)
, .S_AXI_RDATA (M_AXI_RDATA)
, .S_AXI_RRESP (M_AXI_RRESP)
, .S_AXI_RLAST (M_AXI_RLAST)
, .S_AXI_RUSER (M_AXI_RUSER)
, .S_AXI_RVALID (M_AXI_RVALID)
, .S_AXI_RREADY (M_AXI_RREADY)
);
always #(C_PERIOD/2) ACLK = ~ACLK;
integer i;
initial begin
#0
ACLK = 1'b0;
ARESETN = 1'b1;
GPI_STT = 1'b0;
GPI_ADDR = 0;
#(C_PERIOD)
ARESETN = 1'b0;
#(C_PERIOD)
ARESETN = 1'b1;
#(C_PERIOD)
for (i = GPI_ADDR; i < GPI_ADDR + 256; i = i + 1) begin
slave.ram_array[i][7:0] = i[7:0] + 10;
slave.ram_array[i][31:8] = 0;
end
#(C_PERIOD)
GPI_STT = 1'b1;
#(C_PERIOD)
GPI_STT = 1'b0;
#(C_PERIOD * 2000)
GPI_STT = 1'b1;
#(C_PERIOD)
GPI_STT = 1'b0;
#(C_PERIOD * 2000)
$finish;
end
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment