mirror of
https://github.com/bmartini/zynq-axis.git
synced 2024-09-05 19:19:27 +08:00
Merge branch 'connect-axis-to-hp0'
Add a High Performance port (HP0) to the zedboard_axis project and connect a AXIS module that can read and write to the main memory using HP0. Add two small applications that test writing and reading from memory.
This commit is contained in:
commit
80d401db54
10
app/Makefile
10
app/Makefile
@ -4,6 +4,8 @@ CFLAGS := -c -Wall -Werror
|
||||
INCLUDES := -I.
|
||||
|
||||
EXECUTABLE = \
|
||||
write-memory \
|
||||
read-memory \
|
||||
test-cfg
|
||||
|
||||
|
||||
@ -15,6 +17,14 @@ all : $(EXECUTABLE)
|
||||
$(CC) $(INCLUDES) $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
write-memory : write-memory.o
|
||||
$(CC) $< -o $@ $(LDFLAGS)
|
||||
|
||||
|
||||
read-memory : read-memory.o
|
||||
$(CC) $< -o $@ $(LDFLAGS)
|
||||
|
||||
|
||||
test-cfg : test-cfg.o
|
||||
$(CC) $< -o $@ $(LDFLAGS)
|
||||
|
||||
|
57
app/read-memory.c
Normal file
57
app/read-memory.c
Normal file
@ -0,0 +1,57 @@
|
||||
#include <interface.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
enum cfg_regsiters {
|
||||
CFG_AXIS_ADDR,
|
||||
CFG_AXIS_DATA,
|
||||
CFG_HP0_DST_CNT,
|
||||
CFG_HP0_SRC_CNT,
|
||||
CFG_HP0_DST_DATA,
|
||||
CFG_HP0_SRC_DATA,
|
||||
CFG_EMPTY,
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (axis_init("/dev/axis") != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <length>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
off_t offset = 0x1b900000;
|
||||
size_t len = atoi(argv[1]);
|
||||
printf("phys_addr: %ld, %02x, length: %ld\n", (long int)offset,
|
||||
(unsigned int)offset, (long int)len);
|
||||
|
||||
|
||||
// configure axis to write to memory
|
||||
printf("config start\n");
|
||||
cfg_write(CFG_AXIS_ADDR, 1);
|
||||
cfg_write(CFG_AXIS_DATA, offset);
|
||||
cfg_write(CFG_AXIS_DATA, len);
|
||||
printf("config done\n");
|
||||
|
||||
// send data to be written over cfg bus
|
||||
printf("read start\n");
|
||||
cfg_read(CFG_HP0_SRC_DATA); // prime cfg register
|
||||
for (i = 0; i < len; ++i) {
|
||||
printf("%d ", cfg_read(CFG_HP0_SRC_DATA));
|
||||
}
|
||||
printf("\nhp0 src cnt: %d\n", cfg_read(CFG_HP0_SRC_CNT));
|
||||
|
||||
if (axis_exit() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("\ndone\n");
|
||||
|
||||
return 0;
|
||||
}
|
82
app/write-memory.c
Normal file
82
app/write-memory.c
Normal file
@ -0,0 +1,82 @@
|
||||
#include <interface.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
enum cfg_regsiters {
|
||||
CFG_AXIS_ADDR,
|
||||
CFG_AXIS_DATA,
|
||||
CFG_HP0_DST_CNT,
|
||||
CFG_HP0_SRC_CNT,
|
||||
CFG_HP0_DST_DATA,
|
||||
CFG_HP0_SRC_DATA,
|
||||
CFG_EMPTY,
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (axis_init("/dev/axis") != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <length>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
off_t offset = 0x1b900000;
|
||||
size_t len = atoi(argv[1]);
|
||||
printf("phys_addr: %ld, %02x, length: %ld\n", (long int)offset,
|
||||
(unsigned int)offset, (long int)len);
|
||||
|
||||
int fd = open("/dev/mem", O_SYNC);
|
||||
unsigned int *mem =
|
||||
(unsigned int *)mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE,
|
||||
fd, offset);
|
||||
|
||||
if (mem == NULL) {
|
||||
printf("Can't map memory\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
// configure axis to write to memory
|
||||
printf("config start\n");
|
||||
cfg_write(CFG_AXIS_ADDR, 2);
|
||||
cfg_write(CFG_AXIS_DATA, offset);
|
||||
cfg_write(CFG_AXIS_DATA, len);
|
||||
printf("config done\n");
|
||||
|
||||
// send data to be written over cfg bus
|
||||
printf("write start\n");
|
||||
for (i = 0; i < len; ++i) {
|
||||
cfg_write(CFG_HP0_DST_DATA, i + 1);
|
||||
//cfg_write(CFG_HP0_DST_DATA, 0);
|
||||
}
|
||||
printf("hp0 dst cnt: %d\n", cfg_read(CFG_HP0_DST_CNT));
|
||||
printf("write done\n");
|
||||
|
||||
// check memory for data
|
||||
for (i = 0; i < len; ++i) {
|
||||
printf("%6d, %10ld, %02x, hex: %x,\tbinary: %d\n", i + 1,
|
||||
(offset + (sizeof(mem[0]) * i)),
|
||||
(unsigned int)(offset + (sizeof(mem[0]) * i)),
|
||||
(int)mem[i], (int)mem[i]);
|
||||
}
|
||||
|
||||
if (munmap(mem, len) < 0) {
|
||||
printf("Can't unmap memory\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (axis_exit() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("\ndone\n");
|
||||
|
||||
return 0;
|
||||
}
|
225
hdl/axis/axis.v
Normal file
225
hdl/axis/axis.v
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Module:
|
||||
* axis
|
||||
*
|
||||
* Description:
|
||||
* The axis module instantiates the AXI read and write path modules.
|
||||
*
|
||||
* Created:
|
||||
* Fri Nov 7 23:07:05 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_ `define _axis_
|
||||
|
||||
|
||||
`include "axis_write.v"
|
||||
`include "axis_read.v"
|
||||
|
||||
module axis #(
|
||||
parameter
|
||||
BUF_AWIDTH = 9,
|
||||
|
||||
CONFIG_ID_WR = 1,
|
||||
CONFIG_ID_RD = 2,
|
||||
CONFIG_ADDR = 23,
|
||||
CONFIG_DATA = 24,
|
||||
CONFIG_AWIDTH = 5,
|
||||
CONFIG_DWIDTH = 32,
|
||||
|
||||
STREAM_WIDTH = 32,
|
||||
|
||||
AXI_ID_WIDTH = 8,
|
||||
AXI_LEN_WIDTH = 8,
|
||||
AXI_ADDR_WIDTH = 32,
|
||||
AXI_DATA_WIDTH = 256)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
// configuation
|
||||
input [CONFIG_AWIDTH-1:0] cfg_addr,
|
||||
input [CONFIG_DWIDTH-1:0] cfg_data,
|
||||
input cfg_valid,
|
||||
|
||||
// stream interface
|
||||
input wr_valid,
|
||||
input [STREAM_WIDTH-1:0] wr_data,
|
||||
output wr_ready,
|
||||
|
||||
output rd_valid,
|
||||
output [STREAM_WIDTH-1:0] rd_data,
|
||||
input rd_ready,
|
||||
|
||||
// AXI write address channel signals
|
||||
input axi_awready,
|
||||
output [AXI_ID_WIDTH-1:0] axi_awid,
|
||||
output [AXI_ADDR_WIDTH-1:0] axi_awaddr,
|
||||
output [AXI_LEN_WIDTH-1:0] axi_awlen,
|
||||
output [2:0] axi_awsize,
|
||||
output [1:0] axi_awburst,
|
||||
output axi_awlock,
|
||||
output [3:0] axi_awcache,
|
||||
output [2:0] axi_awprot,
|
||||
output [3:0] axi_awqos,
|
||||
output axi_awvalid,
|
||||
|
||||
// AXI write data channel signals
|
||||
input axi_wready,
|
||||
output [AXI_ID_WIDTH-1:0] axi_wid,
|
||||
output [AXI_DATA_WIDTH-1:0] axi_wdata,
|
||||
output [AXI_DATA_WIDTH/8-1:0] axi_wstrb,
|
||||
output axi_wlast,
|
||||
output axi_wvalid,
|
||||
|
||||
// AXI write response channel signals
|
||||
input [AXI_ID_WIDTH-1:0] axi_bid,
|
||||
input [1:0] axi_bresp,
|
||||
input axi_bvalid,
|
||||
output axi_bready,
|
||||
|
||||
// AXI read address channel signals
|
||||
input axi_arready,
|
||||
output [AXI_ID_WIDTH-1:0] axi_arid,
|
||||
output [AXI_ADDR_WIDTH-1:0] axi_araddr,
|
||||
output [AXI_LEN_WIDTH-1:0] axi_arlen,
|
||||
output [2:0] axi_arsize,
|
||||
output [1:0] axi_arburst,
|
||||
output [1:0] axi_arlock,
|
||||
output [3:0] axi_arcache,
|
||||
output [2:0] axi_arprot,
|
||||
output axi_arvalid,
|
||||
output [3:0] axi_arqos,
|
||||
|
||||
// AXI read data channel signals
|
||||
input [AXI_ID_WIDTH-1:0] axi_rid,
|
||||
input [1:0] axi_rresp,
|
||||
input axi_rvalid,
|
||||
input [AXI_DATA_WIDTH-1:0] axi_rdata,
|
||||
input axi_rlast,
|
||||
output axi_rready
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam BURST_SIZE =
|
||||
( 1 == (AXI_DATA_WIDTH/8)) ? 3'h0 :
|
||||
( 2 == (AXI_DATA_WIDTH/8)) ? 3'h1 :
|
||||
( 4 == (AXI_DATA_WIDTH/8)) ? 3'h2 :
|
||||
( 8 == (AXI_DATA_WIDTH/8)) ? 3'h3 :
|
||||
(16 == (AXI_DATA_WIDTH/8)) ? 3'h4 :
|
||||
(32 == (AXI_DATA_WIDTH/8)) ? 3'h5 :
|
||||
(64 == (AXI_DATA_WIDTH/8)) ? 3'h6 : 3'h7;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
// write path static values
|
||||
assign axi_awlock = 1'h0; // NORMAL_ACCESS
|
||||
assign axi_awcache = 4'h0; // NON_CACHE_NON_BUFFER
|
||||
assign axi_awprot = 3'h0; // DATA_SECURE_NORMAL
|
||||
assign axi_awburst = 2'h1; // INCREMENTING
|
||||
assign axi_awqos = 4'h0; // NOT_QOS_PARTICIPANT
|
||||
assign axi_awsize = BURST_SIZE;
|
||||
assign axi_awid = {AXI_ID_WIDTH{1'b0}};
|
||||
assign axi_wid = {AXI_ID_WIDTH{1'b0}};
|
||||
assign axi_wstrb = {(AXI_DATA_WIDTH/8){1'b1}};
|
||||
|
||||
// read path static values
|
||||
assign axi_arlock = 2'h0; // NORMAL_ACCESS
|
||||
assign axi_arcache = 4'h0; // NON_CACHE_NON_BUFFER
|
||||
assign axi_arprot = 3'h0; // DATA_SECURE_NORMAL
|
||||
assign axi_arburst = 2'h1; // INCREMENTING
|
||||
assign axi_arqos = 4'h0; // NOT_QOS_PARTICIPANT
|
||||
assign axi_arsize = BURST_SIZE;
|
||||
assign axi_arid = {AXI_ID_WIDTH{1'b0}};
|
||||
|
||||
|
||||
// assume that all writes are successful and therefore do not need to
|
||||
// check the write response
|
||||
assign axi_bready = 1'b1;
|
||||
|
||||
|
||||
axis_write #(
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
|
||||
.CONFIG_ID (CONFIG_ID_WR),
|
||||
.CONFIG_ADDR (CONFIG_ADDR),
|
||||
.CONFIG_DATA (CONFIG_DATA),
|
||||
.CONFIG_AWIDTH (CONFIG_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
.DATA_WIDTH (STREAM_WIDTH))
|
||||
axis_write_ (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.cfg_addr (cfg_addr),
|
||||
.cfg_data (cfg_data),
|
||||
.cfg_valid (cfg_valid),
|
||||
|
||||
.axi_awready (axi_awready),
|
||||
.axi_awaddr (axi_awaddr),
|
||||
.axi_awlen (axi_awlen),
|
||||
.axi_awvalid (axi_awvalid),
|
||||
|
||||
.axi_wlast (axi_wlast),
|
||||
.axi_wdata (axi_wdata),
|
||||
.axi_wvalid (axi_wvalid),
|
||||
.axi_wready (axi_wready),
|
||||
|
||||
.data (wr_data),
|
||||
.valid (wr_valid),
|
||||
.ready (wr_ready)
|
||||
);
|
||||
|
||||
|
||||
axis_read #(
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
|
||||
.CONFIG_ID (CONFIG_ID_RD),
|
||||
.CONFIG_ADDR (CONFIG_ADDR),
|
||||
.CONFIG_DATA (CONFIG_DATA),
|
||||
.CONFIG_AWIDTH (CONFIG_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
.DATA_WIDTH (STREAM_WIDTH))
|
||||
axis_read_ (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.cfg_addr (cfg_addr),
|
||||
.cfg_data (cfg_data),
|
||||
.cfg_valid (cfg_valid),
|
||||
|
||||
.axi_arready (axi_arready),
|
||||
.axi_araddr (axi_araddr),
|
||||
.axi_arlen (axi_arlen),
|
||||
.axi_arvalid (axi_arvalid),
|
||||
|
||||
.axi_rresp (axi_rresp),
|
||||
.axi_rlast (axi_rlast),
|
||||
.axi_rdata (axi_rdata),
|
||||
.axi_rvalid (axi_rvalid),
|
||||
.axi_rready (axi_rready),
|
||||
|
||||
.data (rd_data),
|
||||
.valid (rd_valid),
|
||||
.ready (rd_ready)
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _axis_
|
203
hdl/axis/axis_addr.v
Normal file
203
hdl/axis/axis_addr.v
Normal file
@ -0,0 +1,203 @@
|
||||
/**
|
||||
* Module:
|
||||
* axis_addr
|
||||
*
|
||||
* Description:
|
||||
* The axis_addr handles the AXI write address channel.
|
||||
*
|
||||
* Test bench:
|
||||
* axis_addr_tb.v
|
||||
*
|
||||
* Created:
|
||||
* Wed Nov 5 21:15:56 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_addr_ `define _axis_addr_
|
||||
|
||||
|
||||
module axis_addr
|
||||
#(parameter
|
||||
CONFIG_DWIDTH = 32,
|
||||
WIDTH_RATIO = 16,
|
||||
CONVERT_SHIFT = 3,
|
||||
AXI_LEN_WIDTH = 8,
|
||||
AXI_ADDR_WIDTH = 32,
|
||||
AXI_DATA_WIDTH = 256)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
input [CONFIG_DWIDTH-1:0] cfg_address,
|
||||
input [CONFIG_DWIDTH-1:0] cfg_length,
|
||||
input cfg_valid,
|
||||
output cfg_ready,
|
||||
|
||||
input axi_aready,
|
||||
output [AXI_ADDR_WIDTH-1:0] axi_aaddr,
|
||||
output [AXI_LEN_WIDTH-1:0] axi_alen,
|
||||
output axi_avalid
|
||||
);
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam BURST_NB_WIDTH = CONFIG_DWIDTH-AXI_LEN_WIDTH;
|
||||
localparam BURST_LENGTH = 1<<AXI_LEN_WIDTH;
|
||||
|
||||
localparam
|
||||
IDLE = 0,
|
||||
SETUP = 1,
|
||||
BURST = 2,
|
||||
LAST = 3,
|
||||
DONE = 4;
|
||||
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
initial $display("\using 'axis_addr'\n");
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* Internal signals
|
||||
*/
|
||||
|
||||
|
||||
reg [4:0] state;
|
||||
reg [4:0] state_nx;
|
||||
|
||||
reg last_en;
|
||||
reg [AXI_LEN_WIDTH-1:0] last_nb;
|
||||
|
||||
reg burst_en;
|
||||
reg [BURST_NB_WIDTH-1:0] burst_nb;
|
||||
reg [BURST_NB_WIDTH-1:0] burst_cnt;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_length_r;
|
||||
reg cfg_valid_r;
|
||||
reg cfg_done;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] axi_address;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign cfg_ready = state[IDLE];
|
||||
|
||||
assign axi_aaddr = axi_address;
|
||||
|
||||
assign axi_alen = state[BURST] ? (BURST_LENGTH-1) : last_nb;
|
||||
|
||||
assign axi_avalid = state[BURST] | state[LAST];
|
||||
|
||||
assign burst_done = (burst_nb == burst_cnt);
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) cfg_valid_r <= 1'b0;
|
||||
else cfg_valid_r <= cfg_valid;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (cfg_valid) begin
|
||||
// the shift converts from number of stream elements to number of
|
||||
// bursts to be sent to the memory after stream is packed. adding a
|
||||
// bit to the length ensures that the shift rounds up
|
||||
|
||||
cfg_length_r <= (cfg_length+WIDTH_RATIO-1) >> CONVERT_SHIFT;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) cfg_done <= 1'b0;
|
||||
else cfg_done <= cfg_valid_r;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (cfg_valid_r) begin
|
||||
last_en <= |(cfg_length_r[AXI_LEN_WIDTH-1:0]);
|
||||
last_nb <= cfg_length_r[AXI_LEN_WIDTH-1:0]-1;
|
||||
|
||||
burst_en <= |(cfg_length_r[AXI_LEN_WIDTH +: BURST_NB_WIDTH]);
|
||||
burst_nb <= cfg_length_r[AXI_LEN_WIDTH +: BURST_NB_WIDTH]-1;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (cfg_valid) begin
|
||||
axi_address <= cfg_address;
|
||||
end
|
||||
else if (axi_aready & state[BURST]) begin
|
||||
// e.g. each burst has 256 long words & each long word has 32 bytes
|
||||
axi_address <= axi_address + (BURST_LENGTH * (AXI_DATA_WIDTH/8));
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (state[IDLE]) begin
|
||||
burst_cnt <= 'b0;
|
||||
end
|
||||
else if (axi_aready & state[BURST]) begin
|
||||
burst_cnt <= burst_cnt + 1;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) begin
|
||||
state <= 'b0;
|
||||
state[IDLE] <= 1'b1;
|
||||
end
|
||||
else state <= state_nx;
|
||||
|
||||
|
||||
always @* begin : ADDR_
|
||||
state_nx <= 'b0;
|
||||
|
||||
case (1'b1)
|
||||
state[IDLE] : begin
|
||||
if (cfg_valid) begin
|
||||
state_nx[SETUP] <= 1'b1;
|
||||
end
|
||||
else state_nx[IDLE] <= 1'b1;
|
||||
end
|
||||
state[SETUP] : begin
|
||||
if (cfg_done & burst_en) begin
|
||||
state_nx[BURST] <= 1'b1;
|
||||
end
|
||||
else if (cfg_done & ~burst_en) begin
|
||||
state_nx[LAST] <= 1'b1;
|
||||
end
|
||||
else state_nx[SETUP] <= 1'b1;
|
||||
end
|
||||
state[BURST] : begin
|
||||
if (axi_aready & burst_done & last_en) begin
|
||||
state_nx[LAST] <= 1'b1;
|
||||
end
|
||||
else if (axi_aready & burst_done & ~last_en) begin
|
||||
state_nx[DONE] <= 1'b1;
|
||||
end
|
||||
else state_nx[BURST] <= 1'b1;
|
||||
end
|
||||
state[LAST] : begin
|
||||
if (axi_aready) begin
|
||||
state_nx[DONE] <= 1'b1;
|
||||
end
|
||||
else state_nx[LAST] <= 1'b1;
|
||||
end
|
||||
state[DONE] : begin
|
||||
state_nx[IDLE] <= 1'b1;
|
||||
end
|
||||
default : begin
|
||||
state_nx[IDLE] <= 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _axis_addr_
|
229
hdl/axis/axis_addr_tb.v
Normal file
229
hdl/axis/axis_addr_tb.v
Normal file
@ -0,0 +1,229 @@
|
||||
/**
|
||||
* Testbench:
|
||||
* axis_addr
|
||||
*
|
||||
* Created:
|
||||
* Wed Nov 5 21:16:08 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
|
||||
`timescale 1ns/10ps
|
||||
|
||||
`define TB_VERBOSE
|
||||
//`define VERBOSE
|
||||
|
||||
|
||||
`include "axis_addr.v"
|
||||
|
||||
module axis_addr_tb;
|
||||
|
||||
/**
|
||||
* Clock and control functions
|
||||
*/
|
||||
|
||||
// Generate a clk
|
||||
reg clk;
|
||||
always #1 clk = !clk;
|
||||
|
||||
// End of simulation event definition
|
||||
event end_trigger;
|
||||
always @(end_trigger) $finish;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
// Display header information
|
||||
initial #1 display_header();
|
||||
always @(end_trigger) display_header();
|
||||
|
||||
// And strobe signals at each clk
|
||||
always @(posedge clk) display_signals();
|
||||
`endif
|
||||
|
||||
// initial begin
|
||||
// $dumpfile("result.vcd"); // Waveform file
|
||||
// $dumpvars;
|
||||
// end
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam CONFIG_DWIDTH = 32;
|
||||
localparam WIDTH_RATIO = 16;
|
||||
localparam AXI_ID_WIDTH = 8;
|
||||
localparam AXI_LEN_WIDTH = 8;
|
||||
localparam AXI_ADDR_WIDTH = 32;
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
initial $display("Testbench for unit 'axis_addr'");
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* signals, registers and wires
|
||||
*/
|
||||
|
||||
reg rst;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_address;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_length;
|
||||
reg cfg_valid;
|
||||
wire cfg_ready;
|
||||
|
||||
reg axi_aready;
|
||||
wire [AXI_ID_WIDTH-1:0] axi_aid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] axi_aaddr;
|
||||
wire [AXI_LEN_WIDTH-1:0] axi_alen;
|
||||
wire axi_avalid;
|
||||
|
||||
|
||||
/**
|
||||
* Unit under test
|
||||
*/
|
||||
|
||||
axis_addr #(
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
.CONVERT_SHIFT ($clog2(WIDTH_RATIO)),
|
||||
.AXI_ID_WIDTH (AXI_ID_WIDTH),
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH))
|
||||
uut (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.cfg_address (cfg_address),
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_valid),
|
||||
.cfg_ready (cfg_ready),
|
||||
|
||||
.axi_aready (axi_aready),
|
||||
.axi_aid (axi_aid),
|
||||
.axi_aaddr (axi_aaddr),
|
||||
.axi_alen (axi_alen),
|
||||
.axi_avalid (axi_avalid)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Wave form display
|
||||
*/
|
||||
|
||||
task display_signals;
|
||||
$display(
|
||||
"%d\t%d",
|
||||
$time, rst,
|
||||
|
||||
"\t%d\t%d\t%b\t%b",
|
||||
cfg_address,
|
||||
cfg_length,
|
||||
cfg_valid,
|
||||
cfg_ready,
|
||||
|
||||
"\t%d\t%d\t%d\t%b\t%b",
|
||||
axi_aid,
|
||||
axi_aaddr,
|
||||
axi_alen,
|
||||
axi_avalid,
|
||||
axi_aready,
|
||||
|
||||
"\tl_en %d\tl_nb %d",
|
||||
uut.last_en,
|
||||
uut.last_nb,
|
||||
|
||||
"\tb_en %d\tb_nb %d",
|
||||
uut.burst_en,
|
||||
uut.burst_nb,
|
||||
|
||||
"\t%b",
|
||||
uut.state,
|
||||
|
||||
);
|
||||
|
||||
endtask // display_signals
|
||||
|
||||
task display_header;
|
||||
$display(
|
||||
"\t\ttime\trst",
|
||||
|
||||
"\t\tc_a",
|
||||
"\t\tc_l",
|
||||
"\tc_v",
|
||||
"\tc_r",
|
||||
|
||||
"\ta_id",
|
||||
"\t\ta_a",
|
||||
"\ta_l",
|
||||
"\ta_v",
|
||||
"\ta_r",
|
||||
|
||||
);
|
||||
endtask
|
||||
|
||||
|
||||
/**
|
||||
* Testbench program
|
||||
*/
|
||||
|
||||
initial begin
|
||||
// init values
|
||||
clk = 0;
|
||||
rst = 0;
|
||||
|
||||
cfg_address = 'b0;
|
||||
cfg_length = 'b0;
|
||||
cfg_valid = 'b0;
|
||||
|
||||
axi_aready = 'b0;
|
||||
//end init
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("RESET");
|
||||
`endif
|
||||
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b1;
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b0;
|
||||
@(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("send config address and length");
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_address <= 255;
|
||||
//cfg_length <= 8;
|
||||
cfg_length <= 256+256+64;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk);
|
||||
cfg_address <= 'b0;
|
||||
cfg_length <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test write address channel");
|
||||
`endif
|
||||
|
||||
repeat(3) @(negedge clk);
|
||||
axi_aready <= 1'b1;
|
||||
@(negedge clk);
|
||||
axi_aready <= 1'b0;
|
||||
@(negedge clk);
|
||||
axi_aready <= 1'b1;
|
||||
repeat(50) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("END");
|
||||
`endif
|
||||
-> end_trigger;
|
||||
end
|
||||
|
||||
endmodule
|
105
hdl/axis/axis_deserializer.v
Normal file
105
hdl/axis/axis_deserializer.v
Normal file
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Module:
|
||||
* axis_deserializer
|
||||
*
|
||||
* Description:
|
||||
* Deserializes multiple 'up' flow bus data words into a single, larger
|
||||
* 'down' data words. Arranges them first to the right and moving left.
|
||||
*
|
||||
* If there is a pause in the incoming 'up' stream the values already written
|
||||
* into the larger 'down' word will stay until enough 'up' data has been sent
|
||||
* in to complete the 'down' word unless a 'up_last' signal forces the down
|
||||
* transfer. The module will stall when the down_ready flag deasserts.
|
||||
*
|
||||
* Testbench:
|
||||
* axis_deserializer_tb.v
|
||||
*
|
||||
* Created:
|
||||
* Thu Nov 6 17:29:58 EST 2014
|
||||
*
|
||||
* Authors:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_deserializer_ `define _axis_deserializer_
|
||||
|
||||
module axis_deserializer
|
||||
#(parameter
|
||||
DATA_NB = 2,
|
||||
DATA_WIDTH = 8)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
output up_ready,
|
||||
input up_valid,
|
||||
input [DATA_WIDTH-1:0] up_data,
|
||||
input up_last,
|
||||
|
||||
input down_ready,
|
||||
output reg down_valid,
|
||||
output reg [(DATA_WIDTH*DATA_NB)-1:0] down_data,
|
||||
output reg down_last
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
initial $display("\using 'axis_deserializer' with %0d words\n", DATA_NB);
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* Internal signals
|
||||
*/
|
||||
|
||||
genvar ii;
|
||||
|
||||
reg [DATA_NB-1:0] token;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
|
||||
assign up_ready = down_ready;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) down_last <= 1'b0;
|
||||
else if (down_ready) down_last <= up_last;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) down_valid <= 1'b0;
|
||||
else if (down_ready) begin
|
||||
down_valid <= (token[DATA_NB-1] & up_valid) | up_last;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst | (down_ready & up_last)) token <= 'b1;
|
||||
else if (down_ready & up_valid) begin
|
||||
token <= {token, token[DATA_NB-1]};
|
||||
end
|
||||
|
||||
|
||||
generate
|
||||
for (ii=0; ii<DATA_NB; ii=ii+1) begin : CONCAT_
|
||||
|
||||
always @(posedge clk)
|
||||
if (down_ready & token[ii]) begin
|
||||
down_data[ii*DATA_WIDTH +: DATA_WIDTH] <= up_data;
|
||||
end
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _axis_deserializer_
|
261
hdl/axis/axis_deserializer_tb.v
Normal file
261
hdl/axis/axis_deserializer_tb.v
Normal file
@ -0,0 +1,261 @@
|
||||
/**
|
||||
* Testbench for:
|
||||
* axis_deserializer
|
||||
*
|
||||
* Created:
|
||||
* Thu Nov 6 17:29:45 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
|
||||
`timescale 1ns/10ps
|
||||
|
||||
`define TB_VERBOSE
|
||||
//`define VERBOSE
|
||||
|
||||
|
||||
`include "axis_deserializer.v"
|
||||
|
||||
module axis_deserializer_tb;
|
||||
|
||||
/**
|
||||
* Clock and control functions
|
||||
*/
|
||||
|
||||
// Generate a clk
|
||||
reg clk;
|
||||
always #1 clk = !clk;
|
||||
|
||||
// End of simulation event definition
|
||||
event end_trigger;
|
||||
always @(end_trigger) $finish;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
// Display header information
|
||||
initial #1 display_header();
|
||||
always @(end_trigger) display_header();
|
||||
|
||||
// And strobe signals at each clk
|
||||
always @(posedge clk) display_signals();
|
||||
`endif
|
||||
|
||||
// initial begin
|
||||
// $dumpfile("result.vcd"); // Waveform file
|
||||
// $dumpvars;
|
||||
// end
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam DATA_NB = 3;
|
||||
localparam DATA_WIDTH = 8;
|
||||
|
||||
localparam STREAM_LENGTH = 256;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
initial begin
|
||||
$display("Testbench for unit 'axis_deserializer' data width: %d, nb: %d",
|
||||
DATA_WIDTH, DATA_NB);
|
||||
end
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* signals, registers and wires
|
||||
*/
|
||||
|
||||
reg rst;
|
||||
|
||||
reg [DATA_WIDTH-1:0] up_data;
|
||||
reg up_valid;
|
||||
wire up_ready;
|
||||
reg up_last;
|
||||
|
||||
wire [DATA_NB*DATA_WIDTH-1:0] down_data;
|
||||
wire down_valid;
|
||||
reg down_ready;
|
||||
wire down_last;
|
||||
|
||||
reg [DATA_WIDTH-1:0] stream [0:STREAM_LENGTH-1];
|
||||
integer cnt;
|
||||
|
||||
/**
|
||||
* Unit under test
|
||||
*/
|
||||
|
||||
axis_deserializer #(
|
||||
.DATA_NB (DATA_NB),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
uut (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.up_data (up_data),
|
||||
.up_valid (up_valid),
|
||||
.up_ready (up_ready),
|
||||
.up_last (up_last),
|
||||
|
||||
.down_data (down_data),
|
||||
.down_valid (down_valid),
|
||||
.down_ready (down_ready),
|
||||
.down_last (down_last)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Wave form display
|
||||
*/
|
||||
|
||||
task display_signals;
|
||||
$display(
|
||||
"%d\t%d",
|
||||
$time, rst,
|
||||
|
||||
"\t%x\t%b\t%b\t%b",
|
||||
up_data,
|
||||
up_valid,
|
||||
up_ready,
|
||||
up_last,
|
||||
|
||||
"\t%x\t%b\t%b\t%b",
|
||||
down_data,
|
||||
down_valid,
|
||||
down_ready,
|
||||
down_last,
|
||||
|
||||
);
|
||||
|
||||
endtask // display_signals
|
||||
|
||||
task display_header;
|
||||
$display(
|
||||
"\t\ttime\trst",
|
||||
|
||||
"\tu_d",
|
||||
"\tu_v",
|
||||
"\tu_r",
|
||||
"\tu_l",
|
||||
|
||||
"\td_d",
|
||||
"\td_v",
|
||||
"\td_r",
|
||||
"\td_l",
|
||||
|
||||
);
|
||||
endtask
|
||||
|
||||
|
||||
/**
|
||||
* Testbench program
|
||||
*/
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (up_ready) begin
|
||||
cnt <= cnt + 1;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
up_data <= stream[cnt];
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
up_valid <= 1'b0;
|
||||
|
||||
if (up_ready) begin
|
||||
up_valid <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
initial begin
|
||||
// init values
|
||||
clk = 0;
|
||||
rst = 0;
|
||||
|
||||
up_last = 'b0;
|
||||
|
||||
down_ready = 'b0;
|
||||
|
||||
cnt = 0;
|
||||
repeat (STREAM_LENGTH) begin
|
||||
stream[cnt] = cnt + 1;
|
||||
cnt = cnt + 1;
|
||||
end
|
||||
cnt = 0;
|
||||
//end init
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("RESET");
|
||||
`endif
|
||||
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b1;
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b0;
|
||||
repeat(6) @(negedge clk);
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test continuous ready");
|
||||
`endif
|
||||
|
||||
down_ready <= 1'b1;
|
||||
repeat(20) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test non-continuous ready");
|
||||
`endif
|
||||
|
||||
down_ready <= 1'b1;
|
||||
repeat(20) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test continuous ready with unalined last");
|
||||
`endif
|
||||
|
||||
cnt <= 0;
|
||||
repeat(3) @(negedge clk);
|
||||
|
||||
down_ready <= 1'b1;
|
||||
//repeat(15) @(negedge clk);
|
||||
repeat(16) @(negedge clk);
|
||||
//repeat(17) @(negedge clk);
|
||||
//repeat(18) @(negedge clk);
|
||||
up_last <= 1'b1;
|
||||
@(negedge clk);
|
||||
up_last <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("END");
|
||||
`endif
|
||||
-> end_trigger;
|
||||
end
|
||||
|
||||
endmodule
|
252
hdl/axis/axis_read.v
Normal file
252
hdl/axis/axis_read.v
Normal file
@ -0,0 +1,252 @@
|
||||
/**
|
||||
* Module:
|
||||
* axis_read
|
||||
*
|
||||
* Description:
|
||||
* The axis_read is configured to read an area of memory and then converts
|
||||
* the large words that are returned by the AXI into a system stream.
|
||||
*
|
||||
* Test bench:
|
||||
* axis_write_tb.v
|
||||
*
|
||||
* Created:
|
||||
* Fri Nov 7 17:23:00 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_read_ `define _axis_read_
|
||||
|
||||
|
||||
`include "axis_addr.v"
|
||||
`include "axis_read_data.v"
|
||||
|
||||
module axis_read
|
||||
#(parameter
|
||||
BUF_AWIDTH = 9,
|
||||
|
||||
CONFIG_ID = 1,
|
||||
CONFIG_ADDR = 23,
|
||||
CONFIG_DATA = 24,
|
||||
CONFIG_AWIDTH = 5,
|
||||
CONFIG_DWIDTH = 32,
|
||||
|
||||
AXI_LEN_WIDTH = 8,
|
||||
AXI_ADDR_WIDTH = 32,
|
||||
AXI_DATA_WIDTH = 32,
|
||||
DATA_WIDTH = 32)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
input [CONFIG_AWIDTH-1:0] cfg_addr,
|
||||
input [CONFIG_DWIDTH-1:0] cfg_data,
|
||||
input cfg_valid,
|
||||
|
||||
input axi_arready,
|
||||
output [AXI_ADDR_WIDTH-1:0] axi_araddr,
|
||||
output [AXI_LEN_WIDTH-1:0] axi_arlen,
|
||||
output axi_arvalid,
|
||||
|
||||
input [1:0] axi_rresp,
|
||||
input axi_rlast,
|
||||
input [AXI_DATA_WIDTH-1:0] axi_rdata,
|
||||
input axi_rvalid,
|
||||
output axi_rready,
|
||||
|
||||
output [DATA_WIDTH-1:0] data,
|
||||
output valid,
|
||||
input ready
|
||||
);
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam WIDTH_RATIO = AXI_DATA_WIDTH/DATA_WIDTH;
|
||||
localparam CONFIG_NB = 2;
|
||||
|
||||
localparam
|
||||
C_IDLE = 0,
|
||||
C_CONFIG = 1,
|
||||
C_WAIT = 2,
|
||||
C_ENABLE = 3;
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
initial $display("\using 'axis_read'\n");
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* Internal signals
|
||||
*/
|
||||
|
||||
|
||||
reg [3:0] c_state;
|
||||
reg [3:0] c_state_nx;
|
||||
|
||||
wire cfg_addr_ready;
|
||||
wire cfg_data_ready;
|
||||
|
||||
reg [CONFIG_AWIDTH-1:0] cfg_addr_r;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_data_r;
|
||||
reg cfg_valid_r;
|
||||
reg [CONFIG_DWIDTH*CONFIG_NB-1:0] cfg_store;
|
||||
reg [7:0] cfg_cnt;
|
||||
|
||||
wire [CONFIG_DWIDTH-1:0] start_addr;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_address;
|
||||
wire [CONFIG_DWIDTH-1:0] str_length;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_length;
|
||||
reg cfg_enable;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign start_addr = cfg_store[CONFIG_DWIDTH +: CONFIG_DWIDTH];
|
||||
|
||||
assign str_length = cfg_store[0 +: CONFIG_DWIDTH];
|
||||
|
||||
assign id_valid = (CONFIG_ID == cfg_data_r);
|
||||
|
||||
assign addressed = (CONFIG_ADDR == cfg_addr_r) & cfg_valid_r;
|
||||
|
||||
assign axis_data = (CONFIG_DATA == cfg_addr_r) & cfg_valid_r;
|
||||
|
||||
|
||||
// register for improved timing
|
||||
always @(posedge clk)
|
||||
if (rst) cfg_valid_r <= 1'b0;
|
||||
else cfg_valid_r <= cfg_valid;
|
||||
|
||||
|
||||
// register for improved timing
|
||||
always @(posedge clk) begin
|
||||
cfg_addr_r <= cfg_addr;
|
||||
cfg_data_r <= cfg_data;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (c_state[C_CONFIG] & axis_data) begin
|
||||
cfg_store <= {cfg_store, cfg_data_r};
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
cfg_cnt <= 'b0;
|
||||
|
||||
if (c_state[C_CONFIG]) begin
|
||||
cfg_cnt <= cfg_cnt + axis_data;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) cfg_enable <= 1'b0;
|
||||
else cfg_enable <= c_state[C_ENABLE];
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (c_state[C_ENABLE]) begin
|
||||
cfg_address <= start_addr;
|
||||
cfg_length <= str_length;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) begin
|
||||
c_state <= 'b0;
|
||||
c_state[C_IDLE] <= 1'b1;
|
||||
end
|
||||
else c_state <= c_state_nx;
|
||||
|
||||
|
||||
always @* begin : CONFIG_
|
||||
c_state_nx = 'b0;
|
||||
|
||||
case (1'b1)
|
||||
c_state[C_IDLE] : begin
|
||||
if (addressed & id_valid) begin
|
||||
c_state_nx[C_CONFIG] = 1'b1;
|
||||
end
|
||||
else c_state_nx[C_IDLE] = 1'b1;
|
||||
end
|
||||
c_state[C_CONFIG] : begin
|
||||
if (axis_data & ((CONFIG_NB-1) <= cfg_cnt)) begin
|
||||
c_state_nx[C_WAIT] = 1'b1;
|
||||
end
|
||||
else c_state_nx[C_CONFIG] = 1'b1;
|
||||
end
|
||||
c_state[C_WAIT] : begin
|
||||
if (cfg_addr_ready & cfg_data_ready) begin
|
||||
c_state_nx[C_ENABLE] = 1'b1;
|
||||
end
|
||||
else c_state_nx[C_WAIT] = 1'b1;
|
||||
end
|
||||
c_state[C_ENABLE] : begin
|
||||
c_state_nx[C_IDLE] = 1'b1;
|
||||
end
|
||||
default : begin
|
||||
c_state_nx[C_IDLE] = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
axis_addr #(
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
.CONVERT_SHIFT ($clog2(WIDTH_RATIO)),
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH))
|
||||
axis_addr_ (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.cfg_address (cfg_address),
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_enable),
|
||||
.cfg_ready (cfg_addr_ready),
|
||||
|
||||
.axi_aready (axi_arready),
|
||||
.axi_aaddr (axi_araddr),
|
||||
.axi_alen (axi_arlen),
|
||||
.axi_avalid (axi_arvalid)
|
||||
);
|
||||
|
||||
|
||||
axis_read_data #(
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
axis_read_data_ (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_enable),
|
||||
.cfg_ready (cfg_data_ready),
|
||||
|
||||
.axi_rresp (axi_rresp),
|
||||
.axi_rlast (axi_rlast),
|
||||
.axi_rdata (axi_rdata),
|
||||
.axi_rvalid (axi_rvalid),
|
||||
.axi_rready (axi_rready),
|
||||
|
||||
.data (data),
|
||||
.valid (valid),
|
||||
.ready (ready)
|
||||
);
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _axis_read_
|
184
hdl/axis/axis_read_data.v
Normal file
184
hdl/axis/axis_read_data.v
Normal file
@ -0,0 +1,184 @@
|
||||
/**
|
||||
* Module:
|
||||
* axis_read_data
|
||||
*
|
||||
* Description:
|
||||
* The axis_read_data handles the AXI read data channel.
|
||||
*
|
||||
* Testbench:
|
||||
* axis_read_data_tb.v
|
||||
*
|
||||
* Created:
|
||||
* Tue Nov 4 22:18:14 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_read_data_ `define _axis_read_data_
|
||||
|
||||
|
||||
`include "fifo_simple.v"
|
||||
`include "axis_serializer.v"
|
||||
|
||||
module axis_read_data
|
||||
#(parameter
|
||||
BUF_AWIDTH = 9,
|
||||
CONFIG_DWIDTH = 32,
|
||||
WIDTH_RATIO = 16,
|
||||
|
||||
AXI_DATA_WIDTH = 32,
|
||||
DATA_WIDTH = 32)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
input [CONFIG_DWIDTH-1:0] cfg_length,
|
||||
input cfg_valid,
|
||||
output cfg_ready,
|
||||
|
||||
input [1:0] axi_rresp,
|
||||
input axi_rlast,
|
||||
input [AXI_DATA_WIDTH-1:0] axi_rdata,
|
||||
input axi_rvalid,
|
||||
output axi_rready,
|
||||
|
||||
output [DATA_WIDTH-1:0] data,
|
||||
output reg valid,
|
||||
input ready
|
||||
);
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam
|
||||
IDLE = 0,
|
||||
ACTIVE = 1,
|
||||
WAIT = 2,
|
||||
DONE = 3;
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
initial $display("\using 'axis_read_data'\n");
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* Internal signals
|
||||
*/
|
||||
|
||||
reg [3:0] state;
|
||||
reg [3:0] state_nx;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] str_cnt;
|
||||
reg [CONFIG_DWIDTH-1:0] str_length;
|
||||
|
||||
wire buf_pop;
|
||||
wire buf_full;
|
||||
wire buf_empty;
|
||||
wire [DATA_WIDTH-1:0] buf_data;
|
||||
wire buf_valid;
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign cfg_ready = state[IDLE];
|
||||
|
||||
assign buf_pop = ~buf_empty & ready;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (cfg_valid) begin
|
||||
str_length <= cfg_length-1;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (state[IDLE]) str_cnt <= 'b0;
|
||||
else str_cnt <= str_cnt + buf_pop;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) valid <= 1'b0;
|
||||
else valid <= buf_pop & state[ACTIVE];
|
||||
|
||||
|
||||
fifo_simple #(
|
||||
.DATA_WIDTH (DATA_WIDTH),
|
||||
.ADDR_WIDTH (BUF_AWIDTH))
|
||||
buffer_ (
|
||||
.clk (clk),
|
||||
.rst (state[IDLE]),
|
||||
|
||||
.count (),
|
||||
.empty (buf_empty),
|
||||
.empty_a (),
|
||||
.full (buf_full),
|
||||
.full_a (),
|
||||
|
||||
.push_data (buf_data),
|
||||
.push (buf_valid),
|
||||
|
||||
.pop_data (data),
|
||||
.pop (buf_pop)
|
||||
);
|
||||
|
||||
|
||||
axis_serializer #(
|
||||
.DATA_NB (WIDTH_RATIO),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
serializer_ (
|
||||
.clk (clk),
|
||||
.rst (state[IDLE]),
|
||||
|
||||
.up_data (axi_rdata),
|
||||
.up_valid (axi_rvalid),
|
||||
.up_ready (axi_rready),
|
||||
|
||||
.down_data (buf_data),
|
||||
.down_valid (buf_valid),
|
||||
.down_ready ( ~buf_full)
|
||||
);
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) begin
|
||||
state <= 'b0;
|
||||
state[IDLE] <= 1'b1;
|
||||
end
|
||||
else state <= state_nx;
|
||||
|
||||
|
||||
always @* begin : DATA_
|
||||
state_nx <= 'b0;
|
||||
|
||||
case (1'b1)
|
||||
state[IDLE] : begin
|
||||
if (cfg_valid) begin
|
||||
state_nx[ACTIVE] <= 1'b1;
|
||||
end
|
||||
else state_nx[IDLE] <= 1'b1;
|
||||
end
|
||||
state[ACTIVE] : begin
|
||||
if (buf_pop & (str_length == str_cnt)) begin
|
||||
state_nx[WAIT] <= 1'b1;
|
||||
end
|
||||
else state_nx[ACTIVE] <= 1'b1;
|
||||
end
|
||||
state[WAIT] : begin
|
||||
state_nx[DONE] <= 1'b1;
|
||||
end
|
||||
state[DONE] : begin
|
||||
state_nx[IDLE] <= 1'b1;
|
||||
end
|
||||
default : begin
|
||||
state_nx[IDLE] <= 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _axis_read_data_
|
240
hdl/axis/axis_read_data_tb.v
Normal file
240
hdl/axis/axis_read_data_tb.v
Normal file
@ -0,0 +1,240 @@
|
||||
/**
|
||||
* Testbench:
|
||||
* axis_read_data
|
||||
*
|
||||
* Created:
|
||||
* Tue Nov 4 22:17:15 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
|
||||
`timescale 1ns/10ps
|
||||
|
||||
`define TB_VERBOSE
|
||||
//`define VERBOSE
|
||||
|
||||
|
||||
`include "axis_read_data.v"
|
||||
|
||||
module axis_read_data_tb;
|
||||
|
||||
/**
|
||||
* Clock and control functions
|
||||
*/
|
||||
|
||||
// Generate a clk
|
||||
reg clk;
|
||||
always #1 clk = !clk;
|
||||
|
||||
// End of simulation event definition
|
||||
event end_trigger;
|
||||
always @(end_trigger) $finish;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
// Display header information
|
||||
initial #1 display_header();
|
||||
always @(end_trigger) display_header();
|
||||
|
||||
// And strobe signals at each clk
|
||||
always @(posedge clk) display_signals();
|
||||
`endif
|
||||
|
||||
// initial begin
|
||||
// $dumpfile("result.vcd"); // Waveform file
|
||||
// $dumpvars;
|
||||
// end
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam STREAM_LENGTH = (256*8*2)-4;
|
||||
|
||||
localparam BUF_AWIDTH = 4;
|
||||
localparam CONFIG_DWIDTH = 32;
|
||||
localparam WIDTH_RATIO = 8;
|
||||
localparam AXI_DATA_WIDTH = 256;
|
||||
localparam DATA_WIDTH = 32;
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
initial $display("Testbench for unit 'axis_read_data'");
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* signals, registers and wires
|
||||
*/
|
||||
|
||||
reg rst;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_length;
|
||||
reg cfg_valid;
|
||||
wire cfg_ready;
|
||||
|
||||
reg axi_rresp;
|
||||
reg axi_rlast;
|
||||
reg [AXI_DATA_WIDTH-1:0] axi_rdata;
|
||||
reg axi_rvalid;
|
||||
wire axi_rready;
|
||||
|
||||
wire [DATA_WIDTH-1:0] data;
|
||||
wire valid;
|
||||
reg ready;
|
||||
|
||||
|
||||
/**
|
||||
* Unit under test
|
||||
*/
|
||||
|
||||
axis_read_data #(
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
uut (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_valid),
|
||||
.cfg_ready (cfg_ready),
|
||||
|
||||
.axi_rresp (axi_rresp),
|
||||
.axi_rlast (axi_rlast),
|
||||
.axi_rdata (axi_rdata),
|
||||
.axi_rvalid (axi_rvalid),
|
||||
.axi_rready (axi_rready),
|
||||
|
||||
.data (data),
|
||||
.valid (valid),
|
||||
.ready (ready)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Wave form display
|
||||
*/
|
||||
|
||||
task display_signals;
|
||||
$display(
|
||||
"%d\t%d",
|
||||
$time, rst,
|
||||
|
||||
"\t%d\t%b",
|
||||
cfg_length,
|
||||
cfg_valid,
|
||||
cfg_ready,
|
||||
|
||||
"\t%x\t%b\t%b",
|
||||
axi_rdata,
|
||||
axi_rvalid,
|
||||
axi_rready,
|
||||
|
||||
"\t%x\t%b\t%b",
|
||||
data,
|
||||
valid,
|
||||
ready,
|
||||
|
||||
"\t%b",
|
||||
uut.state,
|
||||
|
||||
);
|
||||
|
||||
endtask // display_signals
|
||||
|
||||
task display_header;
|
||||
$display(
|
||||
"\t\ttime\trst",
|
||||
|
||||
"\t\tc_l",
|
||||
"\tc_v",
|
||||
"\tc_r",
|
||||
|
||||
"\t\t\t\t\t\tr_d",
|
||||
"\t\t\tr_v",
|
||||
"\tr_r",
|
||||
|
||||
"\t\ts_d",
|
||||
"\ts_v",
|
||||
"\ts_r",
|
||||
|
||||
);
|
||||
endtask
|
||||
|
||||
|
||||
/**
|
||||
* Testbench program
|
||||
*/
|
||||
|
||||
initial begin
|
||||
// init values
|
||||
clk = 0;
|
||||
rst = 0;
|
||||
|
||||
cfg_length = 'b0;
|
||||
cfg_valid = 'b0;
|
||||
|
||||
axi_rresp = 'b0;
|
||||
axi_rlast = 'b0;
|
||||
axi_rdata = 'b0;
|
||||
axi_rvalid = 'b0;
|
||||
|
||||
ready = 'b0;
|
||||
//end init
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("RESET");
|
||||
`endif
|
||||
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b1;
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b0;
|
||||
@(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("send config id, start address and length");
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_length <= 10;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_length <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test read");
|
||||
`endif
|
||||
|
||||
ready <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
axi_rdata <= {32'd8, 32'd7, 32'd6, 32'd5, 32'd4, 32'd3, 32'd2, 32'd1};
|
||||
axi_rvalid <= 1'b1;
|
||||
@(negedge clk);
|
||||
axi_rdata <= {32'd9, 32'd8, 32'd7, 32'd6, 32'd5, 32'd4, 32'd3, 32'd2};
|
||||
while ( ~axi_rready) @(negedge clk);
|
||||
axi_rvalid <= 1'b1;
|
||||
@(negedge clk);
|
||||
axi_rdata <= 'b0;
|
||||
axi_rvalid <= 1'b0;
|
||||
|
||||
repeat(15) @(negedge clk);
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("END");
|
||||
`endif
|
||||
-> end_trigger;
|
||||
end
|
||||
|
||||
endmodule
|
439
hdl/axis/axis_read_tb.v
Normal file
439
hdl/axis/axis_read_tb.v
Normal file
@ -0,0 +1,439 @@
|
||||
/**
|
||||
* Testbench:
|
||||
* axis_read
|
||||
*
|
||||
* Created:
|
||||
* Fri Nov 7 17:22:50 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
|
||||
`timescale 1ns/10ps
|
||||
|
||||
`define TB_VERBOSE
|
||||
//`define VERBOSE
|
||||
|
||||
|
||||
`include "axis_read.v"
|
||||
|
||||
module axis_read_tb;
|
||||
|
||||
/**
|
||||
* Clock and control functions
|
||||
*/
|
||||
|
||||
// Generate a clk
|
||||
reg clk;
|
||||
always #1 clk = !clk;
|
||||
|
||||
// End of simulation event definition
|
||||
event end_trigger;
|
||||
always @(end_trigger) $finish;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
// Display header information
|
||||
initial #1 display_header();
|
||||
always @(end_trigger) display_header();
|
||||
|
||||
// And strobe signals at each clk
|
||||
always @(posedge clk) display_signals();
|
||||
`endif
|
||||
|
||||
// initial begin
|
||||
// $dumpfile("result.vcd"); // Waveform file
|
||||
// $dumpvars;
|
||||
// end
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam STREAM_LENGTH = (256*8*2)-4;
|
||||
|
||||
localparam BUF_AWIDTH = 4;
|
||||
|
||||
localparam CONFIG_ID = 1;
|
||||
localparam CONFIG_ADDR = 23;
|
||||
localparam CONFIG_DATA = 24;
|
||||
localparam CONFIG_AWIDTH = 5;
|
||||
localparam CONFIG_DWIDTH = 32;
|
||||
|
||||
localparam AXI_ID_WIDTH = 8;
|
||||
localparam AXI_ADDR_WIDTH = 32;
|
||||
localparam AXI_DATA_WIDTH = 256;
|
||||
localparam DATA_WIDTH = 32;
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
initial $display("Testbench for unit 'axis_read'");
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* signals, registers and wires
|
||||
*/
|
||||
|
||||
reg rst;
|
||||
|
||||
reg [CONFIG_AWIDTH-1:0] cfg_addr;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_data;
|
||||
reg cfg_valid;
|
||||
|
||||
reg axi_arready;
|
||||
wire [AXI_ID_WIDTH-1:0] axi_arid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] axi_araddr;
|
||||
wire [7:0] axi_arlen;
|
||||
wire axi_arvalid;
|
||||
|
||||
reg [AXI_DATA_WIDTH-1:0] axi_rdata;
|
||||
reg axi_rvalid;
|
||||
wire axi_rready;
|
||||
|
||||
wire [DATA_WIDTH-1:0] data;
|
||||
wire valid;
|
||||
reg ready;
|
||||
|
||||
|
||||
/**
|
||||
* Unit under test
|
||||
*/
|
||||
|
||||
axis_read #(
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
|
||||
.CONFIG_ID (CONFIG_ID),
|
||||
.CONFIG_ADDR (CONFIG_ADDR),
|
||||
.CONFIG_DATA (CONFIG_DATA),
|
||||
.CONFIG_AWIDTH (CONFIG_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
|
||||
.AXI_ID_WIDTH (AXI_ID_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
uut (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.cfg_addr (cfg_addr),
|
||||
.cfg_data (cfg_data),
|
||||
.cfg_valid (cfg_valid),
|
||||
|
||||
.axi_arready (axi_arready),
|
||||
.axi_arid (axi_arid),
|
||||
.axi_araddr (axi_araddr),
|
||||
.axi_arlen (axi_arlen),
|
||||
.axi_arvalid (axi_arvalid),
|
||||
|
||||
.axi_rresp (),
|
||||
.axi_rlast (),
|
||||
.axi_rdata (axi_rdata),
|
||||
.axi_rvalid (axi_rvalid),
|
||||
.axi_rready (axi_rready),
|
||||
|
||||
.data (data),
|
||||
.valid (valid),
|
||||
.ready (ready)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Wave form display
|
||||
*/
|
||||
|
||||
task display_signals;
|
||||
$display(
|
||||
"%d\t%d",
|
||||
$time, rst,
|
||||
|
||||
"\t%d\t%d\t%b",
|
||||
cfg_addr,
|
||||
cfg_data,
|
||||
cfg_valid,
|
||||
|
||||
"\t%d\t%d\t%d\t%b\t%b",
|
||||
axi_arid,
|
||||
axi_araddr,
|
||||
axi_arlen,
|
||||
axi_arvalid,
|
||||
axi_arready,
|
||||
|
||||
"\t%x\t%b\t%b",
|
||||
axi_rdata,
|
||||
axi_rvalid,
|
||||
axi_rready,
|
||||
|
||||
"\t%d\t%b\t%b",
|
||||
data,
|
||||
valid,
|
||||
ready,
|
||||
|
||||
"\t%b",
|
||||
uut.c_state,
|
||||
|
||||
"\t%b",
|
||||
uut.axis_addr_.state,
|
||||
|
||||
);
|
||||
|
||||
endtask // display_signals
|
||||
|
||||
task display_header;
|
||||
$display(
|
||||
"\t\ttime\trst",
|
||||
|
||||
"\tc_a",
|
||||
"\t\tc_d",
|
||||
"\tc_v",
|
||||
|
||||
"\tar_id",
|
||||
"\t\tar_a",
|
||||
"\tar_l",
|
||||
"\tar_v",
|
||||
"\tar_r",
|
||||
|
||||
"\t\t\t\t\t\tr_d",
|
||||
"\t\t\t\tr_v",
|
||||
"\tr_r",
|
||||
|
||||
"\t\ts_d",
|
||||
"\ts_v",
|
||||
"\tm_r",
|
||||
|
||||
);
|
||||
endtask
|
||||
|
||||
|
||||
/**
|
||||
* Testbench program
|
||||
*/
|
||||
|
||||
initial begin
|
||||
// init values
|
||||
clk = 0;
|
||||
rst = 0;
|
||||
|
||||
cfg_addr = 'b0;
|
||||
cfg_data = 'b0;
|
||||
cfg_valid = 'b0;
|
||||
|
||||
axi_arready = 'b0;
|
||||
|
||||
axi_rdata = 'b0;
|
||||
axi_rvalid = 'b0;
|
||||
|
||||
ready = 'b0;
|
||||
//end init
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("RESET");
|
||||
`endif
|
||||
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b1;
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b0;
|
||||
@(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("send config id, start address and length");
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_addr <= CONFIG_ADDR;
|
||||
cfg_data <= CONFIG_ID;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= 'b0;
|
||||
cfg_data <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
// memory address
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_data <= 4;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= 'b0;
|
||||
cfg_data <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
// length of flow stream
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_data <= 8;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= 'b0;
|
||||
cfg_data <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test read address channel");
|
||||
`endif
|
||||
|
||||
repeat(3) @(negedge clk);
|
||||
axi_arready <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
axi_arready <= 1'b0;
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test read data channel");
|
||||
`endif
|
||||
|
||||
@(negedge clk);
|
||||
|
||||
ready <= 1'b1;
|
||||
axi_rdata <= 'b0;
|
||||
axi_rvalid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
axi_rdata <= {32'd8, 32'd7, 32'd6, 32'd5, 32'd4, 32'd3, 32'd2, 32'd1};
|
||||
axi_rvalid <= 1'b1;
|
||||
@(negedge clk);
|
||||
|
||||
axi_rvalid <= 1'b0;
|
||||
repeat(15) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("send config id, start address and length");
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_addr <= CONFIG_ADDR;
|
||||
cfg_data <= CONFIG_ID;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_data <= 4;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_data <= 20;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= 'b0;
|
||||
cfg_data <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test read address channel");
|
||||
`endif
|
||||
|
||||
repeat(3) @(negedge clk);
|
||||
axi_arready <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test read data channel");
|
||||
`endif
|
||||
|
||||
|
||||
@(negedge clk);
|
||||
|
||||
ready <= 1'b1;
|
||||
axi_rdata <= 'b0;
|
||||
axi_rvalid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
axi_rdata <= {32'd8, 32'd7, 32'd6, 32'd5, 32'd4, 32'd3, 32'd2, 32'd1};
|
||||
axi_rvalid <= 1'b1;
|
||||
@(negedge clk);
|
||||
axi_rdata <= {32'd16, 32'd15, 32'd14, 32'd13, 32'd12, 32'd11, 32'd10, 32'd9};
|
||||
while ( ~axi_rready) @(negedge clk);
|
||||
axi_rvalid <= 1'b1;
|
||||
@(negedge clk);
|
||||
axi_rdata <= {32'd24, 32'd23, 32'd22, 32'd21, 32'd20, 32'd19, 32'd18, 32'd17};
|
||||
while ( ~axi_rready) @(negedge clk);
|
||||
axi_rvalid <= 1'b1;
|
||||
@(negedge clk);
|
||||
axi_rdata <= 'b0;
|
||||
axi_rvalid <= 1'b0;
|
||||
|
||||
axi_rvalid <= 1'b0;
|
||||
repeat(15) @(negedge clk);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("send config id, start address and length");
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_addr <= CONFIG_ADDR;
|
||||
cfg_data <= CONFIG_ID;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_data <= 255;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_data <= STREAM_LENGTH;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= 'b0;
|
||||
cfg_data <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test long read");
|
||||
`endif
|
||||
|
||||
repeat(3) @(negedge clk);
|
||||
// ready to recive address
|
||||
axi_arready <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
// ready to recive data
|
||||
axi_rready <= 1'b1;
|
||||
data <= 'b0;
|
||||
valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
repeat (STREAM_LENGTH) begin
|
||||
// stream data into axis
|
||||
data <= data + 1;
|
||||
valid <= 1'b1;
|
||||
@(negedge clk);
|
||||
end
|
||||
|
||||
valid <= 1'b0;
|
||||
repeat(15) @(negedge clk);
|
||||
axi_rready <= 1'b0;
|
||||
repeat(15) @(negedge clk);
|
||||
*/
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("END");
|
||||
`endif
|
||||
-> end_trigger;
|
||||
end
|
||||
|
||||
endmodule
|
117
hdl/axis/axis_serializer.v
Normal file
117
hdl/axis/axis_serializer.v
Normal file
@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Module:
|
||||
* axis_serializer
|
||||
*
|
||||
* Description:
|
||||
* Serializes the 'up' flow bus data word into multiple smaller 'down' data
|
||||
* words. The module will stall when the down_ready flag deasserts.
|
||||
*
|
||||
* Testbench:
|
||||
* axis_serializer_tb.v
|
||||
*
|
||||
* Created:
|
||||
* Fri Nov 7 11:50:04 EST 2014
|
||||
*
|
||||
* Authors:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_serializer_ `define _axis_serializer_
|
||||
|
||||
|
||||
module axis_serializer
|
||||
#(parameter
|
||||
DATA_NB = 2,
|
||||
DATA_WIDTH = 8)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
output up_ready,
|
||||
input up_valid,
|
||||
input [(DATA_WIDTH*DATA_NB)-1:0] up_data,
|
||||
|
||||
input down_ready,
|
||||
output reg down_valid,
|
||||
output reg [DATA_WIDTH-1:0] down_data
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
initial $display("\using 'axis_serializer' with %0d words\n", DATA_NB);
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* Internal signals
|
||||
*/
|
||||
|
||||
wire [2*DATA_NB-1:0] token_nx;
|
||||
reg [DATA_NB-1:0] token;
|
||||
reg [DATA_NB-1:0] serial_valid;
|
||||
reg [(DATA_WIDTH*DATA_NB)-1:0] serial_data;
|
||||
wire serial_start;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign up_ready = down_ready & token[0];
|
||||
|
||||
assign serial_start = |(token >> 1);
|
||||
|
||||
assign token_nx = {token, token};
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) token <= 'b1;
|
||||
else if (down_ready) begin
|
||||
|
||||
if (serial_start | (up_ready & up_valid)) begin
|
||||
token <= token_nx[DATA_NB-1 +: DATA_NB];
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (down_ready) begin
|
||||
|
||||
serial_data <= serial_data >> DATA_WIDTH;
|
||||
if (up_ready & up_valid) begin
|
||||
serial_data <= up_data;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) serial_valid <= 'b0;
|
||||
else if (down_ready) begin
|
||||
|
||||
serial_valid <= {serial_valid[0 +: DATA_NB-1], 1'b0};
|
||||
if (up_ready & up_valid) begin
|
||||
serial_valid <= {serial_valid[0 +: DATA_NB-1], 1'b1};
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (down_ready) begin
|
||||
down_data <= serial_data[0 +: DATA_WIDTH];
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) down_valid <= 1'b0;
|
||||
else if (down_ready) begin
|
||||
down_valid <= |(serial_valid);
|
||||
end
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _axis_serializer_
|
243
hdl/axis/axis_serializer_tb.v
Normal file
243
hdl/axis/axis_serializer_tb.v
Normal file
@ -0,0 +1,243 @@
|
||||
/**
|
||||
* Testbench for:
|
||||
* axis_serializer
|
||||
*
|
||||
* Created:
|
||||
* Fri Nov 7 11:49:55 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
|
||||
`timescale 1ns/10ps
|
||||
|
||||
`define TB_VERBOSE
|
||||
//`define VERBOSE
|
||||
|
||||
|
||||
`include "axis_serializer.v"
|
||||
|
||||
module axis_serializer_tb;
|
||||
|
||||
/**
|
||||
* Clock and control functions
|
||||
*/
|
||||
|
||||
// Generate a clk
|
||||
reg clk;
|
||||
always #1 clk = !clk;
|
||||
|
||||
// End of simulation event definition
|
||||
event end_trigger;
|
||||
always @(end_trigger) $finish;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
// Display header information
|
||||
initial #1 display_header();
|
||||
always @(end_trigger) display_header();
|
||||
|
||||
// And strobe signals at each clk
|
||||
always @(posedge clk) display_signals();
|
||||
`endif
|
||||
|
||||
// initial begin
|
||||
// $dumpfile("result.vcd"); // Waveform file
|
||||
// $dumpvars;
|
||||
// end
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam DATA_NB = 3;
|
||||
localparam DATA_WIDTH = 8;
|
||||
|
||||
localparam STREAM_LENGTH = 256;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
initial begin
|
||||
$display("Testbench for unit 'axis_serializer' data width: %d, nb: %d",
|
||||
DATA_WIDTH, DATA_NB);
|
||||
end
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* signals, registers and wires
|
||||
*/
|
||||
|
||||
reg rst;
|
||||
|
||||
reg [DATA_NB*DATA_WIDTH-1:0] up_data;
|
||||
wire up_valid;
|
||||
wire up_ready;
|
||||
|
||||
wire [DATA_WIDTH-1:0] down_data;
|
||||
wire down_valid;
|
||||
reg down_ready;
|
||||
|
||||
reg [DATA_WIDTH-1:0] stream [0:STREAM_LENGTH-1];
|
||||
integer cnt;
|
||||
|
||||
/**
|
||||
* Unit under test
|
||||
*/
|
||||
|
||||
axis_serializer #(
|
||||
.DATA_NB (DATA_NB),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
uut (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.up_data (up_data),
|
||||
.up_valid (up_valid),
|
||||
.up_ready (up_ready),
|
||||
|
||||
.down_data (down_data),
|
||||
.down_valid (down_valid),
|
||||
.down_ready (down_ready)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Wave form display
|
||||
*/
|
||||
|
||||
task display_signals;
|
||||
$display(
|
||||
"%d\t%d",
|
||||
$time, rst,
|
||||
|
||||
"\tu2: %d\tu1: %d\tu0: %d",
|
||||
up_data[2*DATA_WIDTH+:DATA_WIDTH],
|
||||
up_data[1*DATA_WIDTH+:DATA_WIDTH],
|
||||
up_data[0*DATA_WIDTH+:DATA_WIDTH],
|
||||
|
||||
"\tv %b\tr %b",
|
||||
up_valid,
|
||||
up_ready,
|
||||
|
||||
"\t%d\t%b\t%b",
|
||||
down_data,
|
||||
down_valid,
|
||||
down_ready,
|
||||
|
||||
"\t%b",
|
||||
uut.token,
|
||||
|
||||
"\t%x\t%b",
|
||||
uut.serial_data,
|
||||
uut.serial_valid,
|
||||
);
|
||||
|
||||
endtask // display_signals
|
||||
|
||||
task display_header;
|
||||
$display(
|
||||
"\t\ttime\trst",
|
||||
|
||||
"\tu2_d",
|
||||
"\tu1_d",
|
||||
"\tu0_d",
|
||||
|
||||
"\tu_v",
|
||||
"\tu_r",
|
||||
|
||||
"\td_d",
|
||||
"\td_v",
|
||||
"\td_r",
|
||||
|
||||
);
|
||||
endtask
|
||||
|
||||
|
||||
/**
|
||||
* Testbench program
|
||||
*/
|
||||
|
||||
//assign up_valid = up_ready;
|
||||
assign up_valid = 1'b1;
|
||||
|
||||
always @(posedge clk)
|
||||
if (up_ready & up_valid) begin
|
||||
cnt <= cnt + 1;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
up_data <= {stream[cnt]+4'd2, stream[cnt]+4'd1, stream[cnt]};
|
||||
|
||||
|
||||
|
||||
initial begin
|
||||
// init values
|
||||
clk = 0;
|
||||
rst = 0;
|
||||
|
||||
down_ready = 'b0;
|
||||
|
||||
cnt = 0;
|
||||
repeat (STREAM_LENGTH) begin
|
||||
stream[cnt] = (DATA_NB*cnt)+1;
|
||||
cnt = cnt + 1;
|
||||
end
|
||||
cnt = 0;
|
||||
//end init
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("RESET");
|
||||
`endif
|
||||
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b1;
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b0;
|
||||
repeat(6) @(negedge clk);
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test continuous ready");
|
||||
`endif
|
||||
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
repeat(20) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test non-continuous ready");
|
||||
`endif
|
||||
|
||||
down_ready <= 1'b1;
|
||||
repeat(20) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("END");
|
||||
`endif
|
||||
-> end_trigger;
|
||||
end
|
||||
|
||||
endmodule
|
252
hdl/axis/axis_write.v
Normal file
252
hdl/axis/axis_write.v
Normal file
@ -0,0 +1,252 @@
|
||||
/**
|
||||
* Module:
|
||||
* axis_write
|
||||
*
|
||||
* Description:
|
||||
* The axis_write takes a system stream an translate it to the axi data
|
||||
* channel protocol.
|
||||
*
|
||||
* Test bench:
|
||||
* axis_write_tb.v
|
||||
*
|
||||
* Created:
|
||||
* Tue Nov 4 22:18:14 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_write_ `define _axis_write_
|
||||
|
||||
|
||||
`include "axis_addr.v"
|
||||
`include "axis_write_data.v"
|
||||
|
||||
module axis_write
|
||||
#(parameter
|
||||
BUF_AWIDTH = 9,
|
||||
|
||||
CONFIG_ID = 1,
|
||||
CONFIG_ADDR = 23,
|
||||
CONFIG_DATA = 24,
|
||||
CONFIG_AWIDTH = 5,
|
||||
CONFIG_DWIDTH = 32,
|
||||
|
||||
AXI_LEN_WIDTH = 8,
|
||||
AXI_ADDR_WIDTH = 32,
|
||||
AXI_DATA_WIDTH = 32,
|
||||
DATA_WIDTH = 32)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
input [CONFIG_AWIDTH-1:0] cfg_addr,
|
||||
input [CONFIG_DWIDTH-1:0] cfg_data,
|
||||
input cfg_valid,
|
||||
|
||||
input axi_awready,
|
||||
output [AXI_ADDR_WIDTH-1:0] axi_awaddr,
|
||||
output [AXI_LEN_WIDTH-1:0] axi_awlen,
|
||||
output axi_awvalid,
|
||||
|
||||
output axi_wlast,
|
||||
output [AXI_DATA_WIDTH-1:0] axi_wdata,
|
||||
output axi_wvalid,
|
||||
input axi_wready,
|
||||
|
||||
input [DATA_WIDTH-1:0] data,
|
||||
input valid,
|
||||
output ready
|
||||
);
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam WIDTH_RATIO = AXI_DATA_WIDTH/DATA_WIDTH;
|
||||
localparam CONFIG_NB = 2;
|
||||
|
||||
localparam
|
||||
C_IDLE = 0,
|
||||
C_CONFIG = 1,
|
||||
C_WAIT = 2,
|
||||
C_ENABLE = 3;
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
initial $display("\using 'axis_write'\n");
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* Internal signals
|
||||
*/
|
||||
|
||||
|
||||
reg [3:0] c_state;
|
||||
reg [3:0] c_state_nx;
|
||||
|
||||
wire cfg_addr_ready;
|
||||
wire cfg_data_ready;
|
||||
|
||||
reg [CONFIG_AWIDTH-1:0] cfg_addr_r;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_data_r;
|
||||
reg cfg_valid_r;
|
||||
reg [CONFIG_DWIDTH*CONFIG_NB-1:0] cfg_store;
|
||||
reg [7:0] cfg_cnt;
|
||||
|
||||
wire [CONFIG_DWIDTH-1:0] start_addr;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_address;
|
||||
wire [CONFIG_DWIDTH-1:0] str_length;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_length;
|
||||
reg cfg_enable;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign start_addr = cfg_store[CONFIG_DWIDTH +: CONFIG_DWIDTH];
|
||||
|
||||
assign str_length = cfg_store[0 +: CONFIG_DWIDTH];
|
||||
|
||||
assign id_valid = (CONFIG_ID == cfg_data_r);
|
||||
|
||||
assign addressed = (CONFIG_ADDR == cfg_addr_r) & cfg_valid_r;
|
||||
|
||||
assign axis_data = (CONFIG_DATA == cfg_addr_r) & cfg_valid_r;
|
||||
|
||||
|
||||
// register for improved timing
|
||||
always @(posedge clk)
|
||||
if (rst) cfg_valid_r <= 1'b0;
|
||||
else cfg_valid_r <= cfg_valid;
|
||||
|
||||
|
||||
// register for improved timing
|
||||
always @(posedge clk) begin
|
||||
cfg_addr_r <= cfg_addr;
|
||||
cfg_data_r <= cfg_data;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (c_state[C_CONFIG] & axis_data) begin
|
||||
cfg_store <= {cfg_store, cfg_data_r};
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
cfg_cnt <= 'b0;
|
||||
|
||||
if (c_state[C_CONFIG]) begin
|
||||
cfg_cnt <= cfg_cnt + axis_data;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) cfg_enable <= 1'b0;
|
||||
else cfg_enable <= c_state[C_ENABLE];
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (c_state[C_ENABLE]) begin
|
||||
cfg_address <= start_addr;
|
||||
cfg_length <= str_length;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) begin
|
||||
c_state <= 'b0;
|
||||
c_state[C_IDLE] <= 1'b1;
|
||||
end
|
||||
else c_state <= c_state_nx;
|
||||
|
||||
|
||||
always @* begin : CONFIG_
|
||||
c_state_nx = 'b0;
|
||||
|
||||
case (1'b1)
|
||||
c_state[C_IDLE] : begin
|
||||
if (addressed & id_valid) begin
|
||||
c_state_nx[C_CONFIG] = 1'b1;
|
||||
end
|
||||
else c_state_nx[C_IDLE] = 1'b1;
|
||||
end
|
||||
c_state[C_CONFIG] : begin
|
||||
if (axis_data & ((CONFIG_NB-1) <= cfg_cnt)) begin
|
||||
c_state_nx[C_WAIT] = 1'b1;
|
||||
end
|
||||
else c_state_nx[C_CONFIG] = 1'b1;
|
||||
end
|
||||
c_state[C_WAIT] : begin
|
||||
if (cfg_addr_ready & cfg_data_ready) begin
|
||||
c_state_nx[C_ENABLE] = 1'b1;
|
||||
end
|
||||
else c_state_nx[C_WAIT] = 1'b1;
|
||||
end
|
||||
c_state[C_ENABLE] : begin
|
||||
c_state_nx[C_IDLE] = 1'b1;
|
||||
end
|
||||
default : begin
|
||||
c_state_nx[C_IDLE] = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
axis_addr #(
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
.CONVERT_SHIFT ($clog2(WIDTH_RATIO)),
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH))
|
||||
axis_addr_ (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.cfg_address (cfg_address),
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_enable),
|
||||
.cfg_ready (cfg_addr_ready),
|
||||
|
||||
.axi_aready (axi_awready),
|
||||
.axi_aaddr (axi_awaddr),
|
||||
.axi_alen (axi_awlen),
|
||||
.axi_avalid (axi_awvalid)
|
||||
);
|
||||
|
||||
|
||||
axis_write_data #(
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
.CONVERT_SHIFT ($clog2(WIDTH_RATIO)),
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
axis_write_data_ (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_enable),
|
||||
.cfg_ready (cfg_data_ready),
|
||||
|
||||
.axi_wlast (axi_wlast),
|
||||
.axi_wdata (axi_wdata),
|
||||
.axi_wvalid (axi_wvalid),
|
||||
.axi_wready (axi_wready),
|
||||
|
||||
.data (data),
|
||||
.valid (valid),
|
||||
.ready (ready)
|
||||
);
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _axis_write_
|
210
hdl/axis/axis_write_data.v
Normal file
210
hdl/axis/axis_write_data.v
Normal file
@ -0,0 +1,210 @@
|
||||
/**
|
||||
* Module:
|
||||
* axis_write_data
|
||||
*
|
||||
* Description:
|
||||
* The axis_write_data handles the AXI write data channel.
|
||||
*
|
||||
* Test bench:
|
||||
* axis_write_tb.v
|
||||
*
|
||||
* Created:
|
||||
* Tue Nov 4 22:18:14 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_write_data_ `define _axis_write_data_
|
||||
|
||||
|
||||
`include "fifo_simple.v"
|
||||
`include "axis_deserializer.v"
|
||||
|
||||
module axis_write_data
|
||||
#(parameter
|
||||
BUF_AWIDTH = 9,
|
||||
CONFIG_DWIDTH = 32,
|
||||
WIDTH_RATIO = 16,
|
||||
CONVERT_SHIFT = 3,
|
||||
|
||||
AXI_LEN_WIDTH = 8,
|
||||
AXI_DATA_WIDTH = 32,
|
||||
DATA_WIDTH = 32)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
input [CONFIG_DWIDTH-1:0] cfg_length,
|
||||
input cfg_valid,
|
||||
output cfg_ready,
|
||||
|
||||
output axi_wlast,
|
||||
output [AXI_DATA_WIDTH-1:0] axi_wdata,
|
||||
output axi_wvalid,
|
||||
input axi_wready,
|
||||
|
||||
input [DATA_WIDTH-1:0] data,
|
||||
input valid,
|
||||
output reg ready
|
||||
);
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam BURST_WIDTH = AXI_LEN_WIDTH+CONVERT_SHIFT;
|
||||
localparam BURST_LAST = (1<<BURST_WIDTH)-1;
|
||||
|
||||
localparam
|
||||
IDLE = 0,
|
||||
ACTIVE = 1,
|
||||
WAIT = 2,
|
||||
DONE = 3;
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
initial $display("\using 'axis_write_data'\n");
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* Internal signals
|
||||
*/
|
||||
|
||||
reg [3:0] state;
|
||||
reg [3:0] state_nx;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] str_cnt;
|
||||
reg [CONFIG_DWIDTH-1:0] str_length;
|
||||
|
||||
wire [BUF_AWIDTH:0] buf_count;
|
||||
wire buf_pop;
|
||||
wire buf_empty;
|
||||
|
||||
reg deser_last;
|
||||
wire [DATA_WIDTH-1:0] deser_data;
|
||||
reg deser_valid;
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign cfg_ready = state[IDLE];
|
||||
|
||||
assign buf_pop = ~buf_empty & axi_wready;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (cfg_valid) begin
|
||||
str_length <= cfg_length-1;
|
||||
end
|
||||
|
||||
|
||||
// use axi_wready as a stall signal
|
||||
always @(posedge clk)
|
||||
if (state[IDLE]) deser_valid <= 1'b0;
|
||||
else if (axi_wready) deser_valid <= buf_pop;
|
||||
|
||||
|
||||
// half way mark ready flag
|
||||
always @(posedge clk)
|
||||
if (state[IDLE]) ready <= 1'b0;
|
||||
else ready <= ~|(buf_count[BUF_AWIDTH:BUF_AWIDTH-1]);
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (state[IDLE]) str_cnt <= 'b0;
|
||||
else if (axi_wready) str_cnt <= str_cnt + buf_pop;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (state[IDLE]) deser_last <= 1'b0;
|
||||
else if (axi_wready) begin
|
||||
// trigger on last word in stream or last word in burst
|
||||
deser_last <= buf_pop &
|
||||
((str_length == str_cnt) | (BURST_LAST == str_cnt[0 +: BURST_WIDTH]));
|
||||
end
|
||||
|
||||
|
||||
fifo_simple #(
|
||||
.DATA_WIDTH (DATA_WIDTH),
|
||||
.ADDR_WIDTH (BUF_AWIDTH))
|
||||
buffer_ (
|
||||
.clk (clk),
|
||||
.rst (state[IDLE]),
|
||||
|
||||
.count (buf_count),
|
||||
.empty (buf_empty),
|
||||
.empty_a (),
|
||||
.full (),
|
||||
.full_a (),
|
||||
|
||||
.push_data (data),
|
||||
.push (valid),
|
||||
|
||||
.pop_data (deser_data),
|
||||
.pop (buf_pop)
|
||||
);
|
||||
|
||||
|
||||
axis_deserializer #(
|
||||
.DATA_NB (WIDTH_RATIO),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
deser_ (
|
||||
.clk (clk),
|
||||
.rst (state[IDLE]),
|
||||
|
||||
.up_data (deser_data),
|
||||
.up_valid (deser_valid),
|
||||
.up_ready (),
|
||||
.up_last (deser_last),
|
||||
|
||||
.down_data (axi_wdata),
|
||||
.down_valid (axi_wvalid),
|
||||
.down_ready (axi_wready),
|
||||
.down_last (axi_wlast)
|
||||
);
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) begin
|
||||
state <= 'b0;
|
||||
state[IDLE] <= 1'b1;
|
||||
end
|
||||
else state <= state_nx;
|
||||
|
||||
|
||||
always @* begin : DATA_
|
||||
state_nx <= 'b0;
|
||||
|
||||
case (1'b1)
|
||||
state[IDLE] : begin
|
||||
if (cfg_valid) begin
|
||||
state_nx[ACTIVE] <= 1'b1;
|
||||
end
|
||||
else state_nx[IDLE] <= 1'b1;
|
||||
end
|
||||
state[ACTIVE] : begin
|
||||
if (axi_wready & buf_pop & (str_length == str_cnt)) begin
|
||||
state_nx[WAIT] <= 1'b1;
|
||||
end
|
||||
else state_nx[ACTIVE] <= 1'b1;
|
||||
end
|
||||
state[WAIT] : begin
|
||||
if (axi_wready & axi_wlast) begin
|
||||
state_nx[DONE] <= 1'b1;
|
||||
end
|
||||
else state_nx[WAIT] <= 1'b1;
|
||||
end
|
||||
state[DONE] : begin
|
||||
state_nx[IDLE] <= 1'b1;
|
||||
end
|
||||
default : begin
|
||||
state_nx[IDLE] <= 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _axis_write_data_
|
377
hdl/axis/axis_write_data_tb.v
Normal file
377
hdl/axis/axis_write_data_tb.v
Normal file
@ -0,0 +1,377 @@
|
||||
/**
|
||||
* Testbench:
|
||||
* axis_write_data
|
||||
*
|
||||
* Created:
|
||||
* Tue Nov 4 22:17:15 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
|
||||
`timescale 1ns/10ps
|
||||
|
||||
`define TB_VERBOSE
|
||||
//`define VERBOSE
|
||||
|
||||
|
||||
`include "axis_write_data.v"
|
||||
|
||||
module axis_write_data_tb;
|
||||
|
||||
/**
|
||||
* Clock and control functions
|
||||
*/
|
||||
|
||||
// Generate a clk
|
||||
reg clk;
|
||||
always #1 clk = !clk;
|
||||
|
||||
// End of simulation event definition
|
||||
event end_trigger;
|
||||
always @(end_trigger) $finish;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
// Display header information
|
||||
initial #1 display_header();
|
||||
always @(end_trigger) display_header();
|
||||
|
||||
// And strobe signals at each clk
|
||||
always @(posedge clk) display_signals();
|
||||
`endif
|
||||
|
||||
// initial begin
|
||||
// $dumpfile("result.vcd"); // Waveform file
|
||||
// $dumpvars;
|
||||
// end
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam STREAM_LENGTH = (256*8*2)-4;
|
||||
|
||||
localparam BUF_AWIDTH = 4;
|
||||
localparam CONFIG_DWIDTH = 32;
|
||||
|
||||
localparam AXI_LEN_WIDTH = 4;
|
||||
localparam AXI_DATA_WIDTH = 64;
|
||||
localparam DATA_WIDTH = 32;
|
||||
|
||||
localparam WIDTH_RATIO = AXI_DATA_WIDTH/DATA_WIDTH;
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
initial $display("Testbench for unit 'axis_write_data'");
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* signals, registers and wires
|
||||
*/
|
||||
|
||||
reg rst;
|
||||
|
||||
wire done;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_length;
|
||||
reg cfg_valid;
|
||||
wire cfg_ready;
|
||||
|
||||
wire axi_wlast;
|
||||
wire [AXI_DATA_WIDTH-1:0] axi_wdata;
|
||||
wire axi_wvalid;
|
||||
reg axi_wready;
|
||||
|
||||
reg [DATA_WIDTH-1:0] data;
|
||||
reg valid;
|
||||
wire ready;
|
||||
|
||||
|
||||
/**
|
||||
* Unit under test
|
||||
*/
|
||||
|
||||
axis_write_data #(
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
.CONVERT_SHIFT ($clog2(WIDTH_RATIO)),
|
||||
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
uut (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_valid),
|
||||
.cfg_ready (cfg_ready),
|
||||
|
||||
.axi_wlast (axi_wlast),
|
||||
.axi_wdata (axi_wdata),
|
||||
.axi_wvalid (axi_wvalid),
|
||||
.axi_wready (axi_wready),
|
||||
|
||||
.data (data),
|
||||
.valid (valid),
|
||||
.ready (ready)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Wave form display
|
||||
*/
|
||||
|
||||
task display_signals;
|
||||
$display(
|
||||
"%d\t%d",
|
||||
$time, rst,
|
||||
|
||||
"\t%d\t%b\t%b",
|
||||
cfg_length,
|
||||
cfg_valid,
|
||||
cfg_ready,
|
||||
|
||||
"\t%x\t%b\t%b\t%b",
|
||||
axi_wdata,
|
||||
axi_wvalid,
|
||||
axi_wready,
|
||||
axi_wlast,
|
||||
|
||||
"\t%x\t%b\t%b",
|
||||
data,
|
||||
valid,
|
||||
ready,
|
||||
|
||||
"\t%b",
|
||||
uut.state,
|
||||
|
||||
);
|
||||
|
||||
endtask // display_signals
|
||||
|
||||
task display_header;
|
||||
$display(
|
||||
"\t\ttime\trst",
|
||||
|
||||
"\t\tc_l",
|
||||
"\tc_v",
|
||||
"\tc_r",
|
||||
|
||||
"\tw_d",
|
||||
"\t\t\tw_v",
|
||||
"\tw_r",
|
||||
"\tw_l",
|
||||
|
||||
"\t\ts_d",
|
||||
"\ts_v",
|
||||
"\ts_r",
|
||||
|
||||
);
|
||||
endtask
|
||||
|
||||
|
||||
/**
|
||||
* Testbench program
|
||||
*/
|
||||
|
||||
initial begin
|
||||
// init values
|
||||
clk = 0;
|
||||
rst = 0;
|
||||
|
||||
cfg_length = 'b0;
|
||||
cfg_valid = 'b0;
|
||||
|
||||
axi_wready = 'b0;
|
||||
data = 'b0;
|
||||
valid = 'b0;
|
||||
//end init
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("RESET");
|
||||
`endif
|
||||
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b1;
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b0;
|
||||
@(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("send config id, start address and length");
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_length <= 8;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_length <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test write");
|
||||
`endif
|
||||
|
||||
axi_wready <= 1'b1;
|
||||
data <= 'b0;
|
||||
valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
repeat (5) begin
|
||||
data <= data + 1;
|
||||
valid <= 1'b1;
|
||||
@(negedge clk);
|
||||
end
|
||||
|
||||
axi_wready <= 1'b0;
|
||||
//data <= 'b0;
|
||||
valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
repeat (3) begin
|
||||
data <= data + 1;
|
||||
valid <= 1'b1;
|
||||
@(negedge clk);
|
||||
end
|
||||
|
||||
axi_wready <= 1'b1;
|
||||
//data <= 'b0;
|
||||
valid <= 1'b0;
|
||||
repeat(4) @(negedge clk);
|
||||
axi_wready <= 1'b1;
|
||||
@(negedge clk);
|
||||
axi_wready <= 1'b0;
|
||||
@(negedge clk);
|
||||
axi_wready <= 1'b1;
|
||||
@(negedge clk);
|
||||
axi_wready <= 1'b0;
|
||||
@(negedge clk);
|
||||
axi_wready <= 1'b1;
|
||||
@(negedge clk);
|
||||
axi_wready <= 1'b0;
|
||||
@(negedge clk);
|
||||
axi_wready <= 1'b1;
|
||||
@(negedge clk);
|
||||
axi_wready <= 1'b0;
|
||||
@(negedge clk);
|
||||
axi_wready <= 1'b0;
|
||||
@(negedge clk);
|
||||
axi_wready <= 1'b1;
|
||||
repeat(15) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("RESET");
|
||||
`endif
|
||||
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b1;
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b0;
|
||||
@(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("send config id, start address and length");
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_length <= 8;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_length <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test write address channel");
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
axi_wready <= 1'b1;
|
||||
//data <= 'b0;
|
||||
valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
repeat (8) begin
|
||||
data <= data + 1;
|
||||
valid <= 1'b1;
|
||||
@(negedge clk);
|
||||
valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
end
|
||||
valid <= 1'b0;
|
||||
|
||||
|
||||
repeat(15) @(negedge clk);
|
||||
axi_wready <= 1'b0;
|
||||
|
||||
repeat(15) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("RESET");
|
||||
`endif
|
||||
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b1;
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b0;
|
||||
@(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("send config id, start address and length");
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_length <= STREAM_LENGTH;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_length <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test write address channel");
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
data <= 'b0;
|
||||
valid <= 1'b0;
|
||||
axi_wready <= 1'b1;
|
||||
repeat(15) @(negedge clk);
|
||||
|
||||
repeat (STREAM_LENGTH) begin
|
||||
data <= data + 1;
|
||||
valid <= 1'b1;
|
||||
@(negedge clk);
|
||||
end
|
||||
valid <= 1'b0;
|
||||
|
||||
|
||||
repeat(15) @(negedge clk);
|
||||
axi_wready <= 1'b0;
|
||||
|
||||
repeat(15) @(negedge clk);
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("END");
|
||||
`endif
|
||||
-> end_trigger;
|
||||
end
|
||||
|
||||
endmodule
|
443
hdl/axis/axis_write_tb.v
Normal file
443
hdl/axis/axis_write_tb.v
Normal file
@ -0,0 +1,443 @@
|
||||
/**
|
||||
* Testbench:
|
||||
* axis_write
|
||||
*
|
||||
* Created:
|
||||
* Tue Nov 4 22:17:15 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
|
||||
`timescale 1ns/10ps
|
||||
|
||||
`define TB_VERBOSE
|
||||
//`define VERBOSE
|
||||
|
||||
|
||||
`include "axis_write.v"
|
||||
|
||||
module axis_write_tb;
|
||||
|
||||
/**
|
||||
* Clock and control functions
|
||||
*/
|
||||
|
||||
// Generate a clk
|
||||
reg clk;
|
||||
always #1 clk = !clk;
|
||||
|
||||
// End of simulation event definition
|
||||
event end_trigger;
|
||||
always @(end_trigger) $finish;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
// Display header information
|
||||
initial #1 display_header();
|
||||
always @(end_trigger) display_header();
|
||||
|
||||
// And strobe signals at each clk
|
||||
always @(posedge clk) display_signals();
|
||||
`endif
|
||||
|
||||
// initial begin
|
||||
// $dumpfile("result.vcd"); // Waveform file
|
||||
// $dumpvars;
|
||||
// end
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam STREAM_LENGTH = (256*8*2)-4;
|
||||
|
||||
localparam BUF_AWIDTH = 4;
|
||||
|
||||
localparam CONFIG_ID = 1;
|
||||
localparam CONFIG_ADDR = 23;
|
||||
localparam CONFIG_DATA = 24;
|
||||
localparam CONFIG_AWIDTH = 5;
|
||||
localparam CONFIG_DWIDTH = 32;
|
||||
|
||||
localparam AXI_ID_WIDTH = 8;
|
||||
localparam AXI_LEN_WIDTH = 2;
|
||||
localparam AXI_ADDR_WIDTH = 32;
|
||||
localparam AXI_DATA_WIDTH = 256;
|
||||
localparam DATA_WIDTH = 32;
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
initial $display("Testbench for unit 'axis_write'");
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* signals, registers and wires
|
||||
*/
|
||||
|
||||
reg rst;
|
||||
|
||||
reg [CONFIG_AWIDTH-1:0] cfg_addr;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_data;
|
||||
reg cfg_valid;
|
||||
|
||||
reg axi_awready;
|
||||
wire [AXI_ID_WIDTH-1:0] axi_awid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] axi_awaddr;
|
||||
//wire [7:0] axi_awlen;
|
||||
wire [AXI_LEN_WIDTH-1:0] axi_awlen;
|
||||
wire axi_awvalid;
|
||||
|
||||
wire axi_wlast;
|
||||
wire [AXI_DATA_WIDTH-1:0] axi_wdata;
|
||||
wire axi_wvalid;
|
||||
reg axi_wready;
|
||||
|
||||
reg [DATA_WIDTH-1:0] data;
|
||||
reg valid;
|
||||
wire ready;
|
||||
|
||||
|
||||
/**
|
||||
* Unit under test
|
||||
*/
|
||||
|
||||
axis_write #(
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
|
||||
.CONFIG_ID (CONFIG_ID),
|
||||
.CONFIG_ADDR (CONFIG_ADDR),
|
||||
.CONFIG_DATA (CONFIG_DATA),
|
||||
.CONFIG_AWIDTH (CONFIG_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
|
||||
.AXI_ID_WIDTH (AXI_ID_WIDTH),
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
uut (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.cfg_addr (cfg_addr),
|
||||
.cfg_data (cfg_data),
|
||||
.cfg_valid (cfg_valid),
|
||||
|
||||
.axi_awready (axi_awready),
|
||||
.axi_awid (axi_awid),
|
||||
.axi_awaddr (axi_awaddr),
|
||||
.axi_awlen (axi_awlen[0 +: AXI_LEN_WIDTH]),
|
||||
.axi_awvalid (axi_awvalid),
|
||||
|
||||
.axi_wlast (axi_wlast),
|
||||
.axi_wdata (axi_wdata),
|
||||
.axi_wvalid (axi_wvalid),
|
||||
.axi_wready (axi_wready),
|
||||
|
||||
.data (data),
|
||||
.valid (valid),
|
||||
.ready (ready)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Wave form display
|
||||
*/
|
||||
|
||||
task display_signals;
|
||||
$display(
|
||||
"%d\t%d",
|
||||
$time, rst,
|
||||
|
||||
"\t%d\t%d\t%b",
|
||||
cfg_addr,
|
||||
cfg_data,
|
||||
cfg_valid,
|
||||
|
||||
"\t%d\t%d\t%d\t%b\t%b",
|
||||
axi_awid,
|
||||
axi_awaddr,
|
||||
axi_awlen,
|
||||
axi_awvalid,
|
||||
axi_awready,
|
||||
|
||||
"\t%x\t%b\t%b\t%b",
|
||||
axi_wdata,
|
||||
axi_wvalid,
|
||||
axi_wready,
|
||||
axi_wlast,
|
||||
|
||||
"\t%d\t%b\t%b",
|
||||
data,
|
||||
valid,
|
||||
ready,
|
||||
|
||||
"\t%b",
|
||||
uut.c_state,
|
||||
|
||||
"\t%b",
|
||||
uut.axis_addr_.state,
|
||||
|
||||
);
|
||||
|
||||
endtask // display_signals
|
||||
|
||||
task display_header;
|
||||
$display(
|
||||
"\t\ttime\trst",
|
||||
|
||||
"\tc_a",
|
||||
"\t\tc_d",
|
||||
"\tc_v",
|
||||
|
||||
"\taw_id",
|
||||
"\t\taw_a",
|
||||
"\taw_l",
|
||||
"\taw_v",
|
||||
"\taw_r",
|
||||
|
||||
"\t\t\t\t\t\tw_d",
|
||||
"\t\t\t\tw_v",
|
||||
"\tw_r",
|
||||
"\tw_l",
|
||||
|
||||
"\t\ts_d",
|
||||
"\ts_v",
|
||||
"\tm_r",
|
||||
|
||||
);
|
||||
endtask
|
||||
|
||||
|
||||
/**
|
||||
* Testbench program
|
||||
*/
|
||||
|
||||
initial begin
|
||||
// init values
|
||||
clk = 0;
|
||||
rst = 0;
|
||||
|
||||
cfg_addr = 'b0;
|
||||
cfg_data = 'b0;
|
||||
cfg_valid = 'b0;
|
||||
|
||||
axi_awready = 'b0;
|
||||
|
||||
axi_wready = 'b0;
|
||||
data = 'b0;
|
||||
valid = 'b0;
|
||||
//end init
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("RESET");
|
||||
`endif
|
||||
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b1;
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b0;
|
||||
@(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("send config id, start address and length");
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_addr <= CONFIG_ADDR;
|
||||
cfg_data <= CONFIG_ID;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= 'b0;
|
||||
cfg_data <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_data <= 4;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= 'b0;
|
||||
cfg_data <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_data <= 8;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= 'b0;
|
||||
cfg_data <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test write address channel");
|
||||
`endif
|
||||
|
||||
repeat(3) @(negedge clk);
|
||||
axi_awready <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
axi_wready <= 1'b1;
|
||||
data <= 'b0;
|
||||
valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
repeat (5) begin
|
||||
data <= data + 1;
|
||||
valid <= 1'b1;
|
||||
@(negedge clk);
|
||||
end
|
||||
|
||||
axi_wready <= 1'b0;
|
||||
//data <= 'b0;
|
||||
valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
repeat (3) begin
|
||||
data <= data + 1;
|
||||
valid <= 1'b1;
|
||||
@(negedge clk);
|
||||
end
|
||||
|
||||
axi_wready <= 1'b1;
|
||||
data <= 'b0;
|
||||
valid <= 1'b0;
|
||||
//repeat(4) @(negedge clk);
|
||||
repeat(5) @(negedge clk);
|
||||
//repeat(6) @(negedge clk);
|
||||
axi_wready <= 1'b0;
|
||||
@(negedge clk);
|
||||
axi_wready <= 1'b1;
|
||||
repeat(15) @(negedge clk);
|
||||
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("send config id, start address and length");
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_addr <= CONFIG_ADDR;
|
||||
cfg_data <= CONFIG_ID;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_data <= 4;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_data <= 8;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= 'b0;
|
||||
cfg_data <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test write address channel");
|
||||
`endif
|
||||
|
||||
repeat(3) @(negedge clk);
|
||||
axi_awready <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
axi_wready <= 1'b1;
|
||||
data <= 'b0;
|
||||
valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
repeat (8) begin
|
||||
data <= data + 1;
|
||||
valid <= 1'b1;
|
||||
@(negedge clk);
|
||||
valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
end
|
||||
|
||||
axi_awready <= 1'b0;
|
||||
axi_wready <= 1'b0;
|
||||
repeat(15) @(negedge clk);
|
||||
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("send config id, start address and length");
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_addr <= CONFIG_ADDR;
|
||||
cfg_data <= CONFIG_ID;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_data <= 255;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_data <= STREAM_LENGTH;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= 'b0;
|
||||
cfg_data <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test long write");
|
||||
`endif
|
||||
|
||||
repeat(3) @(negedge clk);
|
||||
// ready to recive address
|
||||
axi_awready <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
// ready to recive data
|
||||
axi_wready <= 1'b1;
|
||||
data <= 'b0;
|
||||
valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
repeat (STREAM_LENGTH) begin
|
||||
// stream data into axis
|
||||
data <= data + 1;
|
||||
valid <= 1'b1;
|
||||
@(negedge clk);
|
||||
end
|
||||
|
||||
valid <= 1'b0;
|
||||
repeat(15) @(negedge clk);
|
||||
axi_wready <= 1'b0;
|
||||
repeat(15) @(negedge clk);
|
||||
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("END");
|
||||
`endif
|
||||
-> end_trigger;
|
||||
end
|
||||
|
||||
endmodule
|
187
hdl/fifo/fifo_simple.v
Normal file
187
hdl/fifo/fifo_simple.v
Normal file
@ -0,0 +1,187 @@
|
||||
/**
|
||||
* Module:
|
||||
* fifo_simple
|
||||
*
|
||||
* Description:
|
||||
* A simple FIFO, with synchronous clock for both the pop and push ports.
|
||||
*
|
||||
* Testbench:
|
||||
* fifo_simple_tb.v
|
||||
*
|
||||
* Created:
|
||||
* Sun Nov 30 13:39:40 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _fifo_simple_ `define _fifo_simple_
|
||||
|
||||
|
||||
module fifo_simple
|
||||
#(parameter
|
||||
DATA_WIDTH = 16,
|
||||
ADDR_WIDTH = 16)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
output reg [ADDR_WIDTH:0] count,
|
||||
output reg full,
|
||||
output reg full_a,
|
||||
output reg empty,
|
||||
output reg empty_a,
|
||||
|
||||
input push,
|
||||
input [DATA_WIDTH-1:0] push_data,
|
||||
|
||||
input pop,
|
||||
output reg [DATA_WIDTH-1:0] pop_data
|
||||
);
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam DEPTH = 1<<ADDR_WIDTH;
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
initial $display("fifo sync with depth: %d", DEPTH);
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* Internal signals
|
||||
*/
|
||||
|
||||
reg [DATA_WIDTH-1:0] mem [0:DEPTH-1];
|
||||
|
||||
reg [ADDR_WIDTH:0] push_ptr;
|
||||
wire [ADDR_WIDTH:0] push_ptr_nx;
|
||||
reg [ADDR_WIDTH:0] pop_ptr;
|
||||
wire [ADDR_WIDTH:0] pop_ptr_nx;
|
||||
|
||||
wire [ADDR_WIDTH-1:0] push_addr;
|
||||
wire [ADDR_WIDTH-1:0] push_addr_nx;
|
||||
wire [ADDR_WIDTH-1:0] pop_addr;
|
||||
wire [ADDR_WIDTH-1:0] pop_addr_nx;
|
||||
|
||||
wire full_nx;
|
||||
wire empty_nx;
|
||||
|
||||
wire full_a_nx;
|
||||
wire [ADDR_WIDTH-1:0] push_addr_a_nx;
|
||||
wire [ADDR_WIDTH:0] push_ptr_a_nx;
|
||||
wire empty_a_nx;
|
||||
wire [ADDR_WIDTH-1:0] pop_addr_a_nx;
|
||||
wire [ADDR_WIDTH:0] pop_ptr_a_nx;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign push_addr = push_ptr [ADDR_WIDTH-1:0];
|
||||
|
||||
assign push_addr_nx = push_ptr_nx [ADDR_WIDTH-1:0];
|
||||
|
||||
assign pop_addr = pop_ptr [ADDR_WIDTH-1:0];
|
||||
|
||||
assign pop_addr_nx = pop_ptr_nx [ADDR_WIDTH-1:0];
|
||||
|
||||
|
||||
// full next
|
||||
assign full_nx = (push_addr_nx == pop_addr) & (push_ptr_nx[ADDR_WIDTH] != pop_ptr[ADDR_WIDTH]);
|
||||
|
||||
// almost full next
|
||||
assign push_ptr_a_nx = push_ptr_nx + 1;
|
||||
|
||||
assign push_addr_a_nx = push_ptr_a_nx[0 +: ADDR_WIDTH];
|
||||
|
||||
assign full_a_nx =
|
||||
(push_addr_a_nx == pop_addr) & (push_ptr_a_nx[ADDR_WIDTH] != pop_ptr[ADDR_WIDTH]);
|
||||
|
||||
|
||||
// empty next
|
||||
assign empty_nx = (push_addr == pop_addr_nx) & (push_ptr[ADDR_WIDTH] == pop_ptr_nx[ADDR_WIDTH]);
|
||||
|
||||
// almost empty next
|
||||
assign pop_ptr_a_nx = pop_ptr_nx + 1;
|
||||
|
||||
assign pop_addr_a_nx = pop_ptr_a_nx[0 +: ADDR_WIDTH];
|
||||
|
||||
assign empty_a_nx =
|
||||
(push_addr == pop_addr_a_nx) & (push_ptr[ADDR_WIDTH] == pop_ptr_a_nx[ADDR_WIDTH]);
|
||||
|
||||
|
||||
// pop next
|
||||
assign pop_ptr_nx = pop_ptr + (pop & ~empty);
|
||||
|
||||
// push next
|
||||
assign push_ptr_nx = push_ptr + (push & ~full);
|
||||
|
||||
|
||||
// registered population count.
|
||||
always @(posedge clk)
|
||||
if (rst) begin
|
||||
count <= 'b0;
|
||||
end
|
||||
else begin
|
||||
if (push_ptr[ADDR_WIDTH] == pop_ptr_nx[ADDR_WIDTH]) begin
|
||||
count <= (push_addr - pop_addr_nx);
|
||||
end
|
||||
else begin
|
||||
count <= DEPTH - pop_addr_nx + push_addr;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// registered full flag
|
||||
always @(posedge clk)
|
||||
if (rst) full <= 1'b0;
|
||||
else full <= full_nx;
|
||||
|
||||
|
||||
// almost full flag
|
||||
always @(posedge clk)
|
||||
if (rst) full_a <= 1'b0;
|
||||
else full_a <= full_a_nx | full_nx;
|
||||
|
||||
|
||||
// registered empty flag
|
||||
always @(posedge clk)
|
||||
if (rst) empty <= 1'b1;
|
||||
else empty <= empty_nx;
|
||||
|
||||
|
||||
// almost empty flag
|
||||
always @(posedge clk)
|
||||
if (rst) empty_a <= 1'b1;
|
||||
else empty_a <= empty_a_nx | empty_nx;
|
||||
|
||||
|
||||
// memory read-address pointer
|
||||
always @(posedge clk)
|
||||
if (rst) pop_ptr <= 0;
|
||||
else pop_ptr <= pop_ptr_nx;
|
||||
|
||||
|
||||
// read from memory
|
||||
always @(posedge clk)
|
||||
if (pop & ~empty) pop_data <= mem[pop_addr];
|
||||
|
||||
|
||||
// memory write-address pointer
|
||||
always @(posedge clk)
|
||||
if (rst) push_ptr <= 0;
|
||||
else push_ptr <= push_ptr_nx;
|
||||
|
||||
|
||||
// write to memory
|
||||
always @(posedge clk)
|
||||
if (push & ~full) mem[push_addr] <= push_data;
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _fifo_simple_
|
228
hdl/fifo/fifo_simple_tb.v
Normal file
228
hdl/fifo/fifo_simple_tb.v
Normal file
@ -0,0 +1,228 @@
|
||||
/**
|
||||
* Testbench:
|
||||
* fifo_simple
|
||||
*
|
||||
* Created:
|
||||
* Sun Nov 30 13:44:07 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
|
||||
`timescale 1ns/10ps
|
||||
|
||||
`define TB_VERBOSE
|
||||
//`define VERBOSE
|
||||
|
||||
`include "fifo_simple.v"
|
||||
|
||||
module fifo_simple_tb;
|
||||
|
||||
/**
|
||||
* Clock and control functions
|
||||
*/
|
||||
|
||||
// Generate a clk
|
||||
reg clk;
|
||||
always #1 clk = !clk;
|
||||
|
||||
// End of simulation event definition
|
||||
event end_trigger;
|
||||
always @(end_trigger) $finish;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
// Display header information
|
||||
initial #1 display_header();
|
||||
always @(end_trigger) display_header();
|
||||
|
||||
// And strobe signals at each clk
|
||||
always @(posedge clk) display_signals();
|
||||
`endif
|
||||
|
||||
// initial begin
|
||||
// $dumpfile("result.vcd"); // Waveform file
|
||||
// $dumpvars;
|
||||
// end
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam DATA_WIDTH = 6;
|
||||
localparam ADDR_WIDTH = 4;
|
||||
|
||||
|
||||
/**
|
||||
* signals, registers and wires
|
||||
*/
|
||||
|
||||
reg rst;
|
||||
reg pop;
|
||||
reg push;
|
||||
reg [DATA_WIDTH-1:0] push_data;
|
||||
wire [DATA_WIDTH-1:0] pop_data;
|
||||
wire empty;
|
||||
wire full;
|
||||
wire empty_a;
|
||||
wire full_a;
|
||||
|
||||
wire [ADDR_WIDTH:0] count;
|
||||
|
||||
|
||||
/**
|
||||
* Unit under test
|
||||
*/
|
||||
|
||||
fifo_simple #(
|
||||
.DATA_WIDTH (DATA_WIDTH),
|
||||
.ADDR_WIDTH (ADDR_WIDTH))
|
||||
uut (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.count (count),
|
||||
.full (full),
|
||||
.full_a (full_a),
|
||||
.empty (empty),
|
||||
.empty_a (empty_a),
|
||||
|
||||
.push (push),
|
||||
.push_data (push_data),
|
||||
|
||||
.pop (pop),
|
||||
.pop_data (pop_data)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Wave form display
|
||||
*/
|
||||
|
||||
task display_signals;
|
||||
$display("%d\t%b\t%b\t%d\t%b\t%b\t%b\t%d\t%b\t%b\t%d\t%d",
|
||||
$time, rst,
|
||||
push,
|
||||
push_data,
|
||||
full,
|
||||
full_a,
|
||||
pop,
|
||||
pop_data,
|
||||
empty,
|
||||
empty_a,
|
||||
count,
|
||||
|(count[ADDR_WIDTH:ADDR_WIDTH-1]),
|
||||
);
|
||||
endtask // display_signals
|
||||
|
||||
task display_header;
|
||||
$display(
|
||||
"\t\ttime\trst",
|
||||
|
||||
"\tpush",
|
||||
"\tdat",
|
||||
"\tfull",
|
||||
"\tfull_a",
|
||||
|
||||
"\tpop",
|
||||
"\tdat",
|
||||
"\tempty",
|
||||
"\tempty_a",
|
||||
"\tcount",
|
||||
|
||||
);
|
||||
endtask
|
||||
|
||||
|
||||
/**
|
||||
* Testbench program
|
||||
*/
|
||||
|
||||
initial begin
|
||||
// init values
|
||||
clk = 0;
|
||||
rst = 0;
|
||||
push = 0;
|
||||
push_data = 0;
|
||||
pop = 0;
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("RESET");
|
||||
`endif
|
||||
|
||||
@(negedge clk);
|
||||
rst <= 1'b1;
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b0;
|
||||
repeat(6) @(negedge clk);
|
||||
|
||||
|
||||
$display("TEST write to fifo");
|
||||
repeat (20) @(negedge clk) begin
|
||||
push <= 1'b1;
|
||||
push_data <= $random;
|
||||
end
|
||||
push <= 1'b0;
|
||||
push_data <= 0;
|
||||
|
||||
|
||||
$display("TEST read from fifo");
|
||||
#1
|
||||
repeat (16) @(negedge clk) begin
|
||||
pop <= 1'b1;
|
||||
end
|
||||
pop <= 1'b0;
|
||||
|
||||
$display("TEST write 5 data points to fifo");
|
||||
repeat (5) @(negedge clk) begin
|
||||
push <= 1'b1;
|
||||
push_data <= $random;
|
||||
end
|
||||
push <= 1'b0;
|
||||
push_data <= 0;
|
||||
#5
|
||||
|
||||
$display("TEST read two data points from fifo");
|
||||
repeat (2) @(negedge clk) begin
|
||||
pop <= 1'b1;
|
||||
end
|
||||
pop <= 1'b0;
|
||||
|
||||
#5
|
||||
$display("TEST write 15 data points to fifo");
|
||||
repeat (15) @(negedge clk) begin
|
||||
push <= 1'b1;
|
||||
push_data <= $random;
|
||||
end
|
||||
push <= 1'b0;
|
||||
push_data <= 0;
|
||||
#5
|
||||
|
||||
$display("TEST read two data points from fifo");
|
||||
#1
|
||||
repeat (8) @(negedge clk) begin
|
||||
pop <= 1'b1;
|
||||
end
|
||||
pop <= 1'b0;
|
||||
|
||||
|
||||
$display("TEST simultaneous read/write 15 data points to fifo");
|
||||
repeat (15) @(negedge clk) begin
|
||||
pop <= 1'b1;
|
||||
push <= 1'b1;
|
||||
push_data <= $random;
|
||||
end
|
||||
repeat (15) @(negedge clk) begin
|
||||
pop <= 1'b1;
|
||||
end
|
||||
|
||||
$display("OTHER TESTS");
|
||||
push <= 1'b0;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("END");
|
||||
`endif
|
||||
-> end_trigger;
|
||||
end
|
||||
endmodule
|
@ -1,5 +1,6 @@
|
||||
|
||||
`include "axi4lite_cfg.v"
|
||||
`include "axis.v"
|
||||
|
||||
module zedboard_axis
|
||||
(inout [14:0] DDR_addr,
|
||||
@ -25,6 +26,24 @@ module zedboard_axis
|
||||
inout FIXED_IO_ps_srstb
|
||||
);
|
||||
|
||||
localparam CFG_AWIDTH = 5;
|
||||
localparam CFG_DWIDTH = 32;
|
||||
|
||||
localparam AXI_ID_WIDTH = 6;
|
||||
localparam AXI_LEN_WIDTH = 4;
|
||||
localparam AXI_ADDR_WIDTH = 32;
|
||||
localparam AXI_DATA_WIDTH = 64;
|
||||
|
||||
localparam
|
||||
CFG_AXIS_ADDR = 0,
|
||||
CFG_AXIS_DATA = 1,
|
||||
CFG_HP0_DST_CNT = 2,
|
||||
CFG_HP0_SRC_CNT = 3,
|
||||
CFG_HP0_DST_DATA = 4,
|
||||
CFG_HP0_SRC_DATA = 5,
|
||||
CFG_EMPTY = 6;
|
||||
|
||||
|
||||
genvar i;
|
||||
|
||||
wire axi_clk;
|
||||
@ -50,6 +69,45 @@ module zedboard_axis
|
||||
wire [3:0] axi_wstrb;
|
||||
wire axi_wvalid;
|
||||
|
||||
wire [31:0] axi_hp0_araddr;
|
||||
wire [1:0] axi_hp0_arburst;
|
||||
wire [3:0] axi_hp0_arcache;
|
||||
wire [5:0] axi_hp0_arid;
|
||||
wire [3:0] axi_hp0_arlen;
|
||||
wire [1:0] axi_hp0_arlock;
|
||||
wire [2:0] axi_hp0_arprot;
|
||||
wire [3:0] axi_hp0_arqos;
|
||||
wire axi_hp0_arready;
|
||||
wire [2:0] axi_hp0_arsize;
|
||||
wire axi_hp0_arvalid;
|
||||
wire [31:0] axi_hp0_awaddr;
|
||||
wire [1:0] axi_hp0_awburst;
|
||||
wire [3:0] axi_hp0_awcache;
|
||||
wire [5:0] axi_hp0_awid;
|
||||
wire [3:0] axi_hp0_awlen;
|
||||
wire [1:0] axi_hp0_awlock;
|
||||
wire [2:0] axi_hp0_awprot;
|
||||
wire [3:0] axi_hp0_awqos;
|
||||
wire axi_hp0_awready;
|
||||
wire [2:0] axi_hp0_awsize;
|
||||
wire axi_hp0_awvalid;
|
||||
wire [5:0] axi_hp0_bid;
|
||||
wire axi_hp0_bready;
|
||||
wire [1:0] axi_hp0_bresp;
|
||||
wire axi_hp0_bvalid;
|
||||
wire [63:0] axi_hp0_rdata;
|
||||
wire [5:0] axi_hp0_rid;
|
||||
wire axi_hp0_rlast;
|
||||
wire axi_hp0_rready;
|
||||
wire [1:0] axi_hp0_rresp;
|
||||
wire axi_hp0_rvalid;
|
||||
wire [63:0] axi_hp0_wdata;
|
||||
wire [5:0] axi_hp0_wid;
|
||||
wire axi_hp0_wlast;
|
||||
wire axi_hp0_wready;
|
||||
wire [7:0] axi_hp0_wstrb;
|
||||
wire axi_hp0_wvalid;
|
||||
|
||||
wire [31:0] cfg_wr_data;
|
||||
wire [4:0] cfg_wr_addr;
|
||||
wire cfg_wr_en;
|
||||
@ -61,6 +119,18 @@ module zedboard_axis
|
||||
reg [31:0] cfg_hold [0:31];
|
||||
reg [0:31] cfg_hold_en;
|
||||
|
||||
wire [31:0] sys_hp0_dst_data;
|
||||
wire sys_hp0_dst_valid;
|
||||
wire sys_hp0_dst_ready;
|
||||
|
||||
wire [31:0] sys_hp0_src_data;
|
||||
wire sys_hp0_src_valid;
|
||||
wire sys_hp0_src_ready;
|
||||
|
||||
reg [CFG_DWIDTH-1:0] axis_hp0_dst_cnt;
|
||||
reg [CFG_DWIDTH-1:0] axis_hp0_src_cnt;
|
||||
|
||||
|
||||
system
|
||||
system_i (
|
||||
.DDR_addr (DDR_addr),
|
||||
@ -106,7 +176,50 @@ module zedboard_axis
|
||||
.M00_AXI_wdata (axi_wdata),
|
||||
.M00_AXI_wready (axi_wready),
|
||||
.M00_AXI_wstrb (axi_wstrb),
|
||||
.M00_AXI_wvalid (axi_wvalid)
|
||||
.M00_AXI_wvalid (axi_wvalid),
|
||||
|
||||
.S_AXI_HP0_araddr (axi_hp0_araddr),
|
||||
.S_AXI_HP0_arburst (axi_hp0_arburst),
|
||||
.S_AXI_HP0_arcache (axi_hp0_arcache),
|
||||
.S_AXI_HP0_arid (axi_hp0_arid),
|
||||
.S_AXI_HP0_arlen (axi_hp0_arlen),
|
||||
.S_AXI_HP0_arlock (axi_hp0_arlock),
|
||||
.S_AXI_HP0_arprot (axi_hp0_arprot),
|
||||
.S_AXI_HP0_arqos (axi_hp0_arqos),
|
||||
.S_AXI_HP0_arready (axi_hp0_arready),
|
||||
.S_AXI_HP0_arsize (axi_hp0_arsize),
|
||||
.S_AXI_HP0_arvalid (axi_hp0_arvalid),
|
||||
|
||||
.S_AXI_HP0_awaddr (axi_hp0_awaddr),
|
||||
.S_AXI_HP0_awburst (axi_hp0_awburst),
|
||||
.S_AXI_HP0_awcache (axi_hp0_awcache),
|
||||
.S_AXI_HP0_awid (axi_hp0_awid),
|
||||
.S_AXI_HP0_awlen (axi_hp0_awlen),
|
||||
.S_AXI_HP0_awlock (axi_hp0_awlock),
|
||||
.S_AXI_HP0_awprot (axi_hp0_awprot),
|
||||
.S_AXI_HP0_awqos (axi_hp0_awqos),
|
||||
.S_AXI_HP0_awready (axi_hp0_awready),
|
||||
.S_AXI_HP0_awsize (axi_hp0_awsize),
|
||||
.S_AXI_HP0_awvalid (axi_hp0_awvalid),
|
||||
|
||||
.S_AXI_HP0_bid (axi_hp0_bid),
|
||||
.S_AXI_HP0_bready (axi_hp0_bready),
|
||||
.S_AXI_HP0_bresp (axi_hp0_bresp),
|
||||
.S_AXI_HP0_bvalid (axi_hp0_bvalid),
|
||||
|
||||
.S_AXI_HP0_rdata (axi_hp0_rdata),
|
||||
.S_AXI_HP0_rid (axi_hp0_rid),
|
||||
.S_AXI_HP0_rlast (axi_hp0_rlast),
|
||||
.S_AXI_HP0_rready (axi_hp0_rready),
|
||||
.S_AXI_HP0_rresp (axi_hp0_rresp),
|
||||
.S_AXI_HP0_rvalid (axi_hp0_rvalid),
|
||||
|
||||
.S_AXI_HP0_wdata (axi_hp0_wdata),
|
||||
.S_AXI_HP0_wid (axi_hp0_wid),
|
||||
.S_AXI_HP0_wlast (axi_hp0_wlast),
|
||||
.S_AXI_HP0_wready (axi_hp0_wready),
|
||||
.S_AXI_HP0_wstrb (axi_hp0_wstrb),
|
||||
.S_AXI_HP0_wvalid (axi_hp0_wvalid)
|
||||
);
|
||||
|
||||
|
||||
@ -179,6 +292,9 @@ module zedboard_axis
|
||||
|
||||
if (cfg_rd_en) begin
|
||||
case (cfg_rd_addr)
|
||||
CFG_HP0_DST_CNT : cfg_rd_data <= axis_hp0_dst_cnt;
|
||||
CFG_HP0_SRC_CNT : cfg_rd_data <= axis_hp0_src_cnt;
|
||||
CFG_HP0_SRC_DATA : cfg_rd_data <= sys_hp0_src_data;
|
||||
|
||||
default : cfg_rd_data <= cfg_hold[cfg_rd_addr];
|
||||
endcase
|
||||
@ -186,4 +302,97 @@ module zedboard_axis
|
||||
end
|
||||
|
||||
|
||||
axis #(
|
||||
.BUF_AWIDTH (9),
|
||||
.CONFIG_ID_RD (1),
|
||||
.CONFIG_ID_WR (2),
|
||||
.CONFIG_ADDR (CFG_AXIS_ADDR),
|
||||
.CONFIG_DATA (CFG_AXIS_DATA),
|
||||
.CONFIG_AWIDTH (CFG_AWIDTH),
|
||||
.CONFIG_DWIDTH (CFG_DWIDTH),
|
||||
.STREAM_WIDTH (32),
|
||||
.AXI_ID_WIDTH (AXI_ID_WIDTH),
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH))
|
||||
axis_hp0_ (
|
||||
.clk (axi_clk),
|
||||
.rst ( ~axi_rst_n),
|
||||
|
||||
.cfg_addr (cfg_wr_addr),
|
||||
.cfg_data (cfg_wr_data),
|
||||
.cfg_valid (cfg_wr_en),
|
||||
|
||||
.wr_data (sys_hp0_dst_data),
|
||||
.wr_valid (sys_hp0_dst_valid),
|
||||
.wr_ready (sys_hp0_dst_ready),
|
||||
|
||||
.rd_data (sys_hp0_src_data),
|
||||
.rd_valid (sys_hp0_src_valid),
|
||||
.rd_ready (sys_hp0_src_ready),
|
||||
|
||||
.axi_awready (axi_hp0_awready),
|
||||
.axi_awid (axi_hp0_awid),
|
||||
.axi_awaddr (axi_hp0_awaddr),
|
||||
.axi_awlen (axi_hp0_awlen),
|
||||
.axi_awsize (axi_hp0_awsize),
|
||||
.axi_awburst (axi_hp0_awburst),
|
||||
.axi_awlock (axi_hp0_awlock),
|
||||
.axi_awcache (axi_hp0_awcache),
|
||||
.axi_awprot (axi_hp0_awprot),
|
||||
.axi_awqos (axi_hp0_awqos),
|
||||
.axi_awvalid (axi_hp0_awvalid),
|
||||
|
||||
.axi_wready (axi_hp0_wready),
|
||||
.axi_wid (axi_hp0_wid),
|
||||
.axi_wdata (axi_hp0_wdata),
|
||||
.axi_wstrb (axi_hp0_wstrb),
|
||||
.axi_wlast (axi_hp0_wlast),
|
||||
.axi_wvalid (axi_hp0_wvalid),
|
||||
|
||||
.axi_bid (axi_hp0_bid),
|
||||
.axi_bresp (axi_hp0_bresp),
|
||||
.axi_bvalid (axi_hp0_bvalid),
|
||||
.axi_bready (axi_hp0_bready),
|
||||
|
||||
.axi_arready (axi_hp0_arready),
|
||||
.axi_arid (axi_hp0_arid),
|
||||
.axi_araddr (axi_hp0_araddr),
|
||||
.axi_arlen (axi_hp0_arlen),
|
||||
.axi_arsize (axi_hp0_arsize),
|
||||
.axi_arburst (axi_hp0_arburst),
|
||||
.axi_arlock (axi_hp0_arlock),
|
||||
.axi_arcache (axi_hp0_arcache),
|
||||
.axi_arprot (axi_hp0_arprot),
|
||||
.axi_arvalid (axi_hp0_arvalid),
|
||||
.axi_arqos (axi_hp0_arqos),
|
||||
|
||||
.axi_rid (axi_hp0_rid),
|
||||
.axi_rresp (axi_hp0_rresp),
|
||||
.axi_rvalid (axi_hp0_rvalid),
|
||||
.axi_rdata (axi_hp0_rdata),
|
||||
.axi_rlast (axi_hp0_rlast),
|
||||
.axi_rready (axi_hp0_rready)
|
||||
);
|
||||
|
||||
|
||||
assign sys_hp0_dst_data = cfg_hold[CFG_HP0_DST_DATA];
|
||||
assign sys_hp0_dst_valid = cfg_hold_en[CFG_HP0_DST_DATA];
|
||||
assign sys_hp0_src_ready = cfg_rd_en & (CFG_HP0_SRC_DATA == cfg_rd_addr);
|
||||
|
||||
|
||||
// counts number of system data sent from AXIS port
|
||||
always @(posedge axi_clk)
|
||||
if ( ~axi_rst_n) axis_hp0_dst_cnt <= 'b0;
|
||||
else if (sys_hp0_dst_valid) begin
|
||||
axis_hp0_dst_cnt <= axis_hp0_dst_cnt + 1;
|
||||
end
|
||||
|
||||
always @(posedge axi_clk)
|
||||
if ( ~axi_rst_n) axis_hp0_src_cnt <= 'b0;
|
||||
else if (sys_hp0_src_valid) begin
|
||||
axis_hp0_src_cnt <= axis_hp0_src_cnt + 1;
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
67
sim-module
Executable file
67
sim-module
Executable file
@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
set -o errexit
|
||||
|
||||
|
||||
# Should give an arg
|
||||
if [ $# == 0 ]
|
||||
then
|
||||
echo "? executes the testbench for the module"
|
||||
echo "syntax:"
|
||||
echo " ./sim-module <module-name>"
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
# create sim scratch work directory
|
||||
test -d sim/scratch && rm -rf sim/scratch
|
||||
mkdir -p sim/scratch/src
|
||||
|
||||
# copy verilog code files from hdl directory into sim work dir
|
||||
for FILE in $(find ./hdl/* -name "*.v" -type f -print)
|
||||
do
|
||||
cp -n $FILE ./sim/scratch/src/ || { echo "ERROR duplicate filename ${FILE}" ; exit 1; }
|
||||
done
|
||||
|
||||
# copy verilog header files from hdl directory into sim work dir
|
||||
for FILE in $(find ./hdl/*/ -name "*.vh" -type f -print)
|
||||
do
|
||||
cp -n $FILE ./sim/scratch/src/ || { echo "ERROR duplicate filename ${FILE}" ; exit 1; }
|
||||
done
|
||||
|
||||
# copy SystemVerilog code files from hdl directory into sim work dir
|
||||
for FILE in $(find ./hdl/*/ -name "*.sv" -type f -print)
|
||||
do
|
||||
cp -n $FILE ./sim/scratch/src/ || { echo "ERROR duplicate filename ${FILE}" ; exit 1; }
|
||||
done
|
||||
|
||||
# cd into the working dir
|
||||
cd sim/scratch/src
|
||||
|
||||
# UUT should contain the name of the unit under test
|
||||
if [ -f $1_tb.v ]
|
||||
then
|
||||
UUT=$1
|
||||
else
|
||||
echo "syntax:"
|
||||
echo " ./sim-module <module-name>"
|
||||
echo ""
|
||||
echo "Where <module-name>_tb.v should exist"
|
||||
exit
|
||||
fi
|
||||
|
||||
# compile current unit
|
||||
echo "UUT = $UUT"
|
||||
iverilog -o ../$UUT ${UUT}_tb.v
|
||||
cd ..
|
||||
|
||||
# run current simul/testbench
|
||||
if [ -f $UUT ]
|
||||
then
|
||||
./$UUT
|
||||
else
|
||||
echo "iverilog failed"
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
echo "test for unit ${UUT} done"
|
@ -251,7 +251,7 @@
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PCW_USE_S_AXI_GP0">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PCW_USE_S_AXI_GP1">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PCW_USE_S_AXI_ACP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PCW_USE_S_AXI_HP0">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PCW_USE_S_AXI_HP0">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PCW_USE_S_AXI_HP1">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PCW_USE_S_AXI_HP2">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PCW_USE_S_AXI_HP3">0</spirit:configurableElementValue>
|
||||
|
@ -45,6 +45,78 @@
|
||||
</spirit:parameter>
|
||||
</spirit:parameters>
|
||||
</spirit:busInterface>
|
||||
<spirit:busInterface>
|
||||
<spirit:name>S_AXI_HP0</spirit:name>
|
||||
<spirit:slave/>
|
||||
<spirit:busType spirit:library="interface" spirit:name="aximm" spirit:vendor="xilinx.com" spirit:version="1.0"/>
|
||||
<spirit:abstractionType spirit:library="interface" spirit:name="aximm_rtl" spirit:vendor="xilinx.com" spirit:version="1.0"/>
|
||||
<spirit:parameters>
|
||||
<spirit:parameter>
|
||||
<spirit:name>DATA_WIDTH</spirit:name>
|
||||
<spirit:value>64</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>PROTOCOL</spirit:name>
|
||||
<spirit:value>AXI3</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>FREQ_HZ</spirit:name>
|
||||
<spirit:value>100000000</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>ID_WIDTH</spirit:name>
|
||||
<spirit:value>6</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>ADDR_WIDTH</spirit:name>
|
||||
<spirit:value>32</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>AWUSER_WIDTH</spirit:name>
|
||||
<spirit:value>0</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>ARUSER_WIDTH</spirit:name>
|
||||
<spirit:value>0</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>WUSER_WIDTH</spirit:name>
|
||||
<spirit:value>0</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>RUSER_WIDTH</spirit:name>
|
||||
<spirit:value>0</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>BUSER_WIDTH</spirit:name>
|
||||
<spirit:value>0</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>READ_WRITE_MODE</spirit:name>
|
||||
<spirit:value>READ_WRITE</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>SUPPORTS_NARROW_BURST</spirit:name>
|
||||
<spirit:value>1</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>NUM_READ_OUTSTANDING</spirit:name>
|
||||
<spirit:value>1</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>NUM_WRITE_OUTSTANDING</spirit:name>
|
||||
<spirit:value>1</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>MAX_BURST_LENGTH</spirit:name>
|
||||
<spirit:value>16</spirit:value>
|
||||
</spirit:parameter>
|
||||
<spirit:parameter>
|
||||
<spirit:name>PHASE</spirit:name>
|
||||
<spirit:value>0.000</spirit:value>
|
||||
</spirit:parameter>
|
||||
</spirit:parameters>
|
||||
</spirit:busInterface>
|
||||
<spirit:busInterface>
|
||||
<spirit:name>CLK.AXI_CLK</spirit:name>
|
||||
<spirit:displayName>Clk</spirit:displayName>
|
||||
@ -107,6 +179,21 @@
|
||||
</spirit:port>
|
||||
</spirit:ports>
|
||||
</spirit:model>
|
||||
<spirit:addressSpaces>
|
||||
<spirit:addressSpace>
|
||||
<spirit:name>S_AXI_HP0</spirit:name>
|
||||
<spirit:range>4G</spirit:range>
|
||||
<spirit:width>32</spirit:width>
|
||||
<spirit:segments>
|
||||
<spirit:segment>
|
||||
<spirit:name>SEG_ps7_HP0_DDR_LOWOCM</spirit:name>
|
||||
<spirit:displayName>/ps7/S_AXI_HP0/HP0_DDR_LOWOCM</spirit:displayName>
|
||||
<spirit:addressOffset>0x00000000</spirit:addressOffset>
|
||||
<spirit:range>512M</spirit:range>
|
||||
</spirit:segment>
|
||||
</spirit:segments>
|
||||
</spirit:addressSpace>
|
||||
</spirit:addressSpaces>
|
||||
<spirit:memoryMaps>
|
||||
<spirit:memoryMap>
|
||||
<spirit:name>M00_AXI</spirit:name>
|
||||
@ -131,6 +218,7 @@
|
||||
<spirit:componentRef spirit:library="ip" spirit:name="processing_system7" spirit:vendor="xilinx.com" spirit:version="5.4"/>
|
||||
<spirit:configurableElementValues>
|
||||
<spirit:configurableElementValue spirit:referenceId="bd:xciName">system_ps7_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PCW_USE_S_AXI_HP0">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="preset">*</spirit:configurableElementValue>
|
||||
</spirit:configurableElementValues>
|
||||
</spirit:componentInstance>
|
||||
@ -160,6 +248,7 @@
|
||||
<spirit:internalPortReference spirit:componentRef="axi_interconnect_0" spirit:portRef="M00_ACLK"/>
|
||||
<spirit:internalPortReference spirit:componentRef="axi_interconnect_0" spirit:portRef="S00_ACLK"/>
|
||||
<spirit:internalPortReference spirit:componentRef="axi_interconnect_0" spirit:portRef="ACLK"/>
|
||||
<spirit:internalPortReference spirit:componentRef="ps7" spirit:portRef="S_AXI_HP0_ACLK"/>
|
||||
</spirit:adHocConnection>
|
||||
<spirit:adHocConnection>
|
||||
<spirit:name>ps7_FCLK_RESET0_N</spirit:name>
|
||||
@ -180,6 +269,9 @@
|
||||
<spirit:hierConnection spirit:interfaceRef="M00_AXI/axi_interconnect_0_M00_AXI">
|
||||
<spirit:activeInterface spirit:busRef="M00_AXI" spirit:componentRef="axi_interconnect_0"/>
|
||||
</spirit:hierConnection>
|
||||
<spirit:hierConnection spirit:interfaceRef="S_AXI_HP0/S_AXI_HP0_1">
|
||||
<spirit:activeInterface spirit:busRef="S_AXI_HP0" spirit:componentRef="ps7"/>
|
||||
</spirit:hierConnection>
|
||||
</spirit:hierConnections>
|
||||
</spirit:design>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user