URL
https://opencores.org/ocsvn/apb_mstr/apb_mstr/trunk
Subversion Repositories apb_mstr
Compare Revisions
- This comparison shows the changes necessary to convert path
/apb_mstr
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/trunk/run/run.bat
0,0 → 1,6
|
echo off |
|
..\..\..\robust.exe ../src/base/apb_master.v -od out -I ../src/gen -list list.txt -listpath -header |
|
echo Completed RobustVerilog APB master run - results in run/out/ |
/trunk/run/run.sh
0,0 → 1,5
#!/bin/bash |
|
../../../robust ../src/base/apb_master.v -od out -I ../src/gen -list list.txt -listpath -header |
|
echo Completed RobustVerilog APB master run - results in run/out/ |
/trunk/src/gen/prgen_fifo.v
0,0 → 1,196
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
IFDEF STUB |
OUTFILE prgen_fifo_stub.v |
module prgen_fifo_stub(PORTS); |
ELSE STUB |
OUTFILE prgen_fifo.v |
module prgen_fifo(PORTS); |
ENDIF STUB |
|
parameter WIDTH = 8; |
parameter DEPTH_FULL = 8; |
|
parameter SINGLE = DEPTH_FULL == 1; |
parameter DEPTH = SINGLE ? 1 : DEPTH_FULL -1; |
parameter DEPTH_BITS = |
(DEPTH <= 2) ? 1 : |
(DEPTH <= 4) ? 2 : |
(DEPTH <= 8) ? 3 : |
(DEPTH <= 16) ? 4 : |
(DEPTH <= 32) ? 5 : |
(DEPTH <= 64) ? 6 : |
(DEPTH <= 128) ? 7 : |
(DEPTH <= 256) ? 8 : |
(DEPTH <= 512) ? 9 : 0; //0 is ilegal |
|
parameter LAST_LINE = DEPTH-1; |
|
|
|
input clk; |
input reset; |
|
input push; |
input pop; |
input [WIDTH-1:0] din; |
output [WIDTH-1:0] dout; |
IF STUB output [DEPTH_BITS:0] fullness; |
output empty; |
output full; |
|
|
wire reg_push; |
wire reg_pop; |
wire fifo_push; |
wire fifo_pop; |
|
reg [DEPTH-1:0] full_mask_in; |
reg [DEPTH-1:0] full_mask_out; |
reg [DEPTH-1:0] full_mask; |
reg [WIDTH-1:0] fifo [DEPTH-1:0]; |
wire fifo_empty; |
wire next; |
reg [WIDTH-1:0] dout; |
reg dout_empty; |
reg [DEPTH_BITS-1:0] ptr_in; |
reg [DEPTH_BITS-1:0] ptr_out; |
|
|
|
|
assign reg_push = push & fifo_empty & (dout_empty | pop); |
assign reg_pop = pop & fifo_empty; |
assign fifo_push = !SINGLE & push & (~reg_push); |
assign fifo_pop = !SINGLE & pop & (~reg_pop); |
|
|
always @(posedge clk or posedge reset) |
if (reset) |
begin |
dout <= #FFD {WIDTH{1'b0}}; |
dout_empty <= #FFD 1'b1; |
end |
else if (reg_push) |
begin |
dout <= #FFD din; |
dout_empty <= #FFD 1'b0; |
end |
else if (reg_pop) |
begin |
dout <= #FFD {WIDTH{1'b0}}; |
dout_empty <= #FFD 1'b1; |
end |
else if (fifo_pop) |
begin |
dout <= #FFD fifo[ptr_out]; |
dout_empty <= #FFD 1'b0; |
end |
|
always @(posedge clk or posedge reset) |
if (reset) |
ptr_in <= #FFD {DEPTH_BITS{1'b0}}; |
else if (fifo_push) |
ptr_in <= #FFD ptr_in == LAST_LINE ? 0 : ptr_in + 1'b1; |
|
always @(posedge clk or posedge reset) |
if (reset) |
ptr_out <= #FFD {DEPTH_BITS{1'b0}}; |
else if (fifo_pop) |
ptr_out <= #FFD ptr_out == LAST_LINE ? 0 : ptr_out + 1'b1; |
|
always @(posedge clk) |
if (fifo_push) |
fifo[ptr_in] <= #FFD din; |
|
|
always @(/*AUTOSENSE*/fifo_push or ptr_in) |
begin |
full_mask_in = {DEPTH{1'b0}}; |
full_mask_in[ptr_in] = fifo_push; |
end |
|
always @(/*AUTOSENSE*/fifo_pop or ptr_out) |
begin |
full_mask_out = {DEPTH{1'b0}}; |
full_mask_out[ptr_out] = fifo_pop; |
end |
|
always @(posedge clk or posedge reset) |
if (reset) |
full_mask <= #FFD {DEPTH{1'b0}}; |
else if (fifo_push | fifo_pop) |
full_mask <= #FFD (full_mask & (~full_mask_out)) | full_mask_in; |
|
|
assign next = |full_mask; |
assign fifo_empty = ~next; |
assign empty = fifo_empty & dout_empty; |
assign full = SINGLE ? !dout_empty : &full_mask; |
|
|
|
IFDEF STUB |
reg [DEPTH_BITS:0] fullness; |
|
always @(posedge clk or posedge reset) |
if (reset) |
fullness <= #FFD {DEPTH_BITS+1{1'b0}}; |
else if (push | pop) |
fullness <= #FFD fullness + push - pop; |
|
wire overflow = full & fifo_push & (~fifo_pop); |
wire underflow = empty & fifo_pop & (~fifo_push); |
|
always @(posedge overflow) |
begin |
#1; |
if (overflow) |
begin |
$display("-E-%m - overflow.\tTime: %0d ns", $time); |
#1000; |
$finish; |
end |
end |
always @(posedge underflow) |
begin |
#1; |
if (underflow) |
begin |
$display("-E-%m - underflow.\tTime: %0d ns", $time); |
#1000; |
$finish; |
end |
end |
ENDIF STUB |
|
endmodule |
|
|
/trunk/src/gen/prgen_rand.v
0,0 → 1,87
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
function integer rand_chance; |
input [31:0] chance_true; |
|
begin |
if (chance_true > 100) |
begin |
$display("RAND_CHANCE-E-: fatal error, rand_chance called with percent chance larger than 100.\tTime: %0d ns", $time); |
$finish; |
end |
rand_chance = (rand(1,100) <= chance_true); |
end |
endfunction // rand_chance |
|
|
function integer rand; |
input [31:0] min; |
input [31:0] max; |
|
integer range; |
begin |
if (min > max) |
begin |
$display("RAND-E-: fatal error, rand was called with min larger than max.\tTime: %0d ns", $time); |
$finish; |
end |
|
range = (max - min) + 1; |
if (range == 0) range = -1; |
rand = min + ($random % range); |
end |
endfunction // rand |
|
|
function integer align; |
input [31:0] num; |
input [31:0] align_size; |
|
integer align; |
begin |
align = num - (num % align_size); |
end |
endfunction |
|
|
function integer rand_align; |
input [31:0] min; |
input [31:0] max; |
input [31:0] align; |
|
integer rand_align; |
begin |
rand_align = rand(min, max); |
|
if (rand_align > align) |
rand_align = align(rand_align, align); |
end |
endfunction |
|
/trunk/src/base/axi2apb_rd.v
0,0 → 1,76
<##////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
//////////////////////////////////////////////////////////////////##> |
|
INCLUDE def_axi2apb.txt |
OUTFILE PREFIX_axi2apb_rd.v |
|
module PREFIX_axi2apb_rd (PORTS); |
|
input clk; |
input reset; |
|
input GROUP_APB3; |
|
input cmd_err; |
input [ID_BITS-1:0] cmd_id; |
output finish_rd; |
|
port RGROUP_APB_AXI_R; |
|
|
parameter RESP_OK = 2'b00; |
parameter RESP_SLVERR = 2'b10; |
parameter RESP_DECERR = 2'b11; |
|
reg RGROUP_APB_AXI_R.OUT; |
|
|
assign finish_rd = RVALID & RREADY & RLAST; |
|
always @(posedge clk or posedge reset) |
if (reset) |
begin |
RGROUP_APB_AXI_R.OUT <= #FFD {GROUP_APB_AXI_R.OUT.WIDTH{1'b0}}; |
end |
else if (finish_rd) |
begin |
RGROUP_APB_AXI_R.OUT <= #FFD {GROUP_APB_AXI_R.OUT.WIDTH{1'b0}}; |
end |
else if (psel & penable & (~pwrite) & pready) |
begin |
RID <= #FFD cmd_id; |
RDATA <= #FFD prdata; |
RRESP <= #FFD cmd_err ? RESP_SLVERR : pslverr ? RESP_DECERR : RESP_OK; |
RLAST <= #FFD 1'b1; |
RVALID <= #FFD 1'b1; |
end |
|
endmodule |
|
|
/trunk/src/base/def_apb_master_static.txt
0,0 → 1,46
<##////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
//////////////////////////////////////////////////////////////////##> |
|
INCLUDE def_axi_master.txt |
|
SWAP.GLOBAL DATA_BITS 32 ##AXI and APB data bits |
|
SWAP.GLOBAL ID_NUM 1 ##Number of IDs (internal masters) |
SWAP.GLOBAL ID0_VAL ID_BITS'b0000 ##AXI ID0 |
|
GROUP STUB_AXI_A overrides { |
ID ID_BITS output |
ADDR ADDR_BITS output |
LEN LEN_BITS output |
SIZE SIZE_BITS output |
VALID 1 output |
READY 1 input |
} |
|
|
/trunk/src/base/apb_master.v
0,0 → 1,172
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
////////////////////////////////////// |
// |
// General: |
// The APB master is built of an AXI master and an AXI2APB bridge. |
// The stub support APB (Amba2) and APB3 (Amba3) protocols, |
// the define APB3 determines this (in def_apb_master.txt) |
// |
// |
// Tasks: |
// |
// write_single(input addr, input wdata) |
// Description: write a single APB burst |
// Parameters: |
// addr - address |
// wdata - write data |
// |
// read_single(input master_num, input addr, output rdata) |
// Description: read a single AB burst |
// Parameters: |
// addr - address |
// rdata - return read data |
// |
// check_single(input master_num, input addr, input expected) |
// Description: read a single AB burst and give an error if the data read does not match expected |
// Parameters: |
// addr - address |
// expected - expected read data |
// |
// write_and_check_single(input master_num, input addr, input data) |
// Description: write a single AB burst read it back and give an error if the write and read data don't match |
// Parameters: |
// addr - address |
// data - data to write and expect on read |
// |
// |
////////////////////////////////////// |
|
|
OUTFILE apb_master.v |
|
INCLUDE def_apb_master.txt |
|
VERIFY (DATA_BITS==32) else only 32 bit data supported |
|
module apb_master(PORTS); |
|
|
input clk; |
input reset; |
|
output psel; |
output penable; |
output [ADDR_BITS-1:0] paddr; |
output pwrite; |
output [DATA_BITS-1:0] pwdata; |
input [DATA_BITS-1:0] prdata; |
IFDEF APB3 |
input pslverr; |
input pready; |
ELSE APB3 |
|
wire pslverr = 1'b0; |
wire pready = 1'b1; |
ENDIF APB3 |
|
wire GROUP_STUB_AXI; |
|
|
//set random tasks to be only 32 bit singles |
initial |
begin |
#1; |
apb_master_axi_master.enable_all; |
apb_master_axi_master.use_addr_base=1; |
apb_master_axi_master.len_min=0; |
apb_master_axi_master.len_max=0; |
apb_master_axi_master.size_min=2; |
apb_master_axi_master.size_max=2; |
end |
|
|
CREATE axi_master.v DEFCMD(SWAP.GLOBAL CONST(PREFIX) apb_master_axi_master) |
|
apb_master_axi_master apb_master_axi_master( |
.clk(clk), |
.reset(reset), |
.GROUP_STUB_AXI(GROUP_STUB_AXI), |
.idle() |
); |
|
|
CREATE axi2apb.v DEFCMD(SWAP CONST(SLAVE_NUM) 1) DEFCMD(SWAP.GLOBAL CONST(PREFIX) apb_master) |
|
apb_master_axi2apb apb_master_axi2apb( |
.clk(clk), |
.reset(reset), |
.GROUP_STUB_AXI(GROUP_STUB_AXI), |
|
.penable(penable), |
.pwrite(pwrite), |
.paddr(paddr), |
.pwdata(pwdata), |
.psel(psel), |
.prdata(prdata), |
.pready(pready), |
.pslverr(pslverr) |
); |
|
|
task write_single; |
input [ADDR_BITS-1:0] addr; |
input [DATA_BITS-1:0] wdata; |
begin |
apb_master_axi_master.write_single(0, addr, wdata); |
end |
endtask |
|
task read_single; |
input [ADDR_BITS-1:0] addr; |
output [DATA_BITS-1:0] rdata; |
begin |
apb_master_axi_master.read_single(0, addr, rdata); |
end |
endtask |
|
task check_single; |
input [ADDR_BITS-1:0] addr; |
input [DATA_BITS-1:0] expected; |
begin |
apb_master_axi_master.check_single(0, addr, expected); |
end |
endtask |
|
task write_and_check_single; |
input [ADDR_BITS-1:0] addr; |
input [DATA_BITS-1:0] data; |
begin |
apb_master_axi_master.write_and_check_single(0, addr, data); |
end |
endtask |
|
|
endmodule |
/trunk/src/base/def_axi2apb.txt
0,0 → 1,51
<##////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
//////////////////////////////////////////////////////////////////##> |
|
INCLUDE def_axi2apb_static.txt |
|
SWAP #FFD #1 ## flip-flop delay |
|
SWAP PREFIX soc ## prefix for all modules and file names |
|
SWAP SLAVE_NUM 8 ## number of APB slaves |
|
SWAP CMD_DEPTH 2 ## number of AXI command FIFO |
|
SWAP ADDR_BITS 24 ## AXI and APB address bits |
SWAP ID_BITS 4 ## AXI ID bits |
SWAP DEC_BITS 8 ## Address MSBits for slave decoding |
|
SWAP DEC_ADDR0 DEC_BITS'h00 ## Slave 0 address deciding |
SWAP DEC_ADDR1 DEC_BITS'h01 ## Slave 1 address deciding |
SWAP DEC_ADDR2 DEC_BITS'h02 ## Slave 2 address deciding |
SWAP DEC_ADDR3 DEC_BITS'h03 ## Slave 3 address deciding |
SWAP DEC_ADDR4 DEC_BITS'h10 ## Slave 4 address deciding |
SWAP DEC_ADDR5 DEC_BITS'h11 ## Slave 5 address deciding |
SWAP DEC_ADDR6 DEC_BITS'h12 ## Slave 6 address deciding |
SWAP DEC_ADDR7 DEC_BITS'h13 ## Slave 7 address deciding |
/trunk/src/base/axi2apb_mux.v
0,0 → 1,123
<##////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
//////////////////////////////////////////////////////////////////##> |
|
INCLUDE def_axi2apb.txt |
OUTFILE PREFIX_axi2apb_mux.v |
|
ITER SX |
module PREFIX_axi2apb_mux (PORTS); |
|
|
input clk; |
input reset; |
|
input [ADDR_BITS-1:0] cmd_addr; |
|
input psel; |
output [31:0] prdata; |
output pready; |
output pslverr; |
|
output pselSX; |
|
input preadySX; |
|
input pslverrSX; |
|
input [31:0] prdataSX; |
|
|
|
parameter ADDR_MSB = EXPR(ADDR_BITS-1); |
parameter ADDR_LSB = EXPR(ADDR_BITS-DEC_BITS); |
|
reg pready; |
reg pslverr_pre; |
reg pslverr; |
reg [31:0] prdata_pre; |
reg [31:0] prdata; |
|
reg [SLV_BITS-1:0] slave_num; |
|
always @(*) |
begin |
casex (cmd_addr[ADDR_MSB:ADDR_LSB]) |
DEC_ADDRSX : slave_num = SLV_BITS'dSX; |
|
default : slave_num = SLV_BITS'dSLAVE_NUM; //decode error |
endcase |
end |
|
assign pselSX = psel & (slave_num == SLV_BITS'dSX); |
|
always @(*) |
begin |
case (slave_num) |
SLV_BITS'dSX: pready = preadySX; |
default : pready = 1'b1; //decode error |
endcase |
end |
|
always @(*) |
begin |
case (slave_num) |
SLV_BITS'dSX: pslverr_pre = pslverrSX; |
default : pslverr_pre = 1'b1; //decode error |
endcase |
end |
|
always @(*) |
begin |
case (slave_num) |
SLV_BITS'dSX: prdata_pre = prdataSX; |
default : prdata_pre = {32{1'b0}}; |
endcase |
end |
|
|
always @(posedge clk or posedge reset) |
if (reset) |
begin |
prdata <= #FFD {32{1'b0}}; |
pslverr <= #FFD 1'b0; |
end |
else if (psel & pready) |
begin |
prdata <= #FFD prdata_pre; |
pslverr <= #FFD pslverr_pre; |
end |
else if (~psel) |
begin |
prdata <= #FFD {32{1'b0}}; |
pslverr <= #FFD 1'b0; |
end |
|
endmodule |
|
|
/trunk/src/base/def_axi_master.txt
0,0 → 1,48
<##////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
//////////////////////////////////////////////////////////////////##> |
|
INCLUDE def_axi_master_static.txt |
|
SWAP.GLOBAL #FFD #1 ##Flip-Flop simulation delay |
|
SWAP PREFIX axi_master ##prefix for all module and file names |
|
SWAP ID_BITS 4 ##AXI ID bits |
SWAP ADDR_BITS 32 ##AXI address bits |
SWAP DATA_BITS 64 ##AXI data bits |
SWAP LEN_BITS 4 ##AXI LEN bits |
SWAP SIZE_BITS 2 ##AXI SIZE bits |
|
SWAP CMD_DEPTH 4 ##AXI command depth for read and write |
|
SWAP ID_NUM 3 ##Number of IDs (internal masters) |
SWAP ID0_VAL ID_BITS'b0011 ##AXI ID0 |
SWAP ID1_VAL ID_BITS'b0010 ##AXI ID1 |
SWAP ID2_VAL ID_BITS'b1010 ##AXI ID2 |
|
/trunk/src/base/def_axi2apb_static.txt
0,0 → 1,85
<##////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
//////////////////////////////////////////////////////////////////##> |
|
SWAP SLV_BITS LOG2(EXPR(SLAVE_NUM+1)) ##one more for decerr slave |
|
LOOP SX SLAVE_NUM |
|
GROUP APB3 is { |
psel 1 output |
penable 1 output |
pwrite 1 output |
paddr ADDR_BITS output |
pwdata 32 output |
prdata 32 input |
pslverr 1 input |
pready 1 input |
} |
|
GROUP APB_AXI_A is { |
ID ID_BITS input |
ADDR ADDR_BITS input |
LEN 4 input |
SIZE 2 input |
VALID 1 input |
READY 1 output |
} |
|
GROUP APB_AXI_W is { |
ID ID_BITS input |
DATA 32 input |
STRB 4 input |
LAST 1 input |
VALID 1 input |
READY 1 output |
} |
|
GROUP APB_AXI_B is { |
ID ID_BITS output |
RESP 2 output |
VALID 1 output |
READY 1 input |
} |
|
GROUP APB_AXI_R is { |
ID ID_BITS output |
DATA 32 output |
RESP 2 output |
LAST 1 output |
VALID 1 output |
READY 1 input |
} |
|
GROUP APB_AXI joins { |
GROUP APB_AXI_A prefix_AW |
GROUP APB_AXI_W prefix_W |
GROUP APB_AXI_B prefix_B |
GROUP APB_AXI_A prefix_AR |
GROUP APB_AXI_R prefix_R |
} |
/trunk/src/base/axi2apb.v
0,0 → 1,154
<##////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
//////////////////////////////////////////////////////////////////##> |
|
INCLUDE def_axi2apb.txt |
OUTFILE PREFIX_axi2apb.v |
|
ITER SX |
module PREFIX_axi2apb (PORTS); |
|
input clk; |
input reset; |
|
port GROUP_APB_AXI; |
|
//apb slaves |
IFDEF TRUE(SLAVE_NUM==1) |
port GROUP_APB3; |
ELSE TRUE(SLAVE_NUM==1) |
output penable; |
output pwrite; |
output [ADDR_BITS-1:0] paddr; |
output [31:0] pwdata; |
output pselSX; |
input [31:0] prdataSX; |
input preadySX; |
input pslverrSX; |
ENDIF TRUE(SLAVE_NUM==1) |
|
|
|
wire GROUP_APB3; |
|
//outputs of cmd |
wire cmd_empty; |
wire cmd_read; |
wire [ID_BITS-1:0] cmd_id; |
wire [ADDR_BITS-1:0] cmd_addr; |
wire cmd_err; |
|
//outputs of rd / wr |
wire finish_wr; |
wire finish_rd; |
|
|
assign paddr = cmd_addr; |
assign pwdata = WDATA; |
|
|
CREATE axi2apb_cmd.v |
PREFIX_axi2apb_cmd PREFIX_axi2apb_cmd( |
.clk(clk), |
.reset(reset), |
.AWGROUP_APB_AXI_A(AWGROUP_APB_AXI_A), |
.ARGROUP_APB_AXI_A(ARGROUP_APB_AXI_A), |
.finish_wr(finish_wr), |
.finish_rd(finish_rd), |
.cmd_empty(cmd_empty), |
.cmd_read(cmd_read), |
.cmd_id(cmd_id), |
.cmd_addr(cmd_addr), |
.cmd_err(cmd_err) |
); |
|
|
CREATE axi2apb_rd.v |
PREFIX_axi2apb_rd PREFIX_axi2apb_rd( |
.clk(clk), |
.reset(reset), |
.GROUP_APB3(GROUP_APB3), |
.cmd_err(cmd_err), |
.cmd_id(cmd_id), |
.finish_rd(finish_rd), |
.RGROUP_APB_AXI_R(RGROUP_APB_AXI_R), |
STOMP , |
); |
|
CREATE axi2apb_wr.v |
PREFIX_axi2apb_wr PREFIX_axi2apb_wr( |
.clk(clk), |
.reset(reset), |
.GROUP_APB3(GROUP_APB3), |
.cmd_err(cmd_err), |
.cmd_id(cmd_id), |
.finish_wr(finish_wr), |
.WGROUP_APB_AXI_W(WGROUP_APB_AXI_W), |
.BGROUP_APB_AXI_B(BGROUP_APB_AXI_B), |
STOMP , |
); |
|
|
|
CREATE axi2apb_ctrl.v |
PREFIX_axi2apb_ctrl PREFIX_axi2apb_ctrl( |
.clk(clk), |
.reset(reset), |
.finish_wr(finish_wr), |
.finish_rd(finish_rd), |
.cmd_empty(cmd_empty), |
.cmd_read(cmd_read), |
.WVALID(WVALID), |
.psel(psel), |
.penable(penable), |
.pwrite(pwrite), |
.pready(pready) |
); |
|
|
IFDEF TRUE(SLAVE_NUM>1) |
CREATE axi2apb_mux.v |
PREFIX_axi2apb_mux PREFIX_axi2apb_mux( |
.clk(clk), |
.reset(reset), |
.cmd_addr(cmd_addr), |
.psel(psel), |
.prdata(prdata), |
.pready(pready), |
.pslverr(pslverr), |
.pselSX(pselSX), |
.preadySX(preadySX), |
.pslverrSX(pslverrSX), |
.prdataSX(prdataSX), |
STOMP , |
); |
ENDIF TRUE(SLAVE_NUM>1) |
|
endmodule |
|
|
/trunk/src/base/axi_master_stall.v
0,0 → 1,191
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
OUTFILE PREFIX_stall.v |
|
INCLUDE def_axi_master.txt |
|
module PREFIX_stall(PORTS); |
|
`include "prgen_rand.v" |
|
input clk; |
input reset; |
|
input rd_hold; |
input wr_hold; |
|
input ARVALID_pre; |
input RREADY_pre; |
input AWVALID_pre; |
input WVALID_pre; |
input BREADY_pre; |
|
input ARREADY; |
input AWREADY; |
input WREADY; |
|
output ARVALID; |
output RREADY; |
output AWVALID; |
output WVALID; |
output BREADY; |
|
|
reg stall_enable = 1; |
|
integer burst_chance = 1; |
integer burst_len = 10; |
integer burst_val = 90; |
|
integer ar_stall_chance = 10; |
integer r_stall_chance = 10; |
integer aw_stall_chance = 10; |
integer w_stall_chance = 10; |
integer b_stall_chance = 10; |
|
|
integer burst_type; |
reg burst_stall; |
integer ar_stall_chance_valid; |
integer r_stall_chance_valid; |
integer aw_stall_chance_valid; |
integer w_stall_chance_valid; |
integer b_stall_chance_valid; |
|
|
reg ARSTALL_pre = 0; |
reg RSTALL_pre = 0; |
reg AWSTALL_pre = 0; |
reg WSTALL_pre = 0; |
reg BSTALL_pre = 0; |
reg ARSTALL; |
reg RSTALL; |
reg AWSTALL; |
reg WSTALL; |
reg BSTALL; |
|
|
|
assign ARVALID = ARVALID_pre & (~ARSTALL) & (~rd_hold); |
assign RREADY = RREADY_pre & (~RSTALL); |
assign AWVALID = AWVALID_pre & (~AWSTALL) & (~wr_hold); |
assign WVALID = WVALID_pre & (~WSTALL); |
assign BREADY = BREADY_pre & (~BSTALL); |
|
|
task set_stall; |
reg stall; |
begin |
ar_stall_chance_valid = ar_stall_chance; |
r_stall_chance_valid = r_stall_chance; |
aw_stall_chance_valid = aw_stall_chance; |
w_stall_chance_valid = w_stall_chance; |
b_stall_chance_valid = b_stall_chance; |
end |
endtask |
|
initial |
begin |
#FFD; |
set_stall; |
|
if (burst_chance > 0) |
forever |
begin |
burst_stall = rand_chance(burst_chance); |
|
if (burst_stall) |
begin |
#FFD; |
burst_type = rand(1, 5); |
|
case (burst_type) |
1 : ar_stall_chance_valid = burst_val; |
2 : r_stall_chance_valid = burst_val; |
3 : aw_stall_chance_valid = burst_val; |
4 : w_stall_chance_valid = burst_val; |
5 : b_stall_chance_valid = burst_val; |
endcase |
|
repeat (burst_len) @(posedge clk); |
set_stall; |
end |
else |
begin |
@(posedge clk); |
end |
end |
end |
|
always @(posedge clk) |
begin |
#FFD; |
ARSTALL_pre = rand_chance(ar_stall_chance_valid); |
RSTALL_pre = rand_chance(r_stall_chance_valid); |
AWSTALL_pre = rand_chance(aw_stall_chance_valid); |
WSTALL_pre = rand_chance(w_stall_chance_valid); |
BSTALL_pre = rand_chance(b_stall_chance_valid); |
end |
|
always @(posedge clk or posedge reset) |
if (reset) |
begin |
ARSTALL <= #FFD 1'b0; |
RSTALL <= #FFD 1'b0; |
AWSTALL <= #FFD 1'b0; |
WSTALL <= #FFD 1'b0; |
BSTALL <= #FFD 1'b0; |
end |
else if (stall_enable) |
begin |
ARSTALL <= #FFD ARSTALL_pre & ARREADY; |
RSTALL <= #FFD RSTALL_pre; |
AWSTALL <= #FFD AWSTALL_pre & AWREADY; |
WSTALL <= #FFD WSTALL_pre & WREADY; |
BSTALL <= #FFD BSTALL_pre; |
end |
else |
begin |
ARSTALL <= #FFD 1'b0; |
RSTALL <= #FFD 1'b0; |
AWSTALL <= #FFD 1'b0; |
WSTALL <= #FFD 1'b0; |
BSTALL <= #FFD 1'b0; |
end |
|
endmodule |
|
|
|
|
|
|
|
|
/trunk/src/base/def_axi_master_static.txt
0,0 → 1,88
<##////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
//////////////////////////////////////////////////////////////////##> |
|
VERIFY (DATA_BITS <= 64) else stub supports 32 or 64 bits data bus |
VERIFY (SIZE_BITS <= 3) else stub supports 32 or 64 bits data bus |
|
GROUP STUB_AXI_A is { |
ID ID_BITS output |
ADDR ADDR_BITS output |
LEN LEN_BITS output |
SIZE SIZE_BITS output |
BURST 2 output |
CACHE 4 output |
PROT 3 output |
LOCK 2 output |
VALID 1 output |
READY 1 input |
} |
|
GROUP STUB_AXI_W is { |
ID ID_BITS output |
DATA DATA_BITS output |
STRB DATA_BITS/8 output |
LAST 1 output |
VALID 1 output |
READY 1 input |
} |
|
GROUP STUB_AXI_B is { |
ID ID_BITS input |
RESP 2 input |
VALID 1 input |
READY 1 output |
} |
|
GROUP STUB_AXI_R is { |
ID ID_BITS input |
DATA DATA_BITS input |
RESP 2 input |
LAST 1 input |
VALID 1 input |
READY 1 output |
} |
|
GROUP STUB_AXI joins { |
GROUP STUB_AXI_A prefix_AW |
GROUP STUB_AXI_W prefix_W |
GROUP STUB_AXI_B prefix_B |
GROUP STUB_AXI_A prefix_AR |
GROUP STUB_AXI_R prefix_R |
} |
|
GROUP AXI_MASTER_RAND is { |
use_addr_base SON(DEFAULT 0) |
len_min SON(DEFAULT 0) |
len_max SON(DEFAULT 15) |
size_min SON(DEFAULT 0) |
size_max SON(DEFAULT 3) |
addr_min SON(DEFAULT 0) |
addr_max SON(DEFAULT {DATA_BITS{1'b1}}) |
} |
|
/trunk/src/base/axi_master.v
0,0 → 1,336
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
////////////////////////////////////// |
// |
// General: |
// The AXI master has an internal master per ID. |
// These internal masters work simultaniously and an interconnect matrix connets them. |
// |
// |
// I/F : |
// idle - all internal masters emptied their command FIFOs |
// scrbrd_empty - all scoreboard checks have been completed (for random testing) |
// |
// |
// Tasks: |
// |
// enable(input master_num) |
// Description: Enables master |
// Parameters: master_num - number of internal master |
// |
// enable_all() |
// Description: Enables all masters |
// |
// write_single(input master_num, input addr, input wdata) |
// Description: write a single AXI burst (1 data cycle) |
// Parameters: master_num - number of internal master |
// addr - address |
// wdata - write data |
// |
// read_single(input master_num, input addr, output rdata) |
// Description: read a single AXI burst (1 data cycle) |
// Parameters: master_num - number of internal master |
// addr - address |
// rdata - return read data |
// |
// check_single(input master_num, input addr, input expected) |
// Description: read a single AXI burst and gives an error if the data read does not match expected |
// Parameters: master_num - number of internal master |
// addr - address |
// expected - expected read data |
// |
// write_and_check_single(input master_num, input addr, input data) |
// Description: write a single AXI burst read it back and compare the write and read data |
// Parameters: master_num - number of internal master |
// addr - address |
// data - data to write and expect on read |
// |
// insert_wr_cmd(input master_num, input addr, input len, input size) |
// Description: add an AXI write burst to command FIFO |
// Parameters: master_num - number of internal master |
// addr - address |
// len - AXI LEN (data strobe number) |
// size - AXI SIZE (data width) |
// |
// insert_rd_cmd(input master_num, input addr, input len, input size) |
// Description: add an AXI read burst to command FIFO |
// Parameters: master_num - number of internal master |
// addr - address |
// len - AXI LEN (data strobe number) |
// size - AXI SIZE (data width) |
// |
// insert_wr_data(input master_num, input wdata) |
// Description: add a single data to data FIFO (to be used in write bursts) |
// Parameters: master_num - number of internal master |
// wdata - write data |
// |
// insert_wr_incr_data(input master_num, input addr, input len, input size) |
// Description: add an AXI write burst to command FIFO will use incremental data (no need to use insert_wr_data) |
// Parameters: master_num - number of internal master |
// addr - address |
// len - AXI LEN (data strobe number) |
// size - AXI SIZE (data width) |
// |
// insert_rand_chk(input master_num, input burst_num) |
// Description: add multiple commands to command FIFO. Each command writes incremental data to a random address, reads the data back and checks the data. Useful for random testing. |
// Parameters: master_num - number of internal master |
// burst_num - total number of bursts to check |
// |
|
// |
// Parameters: |
// |
// For random testing: (changing these values automatically update interanl masters) |
// len_min - minimum burst AXI LEN (length) |
// len_max - maximum burst AXI LEN (length) |
// size_min - minimum burst AXI SIZE (width) |
// size_max - maximum burst AXI SIZE (width) |
// addr_min - minimum address (in bytes) |
// addr_max - maximum address (in bytes) |
// |
////////////////////////////////////// |
|
OUTFILE PREFIX.v |
|
INCLUDE def_axi_master.txt |
|
|
ITER IX ID_NUM |
module PREFIX(PORTS); |
|
input clk; |
input reset; |
|
port GROUP_STUB_AXI; |
|
output idle; |
output scrbrd_empty; |
|
|
//random parameters |
integer GROUP_AXI_MASTER_RAND = GROUP_AXI_MASTER_RAND.DEFAULT; |
|
wire GROUP_STUB_AXI_IX; |
wire idle_IX; |
wire scrbrd_empty_IX; |
|
|
always @(*) |
begin |
#FFD; |
PREFIX_singleIX.GROUP_AXI_MASTER_RAND = GROUP_AXI_MASTER_RAND; |
end |
|
assign idle = CONCAT(idle_IX &); |
assign scrbrd_empty = CONCAT(scrbrd_empty_IX &); |
|
|
CREATE axi_master_single.v |
|
LOOP IX ID_NUM |
PREFIX_single #(IX, IDIX_VAL, CMD_DEPTH) |
PREFIX_singleIX( |
.clk(clk), |
.reset(reset), |
.GROUP_STUB_AXI(GROUP_STUB_AXI_IX), |
.idle(idle_IX), |
.scrbrd_empty(scrbrd_empty_IX) |
); |
ENDLOOP IX |
|
IFDEF TRUE(ID_NUM==1) |
|
assign GROUP_STUB_AXI.OUT = GROUP_STUB_AXI_0.OUT; |
assign GROUP_STUB_AXI_0.IN = GROUP_STUB_AXI.IN; |
|
ELSE TRUE(ID_NUM==1) |
|
CREATE ic.v DEFCMD(SWAP.GLOBAL PARENT PREFIX) DEFCMD(SWAP.GLOBAL MASTER_NUM ID_NUM) DEFCMD(SWAP.GLOBAL CONST(ID_BITS) ID_BITS) DEFCMD(SWAP.GLOBAL CONST(CMD_DEPTH) CMD_DEPTH) DEFCMD(SWAP.GLOBAL CONST(DATA_BITS) DATA_BITS) DEFCMD(SWAP.GLOBAL CONST(ADDR_BITS) ADDR_BITS) |
LOOP IX ID_NUM |
STOMP NEWLINE |
DEFCMD(LOOP.GLOBAL MIX_IDX 1) |
STOMP NEWLINE |
DEFCMD(SWAP.GLOBAL ID_MIX_ID0 IDIX_VAL) |
ENDLOOP IX |
|
PREFIX_ic PREFIX_ic( |
.clk(clk), |
.reset(reset), |
.MIX_GROUP_STUB_AXI(GROUP_STUB_AXI_IX), |
.S0_GROUP_STUB_AXI(GROUP_STUB_AXI), |
STOMP , |
|
); |
|
ENDIF TRUE(ID_NUM==1) |
|
|
|
task check_master_num; |
input [24*8-1:0] task_name; |
input [31:0] master_num; |
begin |
if (master_num >= ID_NUM) |
begin |
$display("FATAL ERROR: task %0s called for master %0d that does not exist.\tTime: %0d ns.", task_name, master_num, $time); |
end |
end |
endtask |
|
task enable; |
input [31:0] master_num; |
begin |
check_master_num("enable", master_num); |
case (master_num) |
IX : PREFIX_singleIX.enable = 1; |
endcase |
end |
endtask |
|
task enable_all; |
begin |
PREFIX_singleIX.enable = 1; |
end |
endtask |
|
task write_single; |
input [31:0] master_num; |
input [ADDR_BITS-1:0] addr; |
input [DATA_BITS-1:0] wdata; |
begin |
check_master_num("write_single", master_num); |
case (master_num) |
IX : PREFIX_singleIX.write_single(addr, wdata); |
endcase |
end |
endtask |
|
task read_single; |
input [31:0] master_num; |
input [ADDR_BITS-1:0] addr; |
output [DATA_BITS-1:0] rdata; |
begin |
check_master_num("read_single", master_num); |
case (master_num) |
IX : PREFIX_singleIX.read_single(addr, rdata); |
endcase |
end |
endtask |
|
task check_single; |
input [31:0] master_num; |
input [ADDR_BITS-1:0] addr; |
input [DATA_BITS-1:0] expected; |
begin |
check_master_num("check_single", master_num); |
case (master_num) |
IX : PREFIX_singleIX.check_single(addr, expected); |
endcase |
end |
endtask |
|
task write_and_check_single; |
input [31:0] master_num; |
input [ADDR_BITS-1:0] addr; |
input [DATA_BITS-1:0] data; |
begin |
check_master_num("write_and_check_single", master_num); |
case (master_num) |
IX : PREFIX_singleIX.write_and_check_single(addr, data); |
endcase |
end |
endtask |
|
task insert_wr_cmd; |
input [31:0] master_num; |
input [ADDR_BITS-1:0] addr; |
input [LEN_BITS-1:0] len; |
input [SIZE_BITS-1:0] size; |
begin |
check_master_num("insert_wr_cmd", master_num); |
case (master_num) |
IX : PREFIX_singleIX.insert_wr_cmd(addr, len, size); |
endcase |
end |
endtask |
|
task insert_rd_cmd; |
input [31:0] master_num; |
input [ADDR_BITS-1:0] addr; |
input [LEN_BITS-1:0] len; |
input [SIZE_BITS-1:0] size; |
begin |
check_master_num("insert_rd_cmd", master_num); |
case (master_num) |
IX : PREFIX_singleIX.insert_rd_cmd(addr, len, size); |
endcase |
end |
endtask |
|
task insert_wr_data; |
input [31:0] master_num; |
input [DATA_BITS-1:0] wdata; |
begin |
check_master_num("insert_wr_data", master_num); |
case (master_num) |
IX : PREFIX_singleIX.insert_wr_data(wdata); |
endcase |
end |
endtask |
|
task insert_wr_incr_data; |
input [31:0] master_num; |
input [ADDR_BITS-1:0] addr; |
input [LEN_BITS-1:0] len; |
input [SIZE_BITS-1:0] size; |
begin |
check_master_num("insert_wr_incr_data", master_num); |
case (master_num) |
IX : PREFIX_singleIX.insert_wr_incr_data(addr, len, size); |
endcase |
end |
endtask |
|
task insert_rand_chk; |
input [31:0] master_num; |
input [31:0] burst_num; |
begin |
check_master_num("insert_rand_chk", master_num); |
case (master_num) |
IX : PREFIX_singleIX.insert_rand_chk(burst_num); |
endcase |
end |
endtask |
|
|
|
endmodule |
|
|
/trunk/src/base/axi_master_single.v
0,0 → 1,855
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
OUTFILE PREFIX_single.v |
|
INCLUDE def_axi_master.txt |
|
module PREFIX_single(PORTS); |
|
parameter MASTER_NUM = 0; |
parameter MASTER_ID = 0; |
parameter MASTER_PEND = 0; |
|
`include "prgen_rand.v" |
|
parameter MAX_CMDS = 16; //Depth of command FIFO |
parameter DATA_LOG = LOG2(EXPR(DATA_BITS/8)); |
parameter PEND_BITS = |
(MAX_CMDS <= 16) ? 4 : |
(MAX_CMDS <= 32) ? 5 : |
(MAX_CMDS <= 64) ? 6 : |
(MAX_CMDS <= 128) ? 7 : |
(MAX_CMDS <= 256) ? 8 : |
(MAX_CMDS <= 512) ? 9 : 0; //0 is ilegal |
|
|
|
input clk; |
input reset; |
|
port GROUP_STUB_AXI; |
|
output idle; |
output scrbrd_empty; |
|
|
|
//random parameters |
integer GROUP_AXI_MASTER_RAND = GROUP_AXI_MASTER_RAND.DEFAULT; |
|
reg AWVALID_pre; |
reg WVALID_pre; |
wire BREADY_pre; |
reg ARVALID_pre; |
wire RREADY_pre; |
|
reg enable = 0; |
reg rd_enable = 0; |
reg wr_enable = 0; |
reg wait_for_write = 0; |
|
reg scrbrd_enable = 0; |
reg [LEN_BITS-1:0] wvalid_cnt; |
|
reg rd_cmd_push = 0; |
wire rd_cmd_pop; |
wire [PEND_BITS:0] rd_cmd_fullness; |
wire rd_cmd_empty; |
wire rd_cmd_full; |
reg [ADDR_BITS-1:0] rd_cmd_addr_in; |
reg [LEN_BITS-1:0] rd_cmd_len_in; |
reg [SIZE_BITS-1:0] rd_cmd_size_in; |
wire [ADDR_BITS-1:0] rd_cmd_addr; |
wire [LEN_BITS-1:0] rd_cmd_len; |
wire [SIZE_BITS-1:0] rd_cmd_size; |
|
reg rd_resp_push = 0; |
wire rd_resp_pop; |
wire rd_resp_empty; |
wire rd_resp_full; |
reg [ADDR_BITS-1:0] rd_resp_addr_in; |
reg [SIZE_BITS-1:0] rd_resp_size_in; |
wire [ADDR_BITS-1:0] rd_resp_addr; |
wire [SIZE_BITS-1:0] rd_resp_size; |
|
reg wr_cmd_push = 0; |
wire wr_cmd_pop; |
wire [PEND_BITS:0] wr_cmd_fullness; |
wire wr_cmd_empty; |
wire wr_cmd_full; |
reg [ADDR_BITS-1:0] wr_cmd_addr_in; |
reg [LEN_BITS-1:0] wr_cmd_len_in; |
reg [SIZE_BITS-1:0] wr_cmd_size_in; |
wire [ADDR_BITS-1:0] wr_cmd_addr; |
wire [LEN_BITS-1:0] wr_cmd_len; |
wire [SIZE_BITS-1:0] wr_cmd_size; |
|
reg wr_data_push = 0; |
wire wr_data_pop; |
wire [PEND_BITS:0] wr_data_fullness; |
wire wr_data_empty; |
wire wr_data_full; |
reg [ADDR_BITS-1:0] wr_data_addr_in; |
reg [LEN_BITS-1:0] wr_data_len_in; |
reg [SIZE_BITS-1:0] wr_data_size_in; |
wire [ADDR_BITS-1:0] wr_data_addr; |
wire [LEN_BITS-1:0] wr_data_len; |
wire [SIZE_BITS-1:0] wr_data_size; |
wire [DATA_BITS/8-1:0] wr_data_strb; |
wire [7:0] wr_data_bytes; |
wire [ADDR_BITS-1:0] wr_data_addr_prog; |
wire [7:0] wr_data_offset; |
|
wire wr_resp_push; |
reg wr_resp_pop = 0; |
wire wr_resp_empty; |
wire wr_resp_full; |
wire [1:0] wr_resp_resp_in; |
wire [1:0] wr_resp_resp; |
|
reg wr_fifo_push = 0; |
wire wr_fifo_pop; |
wire wr_fifo_empty; |
wire wr_fifo_full; |
reg [DATA_BITS-1:0] wr_fifo_data_in; |
wire [DATA_BITS-1:0] wr_fifo_data; |
|
wire rd_fifo_push; |
reg rd_fifo_pop = 0; |
wire rd_fifo_empty; |
wire rd_fifo_full; |
wire [DATA_BITS-1:0] rd_fifo_data_in; |
wire [1:0] rd_fifo_resp_in; |
wire [DATA_BITS-1:0] rd_fifo_data; |
wire [1:0] rd_fifo_resp; |
|
reg scrbrd_push = 0; |
reg scrbrd_pop = 0; |
wire scrbrd_empty; |
wire scrbrd_full; |
reg [ADDR_BITS-1:0] scrbrd_addr_in; |
reg [DATA_BITS-1:0] scrbrd_data_in; |
reg [DATA_BITS-1:0] scrbrd_mask_in; |
wire [ADDR_BITS-1:0] scrbrd_addr; |
wire [DATA_BITS-1:0] scrbrd_data; |
wire [DATA_BITS-1:0] scrbrd_mask; |
|
integer wr_fullness; |
integer rd_fullness; |
integer rd_completed; |
integer wr_completed; |
integer wr_pend_max = MASTER_PEND; |
integer rd_pend_max = MASTER_PEND; |
wire wr_hold; |
wire rd_hold; |
|
integer rand_chk_num = 0; |
|
|
assign idle = rd_cmd_empty & rd_resp_empty & wr_cmd_empty & wr_data_empty & wr_resp_empty; |
|
always @(rand_chk_num) |
if (rand_chk_num > 0) |
insert_rand_chk_loop(rand_chk_num); |
|
always @(posedge enable) |
begin |
@(posedge clk); |
wr_enable = 1; |
repeat (50) @(posedge clk); |
rd_enable = 1; |
end |
|
//for incremental data |
reg [DATA_BITS-1:0] base_data = 0; |
integer ww; |
initial |
begin |
ww=0; |
while (ww < DATA_BITS/8) |
begin |
base_data = base_data + ((MASTER_NUM + ww) << (ww*8)); |
ww = ww + 1; |
end |
end |
|
assign rd_cmd_pop = ARVALID & ARREADY; |
assign rd_resp_pop = RVALID & RREADY & RLAST; |
assign rd_fifo_push = RVALID & RREADY; |
assign wr_cmd_pop = AWVALID & AWREADY; |
assign wr_data_pop = WVALID & WREADY & WLAST; |
assign wr_fifo_pop = WVALID & WREADY; |
assign wr_resp_push = BVALID & BREADY; |
|
assign RREADY_pre = 1; |
assign BREADY_pre = 1; |
|
|
always @(posedge clk or posedge reset) |
if (reset) |
AWVALID_pre <= #FFD 1'b0; |
else if ((wr_cmd_fullness == 1) & wr_cmd_pop) |
AWVALID_pre <= #FFD 1'b0; |
else if ((!wr_cmd_empty) & wr_enable) |
AWVALID_pre <= #FFD 1'b1; |
|
|
assign AWADDR = wr_cmd_addr; |
assign AWLEN = wr_cmd_len; |
assign AWSIZE = wr_cmd_size; |
assign AWID = MASTER_ID; |
assign AWBURST = 2'd1; //INCR only |
assign AWCACHE = 4'd0; //not supported |
assign AWPROT = 4'd0; //not supported |
assign AWLOCK = 2'd0; //not supported |
|
always @(posedge clk or posedge reset) |
if (reset) |
ARVALID_pre <= #FFD 1'b0; |
else if (((rd_cmd_fullness == 1)) & rd_cmd_pop) |
ARVALID_pre <= #FFD 1'b0; |
else if ((!rd_cmd_empty) & rd_enable) |
ARVALID_pre <= #FFD 1'b1; |
|
assign ARADDR = rd_cmd_addr; |
assign ARLEN = rd_cmd_len; |
assign ARSIZE = rd_cmd_size; |
assign ARID = MASTER_ID; |
assign ARBURST = 2'd1; //INCR only |
assign ARCACHE = 4'd0; //not supported |
assign ARPROT = 4'd0; //not supported |
assign ARLOCK = 2'd0; //not supported |
|
assign rd_fifo_data_in = RDATA; |
assign rd_fifo_resp_in = BRESP; |
|
assign wr_data_bytes = 1'b1 << wr_data_size; |
|
assign wr_data_strb = |
wr_data_size == 'd0 ? 1'b1 : |
wr_data_size == 'd1 ? 2'b11 : |
wr_data_size == 'd2 ? 4'b1111 : |
wr_data_size == 'd3 ? {8{1'b1}} : |
wr_data_size == 'd4 ? {16{1'b1}} : 'd0; |
|
assign wr_data_addr_prog = wr_data_addr + (wvalid_cnt * wr_data_bytes); |
|
always @(posedge clk or posedge reset) |
if (reset) |
WVALID_pre <= #FFD 1'b0; |
else if ((wr_data_fullness == 1) & wr_data_pop) |
WVALID_pre <= #FFD 1'b0; |
else if ((!wr_data_empty) & wr_enable) |
WVALID_pre <= #FFD 1'b1; |
|
|
assign wr_data_offset = wr_data_addr_prog[DATA_LOG-1:0]; |
|
assign WID = MASTER_ID; |
assign WDATA = wr_fifo_empty ? 0 : wr_fifo_data; |
assign WSTRB = wr_data_strb << wr_data_offset; |
|
|
always @(posedge clk or posedge reset) |
if (reset) |
wvalid_cnt <= #FFD {LEN_BITS{1'b0}}; |
else if (wr_data_pop) |
wvalid_cnt <= #FFD {LEN_BITS{1'b0}}; |
else if (WVALID & WREADY) |
wvalid_cnt <= #FFD wvalid_cnt + 1'b1; |
|
assign WLAST = WVALID & (wvalid_cnt == wr_data_len); |
|
assign wr_resp_resp_in = BRESP; |
|
always @(posedge clk or posedge reset) |
if (reset) |
begin |
wr_fullness <= #FFD 0; |
rd_fullness <= #FFD 0; |
rd_completed <= #FFD 0; |
wr_completed <= #FFD 0; |
end |
else |
begin |
wr_fullness <= #FFD wr_fullness + wr_cmd_pop - wr_resp_push; |
rd_fullness <= #FFD rd_fullness + rd_cmd_pop - rd_resp_pop; |
rd_completed <= #FFD rd_completed + rd_resp_pop; |
wr_completed <= #FFD wr_completed + wr_resp_push; |
end |
|
assign wr_hold = wr_fullness >= wr_pend_max; |
assign rd_hold = (rd_fullness >= rd_pend_max) | (wait_for_write & (wr_completed <= rd_completed + rd_fullness)); |
|
|
|
task insert_rd_cmd; |
input [ADDR_BITS-1:0] addr; |
input [LEN_BITS-1:0] len; |
input [SIZE_BITS-1:0] size; |
|
begin |
rd_cmd_addr_in = addr; |
rd_cmd_len_in = len; |
rd_cmd_size_in = size; |
rd_resp_addr_in = addr; |
rd_resp_size_in = size; |
|
if (rd_cmd_full) enable = 1; //start stub not started yet |
|
wait ((!rd_cmd_full) & (!rd_resp_full)); |
@(negedge clk); #FFD; |
rd_cmd_push = 1; |
rd_resp_push = 1; |
@(posedge clk); #FFD; |
rd_cmd_push = 0; |
rd_resp_push = 0; |
end |
endtask |
|
task insert_wr_cmd; |
input [ADDR_BITS-1:0] addr; |
input [LEN_BITS-1:0] len; |
input [SIZE_BITS-1:0] size; |
|
begin |
wr_cmd_addr_in = addr; |
wr_cmd_len_in = len; |
wr_cmd_size_in = size; |
wr_data_addr_in = addr; |
wr_data_len_in = len; |
wr_data_size_in = size; |
|
if (wr_cmd_full) enable = 1; //start stub not started yet |
|
wait ((!wr_cmd_full) & (!wr_data_full)); |
@(negedge clk); #FFD; |
wr_cmd_push = 1; |
wr_data_push = 1; |
@(posedge clk); #FFD; |
wr_cmd_push = 0; |
wr_data_push = 0; |
end |
endtask |
|
task insert_wr_data; |
input [DATA_BITS-1:0] wdata; |
|
begin |
wr_fifo_data_in = wdata; |
|
wait (!wr_fifo_full); |
@(negedge clk); #FFD; |
wr_fifo_push = 1; |
@(posedge clk); #FFD; |
wr_fifo_push = 0; |
end |
endtask |
|
task insert_wr_incr_data; |
input [ADDR_BITS-1:0] addr; |
input [LEN_BITS-1:0] len; |
input [SIZE_BITS-1:0] size; |
|
integer valid_cnt; |
integer wdata_cnt; |
reg [7:0] data_cnt; |
integer bytes; |
reg [DATA_BITS-1:0] add_data; |
reg [DATA_BITS-1:0] next_data; |
begin |
//insert data |
valid_cnt = 0; |
while (valid_cnt <= len) |
begin |
bytes = 1'b1 << size; |
wdata_cnt = valid_cnt+(addr[DATA_LOG-1:0]/bytes); |
data_cnt = ((wdata_cnt)/(DATA_BITS/(bytes*8))) * (DATA_BITS/8); |
add_data = {DATA_BITS/8{data_cnt}}; |
next_data = (use_addr_base ? addr : base_data) + add_data; |
insert_wr_data(next_data); |
valid_cnt = valid_cnt+1; |
end |
//insert command |
insert_wr_cmd(addr, len, size); |
end |
endtask |
|
task insert_scrbrd; |
input [ADDR_BITS-1:0] addr; |
input [DATA_BITS-1:0] data; |
input [DATA_BITS-1:0] mask; |
begin |
scrbrd_enable = 1; |
scrbrd_addr_in = addr; |
scrbrd_data_in = data; |
scrbrd_mask_in = mask; |
|
wait (!scrbrd_full); |
@(negedge clk); #FFD; |
scrbrd_push = 1; |
@(posedge clk); #FFD; |
scrbrd_push = 0; |
end |
endtask |
|
task insert_scrbrd_incr_data; |
input [ADDR_BITS-1:0] addr; |
input [LEN_BITS-1:0] len; |
input [SIZE_BITS-1:0] size; |
|
integer valid_cnt; |
integer wdata_cnt; |
reg [7:0] data_cnt; |
integer bytes; |
reg [DATA_BITS-1:0] add_data; |
reg [DATA_BITS-1:0] next_data; |
reg [DATA_BITS:0] strb; |
reg [DATA_BITS-1:0] mask; |
reg [ADDR_BITS-1:0] next_addr; |
begin |
valid_cnt = 0; |
while (valid_cnt <= len) |
begin |
bytes = 1'b1 << size; |
wdata_cnt = valid_cnt+(addr[DATA_LOG-1:0]/bytes); |
data_cnt = ((wdata_cnt)/(DATA_BITS/(bytes*8))) * (DATA_BITS/8); |
add_data = {DATA_BITS/8{data_cnt}}; |
next_data = (use_addr_base ? addr : base_data) + add_data; |
next_addr = addr + (bytes * valid_cnt); |
strb = (1 << (bytes*8)) - 1; |
mask = strb << (next_addr[DATA_LOG-1:0]*8); |
insert_scrbrd(next_addr, next_data, mask); |
valid_cnt = valid_cnt+1; |
end |
end |
endtask |
|
task insert_rd_scrbrd; |
input [ADDR_BITS-1:0] addr; |
input [LEN_BITS-1:0] len; |
input [SIZE_BITS-1:0] size; |
|
begin |
insert_scrbrd_incr_data(addr, len, size); |
insert_rd_cmd(addr, len, size); |
end |
endtask |
|
task insert_wr_rd_scrbrd; |
input [ADDR_BITS-1:0] addr; |
input [LEN_BITS-1:0] len; |
input [SIZE_BITS-1:0] size; |
|
begin |
wait_for_write=1; |
insert_wr_incr_data(addr, len, size); |
insert_rd_scrbrd(addr, len, size); |
end |
endtask |
|
task insert_wr_rd_scrbrd_rand; |
reg [ADDR_BITS-1:0] addr; |
reg [LEN_BITS-1:0] len; |
reg [SIZE_BITS-1:0] size; |
|
begin |
len = rand(len_min, len_max); |
size = rand(size_min, size_max); |
addr = rand_align(addr_min, addr_max, 1 << size); |
insert_wr_rd_scrbrd(addr, len, size); |
end |
endtask |
|
task insert_rand_chk; |
input [31:0] num; |
|
rand_chk_num = num; |
endtask |
|
task insert_rand_chk_loop; |
input [31:0] num; |
|
integer i; |
begin |
i = 0; |
while (i < num) |
begin |
insert_wr_rd_scrbrd_rand; |
i = i + 1; |
end |
end |
endtask |
|
task insert_wr_single; |
input [ADDR_BITS-1:0] addr; |
input [DATA_BITS-1:0] wdata; |
|
reg [SIZE_BITS-1:0] size; |
begin |
size = EXPR((DATA_BITS/32)+1); |
insert_wr_data(wdata); |
insert_wr_cmd(addr, 0, size); |
end |
endtask |
|
task get_rd_resp; |
output [DATA_BITS-1:0] rdata; |
output [1:0] resp; |
|
reg [DATA_BITS-1:0] rdata; |
reg [1:0] resp; |
begin |
wait (!rd_fifo_empty); |
rdata = rd_fifo_data; |
resp = rd_fifo_resp; |
@(negedge clk); #FFD; |
rd_fifo_pop = 1; |
@(posedge clk); #FFD; |
rd_fifo_pop = 0; |
end |
endtask |
|
task get_scrbrd; |
output [ADDR_BITS-1:0] addr; |
output [DATA_BITS-1:0] rdata; |
output [DATA_BITS-1:0] mask; |
|
reg [ADDR_BITS-1:0] addr; |
reg [DATA_BITS-1:0] rdata; |
reg [DATA_BITS-1:0] mask; |
begin |
wait (!scrbrd_empty); |
addr = scrbrd_addr; |
rdata = scrbrd_data; |
mask = scrbrd_mask; |
@(negedge clk); #FFD; |
scrbrd_pop = 1; |
@(posedge clk); #FFD; |
scrbrd_pop = 0; |
end |
endtask |
|
task get_wr_resp; |
output [1:0] resp; |
|
reg [1:0] resp; |
begin |
wait (!wr_resp_empty); |
resp = wr_resp_resp; |
@(negedge clk); #FFD; |
wr_resp_pop = 1; |
@(posedge clk); #FFD; |
wr_resp_pop = 0; |
end |
endtask |
|
task insert_rd_single; |
input [ADDR_BITS-1:0] addr; |
|
reg [SIZE_BITS-1:0] size; |
begin |
size = EXPR((DATA_BITS/32)+1); |
insert_rd_cmd(addr, 0, size); |
end |
endtask |
|
task read_single_ack; |
input [ADDR_BITS-1:0] addr; |
output [DATA_BITS-1:0] rdata; |
output [1:0] resp; |
|
reg [1:0] resp; |
begin |
insert_rd_single(addr); |
get_rd_resp(rdata, resp); |
end |
endtask |
|
task write_single_ack; |
input [ADDR_BITS-1:0] addr; |
input [DATA_BITS-1:0] wdata; |
output [1:0] resp; |
|
reg [1:0] resp; |
begin |
insert_wr_single(addr, wdata); |
get_wr_resp(resp); |
end |
endtask |
|
task read_single; |
input [ADDR_BITS-1:0] addr; |
output [DATA_BITS-1:0] rdata; |
|
reg [1:0] resp; |
begin |
read_single_ack(addr, rdata, resp); |
end |
endtask |
|
task check_single; |
input [ADDR_BITS-1:0] addr; |
input [DATA_BITS-1:0] expected; |
|
reg [1:0] resp; |
reg [DATA_BITS-1:0] rdata; |
begin |
read_single_ack(addr, rdata, resp); |
if (rdata !== expected) |
$display("MASTER%0d: CHK_SINGLE_ERROR: Address: 0x%0h, Expected: 0x%0h, Received: 0x%0h.\tTime: %0d ns.", MASTER_NUM, addr, expected, rdata, $time); |
end |
endtask |
|
task write_and_check_single; |
input [ADDR_BITS-1:0] addr; |
input [DATA_BITS-1:0] data; |
|
begin |
write_single(addr, data); |
check_single(addr, data); |
end |
endtask |
|
task write_single; |
input [ADDR_BITS-1:0] addr; |
input [DATA_BITS-1:0] wdata; |
|
reg [1:0] resp; |
begin |
write_single_ack(addr, wdata, resp); |
end |
endtask |
|
task chk_scrbrd; |
reg [ADDR_BITS-1:0] addr; |
reg [DATA_BITS-1:0] mask; |
reg [DATA_BITS-1:0] expected_data; |
reg [DATA_BITS-1:0] rdata; |
reg [DATA_BITS-1:0] rdata_masked; |
reg [1:0] resp; |
|
begin |
if (!wr_resp_empty) get_wr_resp(resp); |
get_scrbrd(addr, expected_data, mask); |
get_rd_resp(rdata, resp); |
expected_data = expected_data & mask; //TBD insert z as dontcare (for print) |
rdata_masked = rdata & mask; |
|
if (expected_data !== rdata_masked) |
$display("MASTER%0d: SCRBRD_ERROR: Address: 0x%0h, Expected: 0x%0h, Received: 0x%0h.\tTime: %0d ns.", MASTER_NUM, addr, expected_data, rdata, $time); |
end |
endtask |
|
always @(posedge scrbrd_enable) |
begin |
while (scrbrd_enable) |
begin |
chk_scrbrd; |
end |
end |
|
|
CREATE prgen_fifo.v DEFCMD(DEFINE STUB) |
prgen_fifo_stub #(ADDR_BITS+LEN_BITS+SIZE_BITS, MAX_CMDS) |
rd_cmd_list( |
.clk(clk), |
.reset(reset), |
.push(rd_cmd_push), |
.pop(rd_cmd_pop), |
.din({ |
rd_cmd_size_in, |
rd_cmd_len_in, |
rd_cmd_addr_in |
}), |
.dout({ |
rd_cmd_size, |
rd_cmd_len, |
rd_cmd_addr |
}), |
.fullness(rd_cmd_fullness), |
.empty(rd_cmd_empty), |
.full(rd_cmd_full) |
); |
|
prgen_fifo_stub #(ADDR_BITS+SIZE_BITS, MAX_CMDS) |
rd_resp_list( |
.clk(clk), |
.reset(reset), |
.push(rd_resp_push), |
.pop(rd_resp_pop), |
.din({ |
rd_resp_addr_in, |
rd_resp_size_in |
}), |
.dout({ |
rd_resp_addr, |
rd_resp_size |
}), |
.empty(rd_resp_empty), |
.full(rd_resp_full) |
); |
|
prgen_fifo_stub #(ADDR_BITS+LEN_BITS+SIZE_BITS, MAX_CMDS) |
wr_cmd_list( |
.clk(clk), |
.reset(reset), |
.push(wr_cmd_push), |
.pop(wr_cmd_pop), |
.din({ |
wr_cmd_size_in, |
wr_cmd_len_in, |
wr_cmd_addr_in |
}), |
.dout({ |
wr_cmd_size, |
wr_cmd_len, |
wr_cmd_addr |
}), |
.fullness(wr_cmd_fullness), |
.empty(wr_cmd_empty), |
.full(wr_cmd_full) |
); |
|
prgen_fifo_stub #(ADDR_BITS+LEN_BITS+SIZE_BITS, MAX_CMDS) |
wr_data_list( |
.clk(clk), |
.reset(reset), |
.push(wr_data_push), |
.pop(wr_data_pop), |
.din({ |
wr_data_size_in, |
wr_data_len_in, |
wr_data_addr_in |
}), |
.dout({ |
wr_data_size, |
wr_data_len, |
wr_data_addr |
}), |
.fullness(wr_data_fullness), |
.empty(wr_data_empty), |
.full(wr_data_full) |
); |
|
prgen_fifo_stub #(2, MAX_CMDS) |
wr_resp_list( |
.clk(clk), |
.reset(reset), |
.push(wr_resp_push), |
.pop(wr_resp_pop), |
.din(wr_resp_resp_in), |
.dout(wr_resp_resp), |
.empty(wr_resp_empty), |
.full(wr_resp_full) |
); |
|
|
prgen_fifo_stub #(DATA_BITS, MAX_CMDS*EXPR(2^LEN_BITS)) |
wr_data_fifo( |
.clk(clk), |
.reset(reset), |
.push(wr_fifo_push), |
.pop(wr_fifo_pop), |
.din(wr_fifo_data_in), |
.dout(wr_fifo_data), |
.empty(wr_fifo_empty), |
.full(wr_fifo_full) |
); |
|
prgen_fifo_stub #(DATA_BITS+2, MAX_CMDS*EXPR(2^LEN_BITS)) |
rd_data_fifo( |
.clk(clk), |
.reset(reset), |
.push(rd_fifo_push), |
.pop(rd_fifo_pop), |
.din({ |
rd_fifo_data_in, |
rd_fifo_resp_in |
}), |
.dout({ |
rd_fifo_data, |
rd_fifo_resp |
}), |
.empty(rd_fifo_empty), |
.full(rd_fifo_full) |
); |
|
prgen_fifo_stub #(ADDR_BITS+2*DATA_BITS, MAX_CMDS*EXPR(2^LEN_BITS)) |
scrbrd_fifo( |
.clk(clk), |
.reset(reset), |
.push(scrbrd_push), |
.pop(scrbrd_pop), |
.din({ |
scrbrd_addr_in, |
scrbrd_data_in, |
scrbrd_mask_in |
}), |
.dout({ |
scrbrd_addr, |
scrbrd_data, |
scrbrd_mask |
}), |
.empty(scrbrd_empty), |
.full(scrbrd_full) |
); |
|
|
CREATE axi_master_stall.v |
PREFIX_stall |
PREFIX_stall ( |
.clk(clk), |
.reset(reset), |
|
.rd_hold(rd_hold), |
.wr_hold(wr_hold), |
|
.ARVALID_pre(ARVALID_pre), |
.RREADY_pre(RREADY_pre), |
.AWVALID_pre(AWVALID_pre), |
.WVALID_pre(WVALID_pre), |
.BREADY_pre(BREADY_pre), |
|
.ARREADY(ARREADY), |
.AWREADY(AWREADY), |
.WREADY(WREADY), |
|
.ARVALID(ARVALID), |
.RREADY(RREADY), |
.AWVALID(AWVALID), |
.WVALID(WVALID), |
.BREADY(BREADY) |
); |
|
|
endmodule |
|
|
/trunk/src/base/axi2apb_wr.v
0,0 → 1,77
<##////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
//////////////////////////////////////////////////////////////////##> |
|
INCLUDE def_axi2apb.txt |
OUTFILE PREFIX_axi2apb_wr.v |
|
module PREFIX_axi2apb_wr (PORTS); |
|
input clk; |
input reset; |
|
input GROUP_APB3; |
|
input cmd_err; |
input [ID_BITS-1:0] cmd_id; |
output finish_wr; |
|
port WGROUP_APB_AXI_W; |
port BGROUP_APB_AXI_B; |
|
|
parameter RESP_OK = 2'b00; |
parameter RESP_SLVERR = 2'b10; |
parameter RESP_DECERR = 2'b11; |
|
reg BGROUP_APB_AXI_B.OUT; |
|
|
assign finish_wr = BVALID & BREADY; |
|
assign WREADY = psel & penable & pwrite & pready; |
|
always @(posedge clk or posedge reset) |
if (reset) |
begin |
BGROUP_APB_AXI_B.OUT <= #FFD {GROUP_APB_AXI_B.OUT.WIDTH{1'b0}}; |
end |
else if (finish_wr) |
begin |
BGROUP_APB_AXI_B.OUT <= #FFD {GROUP_APB_AXI_B.OUT.WIDTH{1'b0}}; |
end |
else if (psel & penable & pwrite & pready) |
begin |
BID <= #FFD cmd_id; |
BRESP <= #FFD cmd_err ? RESP_SLVERR : pslverr ? RESP_DECERR : RESP_OK; |
BVALID <= #FFD 1'b1; |
end |
|
endmodule |
|
|
/trunk/src/base/def_apb_master.txt
0,0 → 1,37
<##////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
//////////////////////////////////////////////////////////////////##> |
|
INCLUDE def_apb_master_static.txt |
|
SWAP.GLOBAL #FFD #1 ##Flip-flop delay |
|
SWAP.GLOBAL ADDR_BITS 16 ##APB address bits |
|
##DEFINE APB3 ##if set use pready and pslverr APB3 signals |
|
/trunk/src/base/axi2apb_cmd.v
0,0 → 1,115
<##////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
//////////////////////////////////////////////////////////////////##> |
|
INCLUDE def_axi2apb.txt |
OUTFILE PREFIX_axi2apb_cmd.v |
|
module PREFIX_axi2apb_cmd (PORTS); |
|
input clk; |
input reset; |
|
port AWGROUP_APB_AXI_A; |
port ARGROUP_APB_AXI_A; |
input finish_wr; |
input finish_rd; |
|
output cmd_empty; |
output cmd_read; |
output [ID_BITS-1:0] cmd_id; |
output [ADDR_BITS-1:0] cmd_addr; |
output cmd_err; |
|
|
wire AGROUP_APB_AXI_A; |
|
wire cmd_push; |
wire cmd_pop; |
wire cmd_empty; |
wire cmd_full; |
reg read; |
|
wire wreq, rreq; |
wire wack, rack; |
wire AERR; |
|
|
assign wreq = AWVALID; |
assign rreq = ARVALID; |
assign wack = AWVALID & AWREADY; |
assign rack = ARVALID & ARREADY; |
|
always @(posedge clk or posedge reset) |
if (reset) |
read <= #FFD 1'b1; |
else if (wreq & (rack | (~rreq))) |
read <= #FFD 1'b0; |
else if (rreq & (wack | (~wreq))) |
read <= #FFD 1'b1; |
|
//command mux |
assign AGROUP_APB_AXI_A = read ? ARGROUP_APB_AXI_A : AWGROUP_APB_AXI_A; |
assign AERR = (ASIZE != 'd2) | (ALEN != 'd0); //support only 32 bit single AXI commands |
|
assign ARREADY = (~cmd_full) & read; |
assign AWREADY = (~cmd_full) & (~read); |
|
assign cmd_push = AVALID & AREADY; |
assign cmd_pop = cmd_read ? finish_rd : finish_wr; |
|
CREATE prgen_fifo.v DEFCMD(SWAP CONST(#FFD) #FFD) |
prgen_fifo #(ID_BITS+ADDR_BITS+2, CMD_DEPTH) |
cmd_fifo( |
.clk(clk), |
.reset(reset), |
.push(cmd_push), |
.pop(cmd_pop), |
.din({ |
AID, |
AADDR, |
AERR, |
read |
} |
), |
.dout({ |
cmd_id, |
cmd_addr, |
cmd_err, |
cmd_read |
} |
), |
.empty(cmd_empty), |
.full(cmd_full) |
); |
|
|
|
endmodule |
|
|
/trunk/src/base/axi2apb_ctrl.v
0,0 → 1,104
<##////////////////////////////////////////////////////////////////// |
//// //// |
//// Author: Eyal Hochberg //// |
//// eyal@provartec.com //// |
//// //// |
//// Downloaded from: http://www.opencores.org //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2010 Provartec LTD //// |
//// www.provartec.com //// |
//// info@provartec.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation.//// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more//// |
//// details. http://www.gnu.org/licenses/lgpl.html //// |
//// //// |
//////////////////////////////////////////////////////////////////##> |
|
INCLUDE def_axi2apb.txt |
OUTFILE PREFIX_axi2apb_ctrl.v |
|
module PREFIX_axi2apb_ctrl (PORTS); |
|
|
input clk; |
input reset; |
|
input finish_wr; |
input finish_rd; |
|
input cmd_empty; |
input cmd_read; |
input WVALID; |
|
output psel; |
output penable; |
output pwrite; |
input pready; |
|
|
wire wstart; |
wire rstart; |
|
reg busy; |
reg psel; |
reg penable; |
reg pwrite; |
wire pack; |
wire cmd_ready; |
|
|
assign cmd_ready = (~busy) & (~cmd_empty); |
assign wstart = cmd_ready & (~cmd_read) & (~psel) & WVALID; |
assign rstart = cmd_ready & cmd_read & (~psel); |
|
assign pack = psel & penable & pready; |
|
always @(posedge clk or posedge reset) |
if (reset) |
busy <= #FFD 1'b0; |
else if (psel) |
busy <= #FFD 1'b1; |
else if (finish_rd | finish_wr) |
busy <= #FFD 1'b0; |
|
always @(posedge clk or posedge reset) |
if (reset) |
psel <= #FFD 1'b0; |
else if (pack) |
psel <= #FFD 1'b0; |
else if (wstart | rstart) |
psel <= #FFD 1'b1; |
|
always @(posedge clk or posedge reset) |
if (reset) |
penable <= #FFD 1'b0; |
else if (pack) |
penable <= #FFD 1'b0; |
else if (psel) |
penable <= #FFD 1'b1; |
|
always @(posedge clk or posedge reset) |
if (reset) |
pwrite <= #FFD 1'b0; |
else if (pack) |
pwrite <= #FFD 1'b0; |
else if (wstart) |
pwrite <= #FFD 1'b1; |
|
|
endmodule |
|
|
/trunk/README.txt
0,0 → 1,22
|
------------------------------ Remark ---------------------------------------- |
This code is a generic code written in RobustVerilog. In order to convert it to Verilog a RobustVerilog parser is required. |
It is possible to download a free RobustVerilog parser from www.provartec.com/edatools. |
|
We will be very happy to receive any kind of feedback regarding our tools and cores. |
We will also be willing to support any company intending to integrate our cores into their project. |
For any questions / remarks / suggestions / bugs please contact info@provartec.com. |
------------------------------------------------------------------------------ |
|
RobustVerilog generic APB master stub |
|
The APB master is built out of an AXI master and an AXI2APB bridge (both independent OpenCores projects) |
|
In order to create the Verilog design use the run.sh script in the run directory (notice that the run scripts calls the robust binary (RobustVerilog parser)). |
|
The RobustVerilog top source file is apb_master.v, it calls the top definition file named def_apb_master.txt. |
|
Changing the stub parameters should be made only in def_apb_master.txt in the src/base directory (changing to APB3, address bits, etc.). |
|
Once the Verilog files have been generated instruction on how to use the stub are at the top of apb_master.v (tasks and parameters). |
|