Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
public class Template extends Thread
{ // AXI IO
public int waddr;
public int wdata;
public int wburst;
public boolean wreq;
public boolean wbusy;
public int raddr;
public int rdata;
public boolean rreq;
public boolean rbusy;
// user IO
public int gpio0; // fb_addr
public int gpio1; // line_bytes
public int gpio2; // dot_size
public int gpio3;
private int fb_addr;
private int line_bytes;
private int dot_size;
private int calc_page;
private int draw_page;
private byte cell[] = new byte[8192 /*all_page_size*/];
private void fill_rect(int addr, int data, int width, int height)
{
int len;
if (width < 16 /*max_burst*/)
{
len = width;
}
else
{
len = 16 /*max_burst*/;
}
int burst = len - 1;
int w = width >> 4 /*max_burst_bits*/;
int dx = len << 2 /*bpp_bits*/;
int ady = addr;
for (int y = 0; y < height; y++)
{
int adx = ady;
for (int x = 0; x < w; x++)
{
write_data(adx, data, burst);
adx += dx;
}
ady += line_bytes;
}
int left_start = w << 4 /*max_burst_bits*/;
int left_size = width - left_start;
if (left_size > 0)
{
int left_burst = left_size - 1;
ady = addr + (left_start << 2 /*bpp_bits*/);
for (int y = 0; y < height; y++)
{
write_data(ady, data, left_burst);
ady += line_bytes;
}
}
}
private int get_index(int x, int y, int page)
{
return (x & 63 /*cell_size_minus_1*/) + ((y & 63 /*cell_size_minus_1*/) << 6 /*cell_size_bits*/) + (page << 12 /*page_bits*/);
}
private byte get_cell(int x, int y, int page)
{
return cell[get_index(x, y, page)];
}
private void set_cell(int x, int y, int page, byte value)
{
cell[get_index(x, y, page)] = value;
}
private int get_neighbor(int x, int y, int p)
{
int neighbor =
get_cell(x-1,y-1,p)+get_cell(x,y-1,p)+get_cell(x+1,y-1,p)+
get_cell(x-1,y,p)+ get_cell(x+1,y,p)+
get_cell(x-1,y+1,p)+get_cell(x,y+1,p)+get_cell(x+1,y+1,p);
return neighbor;
}
private void calc_cells()
{
for (int y = 0; y < 64 /*cell_size*/; y++)
{
for (int x = 0; x < 64 /*cell_size*/; x++)
{
byte me = get_cell(x, y, calc_page);
set_cell(x, y, draw_page, me);
int neighbor = get_neighbor(x, y , calc_page);
if (me == (byte)0)
{
if (neighbor == 3)
{
set_cell(x, y, draw_page, (byte)1);
}
}
else
{
if ((neighbor < 2) || (neighbor > 3))
{
set_cell(x, y, draw_page, (byte)0);
}
}
}
}
}
private void draw_cells()
{
int width = dot_size;
int height = dot_size;
int dx = width << 2 /*bpp_bits*/;
int dy = 0;
for (int i = 0; i < height; i++)
{
dy += line_bytes;
}
int fby = fb_addr;
for (int y = 0; y < 64 /*cell_size*/; y++)
{
int fbx = fby;
for (int x = 0; x < 64 /*cell_size*/; x++)
{
int cd = get_cell(x, y, draw_page);
int cc = get_cell(x, y, calc_page);
if (cd != cc)
{
if (cd == (byte)1)
{
fill_rect(fbx, 0xffffffff /*on_color*/, width, height);
}
else
{
fill_rect(fbx, 0xff000000 /*off_color*/, width, height);
}
}
fbx += dx;
}
fby += dy;
}
}
public void run()
{
calc_cells();
draw_cells();
int p = calc_page;
calc_page = draw_page;
draw_page = p;
}
}
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// AXI4-Lite slave interface // To write: 1:write data_write, 2:write control with write_enable=1 and req=1, 3:poll until ack==1, 4:write control with write_enable=1 and req=0, 5:poll until ack==0 // To read: 1:write control with write_enable=0 and req=1, 2:poll until ack==1, 3:write control with write_enable=0 and req=0, 4:poll until ack==0, 5:read data_read // addr:0xXXXXXXX0 :(w) control // [31:24]:parameter_number, [1]:write_enable(1:write 0:read) [0]:req(1:go 0:idle) // addr:0xXXXXXXX4 :(w) data_write // [31:0]:data // addr:0xXXXXXXX8 :(r) ack // [0]:ack 0:normal 1:done & wait for req=0 // addr:0xXXXXXXXC :(r) data_read // [31:0]:data
// AXI4-Lite slave
always @(posedge S_AXI_ACLK)
begin
if (S_AXI_ARESETN == 1'b0)
begin
s_axi_awready <= 1'b0;
s_axi_wready <= 1'b0;
s_axi_bvalid <= 1'b0;
s_axi_arready <= 1'b0;
s_axi_rvalid <= 1'b0;
s_axi_bresp <= 2'b00;
s_axi_rresp <= 2'b00;
state_s <= C_STATE_S_ADDR;
end
else
begin
case (state_s)
C_STATE_S_ADDR:
begin // address decode
if ((S_AXI_AWVALID == 1'b1) && (S_AXI_AWADDR[31:C_S_ADDR_MASK_LSB] == C_BASEADDR[31:C_S_ADDR_MASK_LSB])) // write: get the address
begin
s_address <= S_AXI_AWADDR;
s_axi_awready <= 1'b1;
state_s <= C_STATE_S_W_DATA;
end
else if ((S_AXI_ARVALID == 1'b1) && (S_AXI_ARADDR[31:C_S_ADDR_MASK_LSB] == C_BASEADDR[31:C_S_ADDR_MASK_LSB])) // read: get the address
begin
s_address <= S_AXI_ARADDR;
s_axi_arready <= 1'b1;
state_s <= C_STATE_S_R_DATA;
end
end // write: get the data
C_STATE_S_W_DATA:
if (S_AXI_WVALID == 1'b1)
begin
case (s_address[3:2])
2'd0: // addr: 0xXXXXXXX0
begin // write control data
sync_a_addr <= S_AXI_WDATA[31:24];
sync_a_we <= S_AXI_WDATA[1];
sync_a_req <= S_AXI_WDATA[0];
end
2'd1: // addr: 0xXXXXXXX4
begin // write data
sync_a_data <= S_AXI_WDATA;
end
default: ;
endcase
s_axi_awready <= 1'b0;
s_axi_wready <= 1'b1;
s_axi_bvalid <= 1'b1;
state_s <= C_STATE_S_W_RESPONSE;
end // write: wait for bready
C_STATE_S_W_RESPONSE:
if (S_AXI_BREADY == 1'b1)
begin
s_axi_wready <= 1'b0;
s_axi_bvalid <= 1'b0;
state_s <= C_STATE_S_ADDR;
end // read: pass the data
C_STATE_S_R_DATA:
begin
case (s_address[3:2])
2'd2: // addr: 0xXXXXXXX8
begin // read ack
s_axi_rdata <= sync_b2a_ack;
end
2'd3: // addr: 0xXXXXXXXC
begin // read data
s_axi_rdata <= sync_b2a_data;
end
default: ;
endcase
s_axi_arready <= 1'b0;
s_axi_rvalid <= 1'b1;
state_s <= C_STATE_S_R_READY;
end // read: wait for rready
C_STATE_S_R_READY:
if (S_AXI_RREADY == 1'b1)
begin
s_axi_rvalid <= 1'b0;
state_s <= C_STATE_S_ADDR;
end
default: ;
endcase
end
end
// ---- state machine A ---- // 1. to start, if B2A_ACK == low, goto 2 else goto 1 // 2. set A_ADDR and A_DATA, set A_REQ high // 3. poll B2A_ACK, if B2A_ACK == high, set A_REQ low // 4. poll B2A_ACK, if B2A_ACK == low, goto 1 // ---- state machine B ---- // 1. poll A2B_REQ, if A2B_REQ == high and B_ACK == low, get A_ADDR and A_DATA, set B_ACK high // 2. poll A2B_REQ, if A2B_REQ == low, set B_ACK low, goto 1
// class Template controller // reg addr: // 0: go command sync_a2b_data[0] 0:init 1:run // 1: GPIO0 sync_a2b_data[31:0] // 2: GPIO1 sync_a2b_data[31:0] // 3: GPIO2 sync_a2b_data[31:0] // 4: GPIO3 sync_a2b_data[31:0]
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 1'b0)
begin
sync_b_ack <= 1'b0;
sync_b_data <= 1'b0;
class_obj_0000_run_req <= 1'b0;
state_m_c <= C_STATE_M_C_IDLE;
end
else
begin
case (state_m_c)
C_STATE_M_C_IDLE:
begin
if (sync_a2b_req == 1'b1)
begin
m_c_we <= sync_a2b_we;
m_c_address <= sync_a2b_addr;
if (sync_a2b_we == 1'b1)
begin // command / parameter write
case (sync_a2b_addr)
C_M_C_ADDR_GO:
begin
case (sync_a2b_data[0])
1'b0:
begin
class_obj_0000_init_req <= 1'b1;
state_m_c <= C_STATE_M_C_INIT1;
end
1'b1:
begin
class_obj_0000_run_req <= 1'b1;
state_m_c <= C_STATE_M_C_RUN1;
end
default: ;
endcase
end
C_M_C_ADDR_GPIO0:
begin
class_obj_0000_gpio0_in <= sync_a2b_data;
class_obj_0000_gpio0_we <= 1'b1;
state_m_c <= C_STATE_M_C_PARAM_W;
end
C_M_C_ADDR_GPIO1:
begin
class_obj_0000_gpio1_in <= sync_a2b_data;
class_obj_0000_gpio1_we <= 1'b1;
state_m_c <= C_STATE_M_C_PARAM_W;
end
C_M_C_ADDR_GPIO2:
begin
class_obj_0000_gpio2_in <= sync_a2b_data;
class_obj_0000_gpio2_we <= 1'b1;
state_m_c <= C_STATE_M_C_PARAM_W;
end
C_M_C_ADDR_GPIO3:
begin
class_obj_0000_gpio3_in <= sync_a2b_data;
class_obj_0000_gpio3_we <= 1'b1;
state_m_c <= C_STATE_M_C_PARAM_W;
end
default: ;
endcase
end
else
begin // parameter read
case (sync_a2b_addr)
C_M_C_ADDR_GPIO0:
begin
sync_b_data <= class_obj_0000_gpio0_out;
end
C_M_C_ADDR_GPIO1:
begin
sync_b_data <= class_obj_0000_gpio1_out;
end
C_M_C_ADDR_GPIO2:
begin
sync_b_data <= class_obj_0000_gpio2_out;
end
C_M_C_ADDR_GPIO3:
begin
sync_b_data <= class_obj_0000_gpio3_out;
end
default: ;
endcase
state_m_c <= C_STATE_M_C_PARAM_R;
end
end
end
C_STATE_M_C_INIT1:
begin
class_obj_0000_init_req <= 1'b0; // pulse
if (class_obj_0000_init_busy == 1'b1)
begin
state_m_c <= C_STATE_M_C_INIT2;
end
end
C_STATE_M_C_INIT2:
begin
if (class_obj_0000_init_busy == 1'b0)
begin
sync_b_ack <= 1'b1;
state_m_c <= C_STATE_M_C_FINISH;
end
end
C_STATE_M_C_RUN1:
begin
class_obj_0000_run_req <= 1'b0; // pulse
if (class_obj_0000_run_busy == 1'b1)
begin
state_m_c <= C_STATE_M_C_RUN2;
end
end
C_STATE_M_C_RUN2:
begin
if (class_obj_0000_run_busy == 1'b0)
begin
sync_b_ack <= 1'b1;
state_m_c <= C_STATE_M_C_FINISH;
end
end
C_STATE_M_C_PARAM_W:
begin
case (m_c_address)
C_M_C_ADDR_GPIO0:
begin
class_obj_0000_gpio0_we <= 1'b0;
end
C_M_C_ADDR_GPIO1:
begin
class_obj_0000_gpio1_we <= 1'b0;
end
C_M_C_ADDR_GPIO2:
begin
class_obj_0000_gpio2_we <= 1'b0;
end
C_M_C_ADDR_GPIO3:
begin
class_obj_0000_gpio3_we <= 1'b0;
end
default: ;
endcase
sync_b_ack <= 1'b1;
state_m_c <= C_STATE_M_C_FINISH;
end
C_STATE_M_C_PARAM_R:
begin
sync_b_ack <= 1'b1;
state_m_c <= C_STATE_M_C_FINISH;
end
C_STATE_M_C_FINISH:
begin
if (sync_a2b_req == 1'b0)
begin
sync_b_ack <= 1'b0;
state_m_c <= C_STATE_M_C_IDLE;
end
end
default: ;
endcase
end
end
// AXI master write
assign M_AXI_WLAST = (m_w_burst_count == m_axi_awlen) ? 1'b1 : 1'b0;
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 1'b0)
begin
m_axi_awid <= 1'b0;
m_axi_awburst <= 2'b01; // INCR
m_axi_awlock <= 2'b00;
m_axi_awcache <= 4'b0011; // Normal non-cacheable bufferable
m_axi_awprot <= 3'b000;
m_axi_awvalid <= 1'b0;
m_axi_wstrb <= {C_M_STRB_WIDTH{1'b1}};
m_axi_awaddr <= 32'h00000000;
m_axi_wdata <= 32'h00000000;
m_axi_awlen <= 1'd0;
class_obj_0000_wbusy_in <= 1'b0;
class_obj_0000_wbusy_we <= 1'b1;
state_m_w <= C_STATE_M_W_IDLE;
end
else
begin
case (state_m_w)
C_STATE_M_W_IDLE:
begin
if (class_obj_0000_wreq_out == 1'b1)
begin
class_obj_0000_wbusy_in <= 1'b1;
class_obj_0000_wbusy_we <= 1'b1;
m_axi_awaddr <= class_obj_0000_waddr_out;
m_axi_awlen <= class_obj_0000_wburst_out;
m_axi_wdata <= class_obj_0000_wdata_out;
m_axi_awvalid <= 1'b1;
state_m_w <= C_STATE_M_W_ADDR;
end
end
C_STATE_M_W_ADDR:
begin
if (M_AXI_AWREADY == 1'b1)
begin
m_axi_bready <= 1'b1;
m_axi_awvalid <= 1'b0;
m_axi_wvalid <= 1'b1;
m_w_burst_count <= 8'd0;
state_m_w <= C_STATE_M_W_DATA;
end
end
C_STATE_M_W_DATA:
begin
if (M_AXI_WREADY == 1'b1)
begin
if (m_w_burst_count < m_axi_awlen)
begin
m_w_burst_count <= m_w_burst_count + 1'd1;
end
else
begin
m_axi_wvalid <= 1'b0;
state_m_w <= C_STATE_M_W_RESPONSE;
end
end
end
C_STATE_M_W_RESPONSE:
begin
if (M_AXI_BVALID == 1'b1)
begin
m_axi_bready <= 1'b0;
class_obj_0000_wbusy_in <= 1'b0;
class_obj_0000_wbusy_we <= 1'b1;
state_m_w <= C_STATE_M_W_IDLE;
end
end
default: ;
endcase
end
end
// AXI master read
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 1'b0)
begin
m_axi_arid <= 1'b0;
m_axi_arburst <= 2'b01; // INCR
m_axi_arlock <= 2'b00;
m_axi_arcache <= 4'b0011; // Normal non-cacheable bufferable
m_axi_arprot <= 3'b000;
m_axi_arlen <= 8'd0;
m_axi_araddr <= 32'h00000000;
class_obj_0000_rbusy_in <= 1'b0;
class_obj_0000_rbusy_we <= 1'b1;
state_m_r <= C_STATE_M_R_IDLE;
end
else
begin
case (state_m_r)
C_STATE_M_R_IDLE:
begin
if (class_obj_0000_rreq_out == 1'b1)
begin
class_obj_0000_rbusy_in <= 1'b1;
class_obj_0000_rbusy_we <= 1'b1;
m_axi_araddr <= class_obj_0000_raddr_out;
m_axi_arvalid <= 1'b1;
m_axi_rready <= 1'b0;
state_m_r <= C_STATE_M_R_ADDR;
end
end
C_STATE_M_R_ADDR:
begin
if (M_AXI_ARREADY == 1'b1)
begin
m_axi_arvalid <= 1'b0;
m_axi_rready <= 1'b1;
state_m_r <= C_STATE_M_R_DATA;
end
end
C_STATE_M_R_DATA:
begin
if (M_AXI_RVALID == 1'b1)
begin
class_obj_0000_rdata_in <= M_AXI_RDATA;
class_obj_0000_rdata_we <= 1'b1;
m_axi_rready <= 1'b0;
class_obj_0000_rbusy_in <= 1'b0;
class_obj_0000_rbusy_we <= 1'b1;
state_m_r <= C_STATE_M_R_IDLE;
end
end
default: ;
endcase
end
end
always @(posedge A_CLK)
begin
if (A_RESETN == 1'b0)
begin
B2A_ACK <= 1'b0;
B2A_DATA <= 1'b0;
for (ia = 4'd0; ia < 4'd3; ia = ia + 4'd1)
begin
ack[ia] <= 1'b0;
end
end
else
begin
ack[0] <= B_ACK;
ack[1] <= ack[0];
ack[2] <= ack[1];
data_b[0] <= B_DATA;
data_b[1] <= data_b[0];
B2A_DATA <= data_b[1];
if ((ack[1] == ack[2]) && (ack[2] != B2A_ACK))
B2A_ACK <= ack[2];
end
end
always @(posedge B_CLK)
begin
if (B_RESETN == 1'b0)
begin
A2B_REQ <= 1'b0;
A2B_ADDR <= 1'b0;
A2B_DATA <= 1'b0;
A2B_WE <= 1'b0;
for (ib = 4'd0; ib < 4'd3; ib = ib + 4'd1)
begin
req[ib] <= 1'b0;
end
end
else
begin
req[0] <= A_REQ;
req[1] <= req[0];
req[2] <= req[1];
we[0] <= A_WE;
we[1] <= we[0];
A2B_WE <= we[1];
addr[0] <= A_ADDR;
addr[1] <= addr[0];
A2B_ADDR <= addr[1];
data_a[0] <= A_DATA;
data_a[1] <= data_a[0];
A2B_DATA <= data_a[1];
if ((req[1] == req[2]) && (req[2] != A2B_REQ))
A2B_REQ <= req[2];
end
end
endmodule
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
initial
begin
$dumpfile("wave.vcd");
$dumpvars(5, synthesijer_template_tb);
end
// generate clock slave
initial
begin
S_AXI_ACLK = 1'b1;
forever
begin
#(STEP / 2) S_AXI_ACLK = ~S_AXI_ACLK;
end
end
// generate reset slave
initial
begin
S_AXI_ARESETN <= 1'b1;
@(posedge S_AXI_ACLK) S_AXI_ARESETN <= 1'b0;
@(posedge S_AXI_ACLK) S_AXI_ARESETN <= 1'b1;
end
// generate clock master
initial
begin
M_AXI_ACLK = 1'b1;
forever
begin
#(STEPM / 2) M_AXI_ACLK = ~M_AXI_ACLK;
if ($stime > 10000)
begin
$finish;
end
end
end
// generate reset master
initial
begin
M_AXI_ARESETN <= 1'b1;
@(posedge M_AXI_ACLK) M_AXI_ARESETN <= 1'b0;
@(posedge M_AXI_ACLK) M_AXI_ARESETN <= 1'b1;
end
// Application interface: Data write
task app_write
(
input [7:0] reg_addr,
input [31:0] data
);
begin // poll ack == 0
fake_axi_master_read(BASE_ADDR + REG_ADDR_ACK);
while (master_read_data[0] != 1'b0)
begin
fake_axi_master_read(BASE_ADDR + REG_ADDR_ACK);
end // write data
fake_axi_master_write(BASE_ADDR + REG_ADDR_WDATA, data); // write control
fake_axi_master_write(BASE_ADDR + REG_ADDR_CONTROL, {reg_addr, 22'b0, 1'b1, 1'b1}); // poll ack == 1
fake_axi_master_read(BASE_ADDR + REG_ADDR_ACK);
while (master_read_data[0] != 1'b1)
begin
fake_axi_master_read(BASE_ADDR + REG_ADDR_ACK);
end // write req <= 0
fake_axi_master_write(BASE_ADDR + REG_ADDR_CONTROL, {reg_addr, 22'b0, 1'b1, 1'b0}); // poll ack == 0
fake_axi_master_read(BASE_ADDR + REG_ADDR_ACK);
while (master_read_data[0] != 1'b0)
begin
fake_axi_master_read(BASE_ADDR + REG_ADDR_ACK);
end
end
endtask
// Application interface: Data read
task app_read
(
input [7:0] reg_addr
);
begin // poll ack == 0
fake_axi_master_read(BASE_ADDR + REG_ADDR_ACK);
while (master_read_data[0] != 1'b0)
begin
fake_axi_master_read(BASE_ADDR + REG_ADDR_ACK);
end // write control
fake_axi_master_write(BASE_ADDR + REG_ADDR_CONTROL, {reg_addr, 22'b0, 1'b0, 1'b1}); // poll ack == 1
fake_axi_master_read(BASE_ADDR + REG_ADDR_ACK);
while (master_read_data[0] != 1'b1)
begin
fake_axi_master_read(BASE_ADDR + REG_ADDR_ACK);
end // write req <= 0
fake_axi_master_write(BASE_ADDR + REG_ADDR_CONTROL, {reg_addr, 22'b0, 1'b0, 1'b0}); // poll ack == 0
fake_axi_master_read(BASE_ADDR + REG_ADDR_ACK);
while (master_read_data[0] != 1'b0)
begin
fake_axi_master_read(BASE_ADDR + REG_ADDR_ACK);
end // read data
fake_axi_master_read(BASE_ADDR + REG_ADDR_RDATA);
app_read_data = master_read_data;
end
endtask
// initialize
initial
begin
repeat(4) @(posedge S_AXI_ACLK);
// run Test
app_write(8'd1, 32'h2d100000); // fb address
app_write(8'd2, 32'd5120); // line bytes
app_write(8'd3, 32'd11); // dot size
app_write(8'd0, 32'd0); // run init()
app_write(8'd0, 32'd1); // run run()
repeat(4) @(posedge S_AXI_ACLK);
$finish;
end
// fake master->slave
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_AWVALID == 1'b1)
begin
M_AXI_AWREADY <= 1'b1;
end
if (M_AXI_WVALID == 1'b1)
begin
M_AXI_AWREADY <= 1'b0;
M_AXI_WREADY <= 1'b1;
end
if (M_AXI_WVALID == 1'b0)
begin
M_AXI_WREADY <= 1'b0;
end
if ((M_AXI_WLAST == 1'b1) && (M_AXI_WREADY == 1'b1))
begin
M_AXI_BVALID <= 1'b1;
end
if (M_AXI_BREADY == 1'b0)
begin
M_AXI_BVALID <= 1'b0;
end
end
// fake slave->master
integer m2s_burst_len;
integer m2s_burst_count;
integer m2s_data;
integer m2s_i;
initial
begin
M_AXI_RLAST <= 1'b0;
end
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARVALID == 1'b1)
begin
M_AXI_ARREADY <= 1'b1;
m2s_burst_len <= M_AXI_ARLEN;
m2s_burst_count <= 0;
@(posedge M_AXI_ACLK);
M_AXI_ARREADY <= 1'b0;
for (m2s_i = 0; m2s_i <= m2s_burst_len; m2s_i = m2s_i + 1)
begin
M_AXI_RDATA <= m2s_i;
M_AXI_RVALID <= 1'b1;
if (m2s_i == m2s_burst_len)
begin
M_AXI_RLAST <= 1'b1;
end
@(posedge M_AXI_ACLK);
end
M_AXI_RVALID <= 1'b0;
M_AXI_RLAST <= 1'b0;
@(posedge M_AXI_ACLK);
end
end
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/