URL
https://opencores.org/ocsvn/qaz_libs/qaz_libs/trunk
Subversion Repositories qaz_libs
Compare Revisions
- This comparison shows the changes necessary to convert path
/qaz_libs/trunk/axi4_stream_lib
- from Rev 41 to Rev 40
- ↔ Reverse comparison
Rev 41 → Rev 40
/sim/tests/tb_axis_gear_box/tb_dut_if.sv
File deleted
/sim/tests/tb_axis_gear_box/tests_base_pkg.sv
File deleted
/sim/tests/tb_axis_gear_box/axis_pkg.sv
33,11 → 33,11
// |
import uvm_pkg::*; |
`include "uvm_macros.svh" |
import bfm_pkg::*; |
import axis_pkg::*; |
|
// -------------------------------------------------------------------- |
// |
typedef struct |
typedef struct packed |
{ |
int unsigned N; // data bus width in bytes |
int unsigned I; // TID width |
66,7 → 66,6
|
// -------------------------------------------------------------------- |
// |
delay_class delay_h; |
rand logic [(8*N)-1:0] tdata; |
rand logic [N-1:0] tstrb; |
rand logic [N-1:0] tkeep; |
74,12 → 73,11
rand logic [I-1:0] tid; |
rand logic [D-1:0] tdest; |
rand logic [U-1:0] tuser; |
|
|
// -------------------------------------------------------------------- |
// |
function new(string name = ""); |
super.new(name); |
delay_h = new; |
endfunction : new |
|
// -------------------------------------------------------------------- |
138,10 → 136,10
|
// -------------------------------------------------------------------- |
// |
class axis_driver #(parameter axis_config_t cfg) |
class axis_driver #(parameter axis_config_t cfg) |
extends uvm_driver #(axis_sequence_item #(cfg)); |
`uvm_component_param_utils(axis_driver#(cfg)) |
|
|
// -------------------------------------------------------------------- |
// |
localparam N = cfg.N; |
155,7 → 153,7
// -------------------------------------------------------------------- |
// |
virtual axis_if #(.N(N), .I(I), .D(D), .U(U)) axis_bus; |
|
|
//-------------------------------------------------------------------- |
// |
function void set_default; |
169,21 → 167,22
axis_bus.cb_m.tuser <= 'bx; |
endfunction: set_default |
|
|
//-------------------------------------------------------------------- |
// |
virtual task run_phase(uvm_phase phase); |
axis_sequence_item #(cfg) item; |
super.run_phase(phase); |
|
$display("^^^ %16.t | %m | ", $time); |
|
set_default(); |
wait(~axis_bus.aresetn); |
@(axis_bus.cb_m); |
|
forever |
@(axis_bus.cb_m) forever |
begin |
// seq_item_port.try_next_item(item); |
seq_item_port.get_next_item(item); |
|
|
axis_bus.cb_m.tvalid <= 1; |
axis_bus.cb_m.tdata <= item.tdata; |
axis_bus.cb_m.tstrb <= 0; |
198,63 → 197,69
// @(axis_bus.cb_m iff axis_bus.cb_m.tready); |
|
set_default(); |
repeat(item.delay_h.next()) @(axis_bus.cb_m); |
|
seq_item_port.item_done(); |
end |
endtask : run_phase |
|
|
//-------------------------------------------------------------------- |
// |
function new(string name, uvm_component parent); |
super.new(name, parent); |
endfunction |
|
|
// -------------------------------------------------------------------- |
// |
endclass : axis_driver |
|
|
|
// -------------------------------------------------------------------- |
// |
class axis_sequencer #(axis_config_t cfg) |
extends uvm_sequencer #(axis_sequence_item #(cfg)); |
`uvm_component_param_utils(axis_sequencer #(cfg)) |
|
|
// -------------------------------------------------------------------- |
// |
function new(string name, uvm_component parent); |
super.new(name, parent); |
$display("^^^ %16.t | %m | ", $time); |
endfunction |
|
// -------------------------------------------------------------------- |
// |
endclass : axis_sequencer |
|
|
// -------------------------------------------------------------------- |
// |
class axis_counting_sequence #(axis_config_t cfg) |
class axis_counting_sequence #(axis_config_t cfg) |
extends uvm_sequence #(axis_sequence_item #(cfg)); |
`uvm_object_param_utils(axis_counting_sequence #(cfg)) |
`uvm_object_param_utils(axis_counting_sequence #(cfg)) |
|
rand int length = 16; |
|
// -------------------------------------------------------------------- |
// |
localparam LENGTH = 16; |
|
// -------------------------------------------------------------------- |
// |
virtual task body(); |
axis_sequence_item #(cfg) item; |
|
for(int i = 0; i < length; i++) |
|
$display("^^^ %16.t | %m | ", $time); |
|
for(int i = 0; i < LENGTH; i++) |
begin |
item = axis_sequence_item #(cfg)::type_id::create("axis_sequence_item"); |
|
|
item.tdata = i; |
item.tlast = (i == length - 1); |
item.tlast = (i == LENGTH - 1); |
|
start_item (item); |
finish_item(item); |
end |
endtask |
|
|
// -------------------------------------------------------------------- |
// |
function new(string name = "axis_counting_sequence"); |
264,10 → 269,10
// -------------------------------------------------------------------- |
// |
endclass : axis_counting_sequence |
|
|
// -------------------------------------------------------------------- |
// |
class axis_agent #(axis_config_t cfg) |
class axis_agent #(axis_config_t cfg) |
extends uvm_agent; |
`uvm_component_param_utils(axis_agent #(cfg)) |
|
283,19 → 288,22
|
// -------------------------------------------------------------------- |
// |
virtual axis_if #(.N(N), .I(I), .D(D), .U(U)) axis_bus; |
// virtual axis_if #(.N(N), .I(I), .D(D), .U(U)) axis_bus; |
virtual tb_dut_if #(.IN_N(N), .OUT_N(N), .I(I), .D(D), .U(U)) dut_bus; |
|
axis_driver #(cfg) driver; |
// my_monitor #(cfg) monitor; |
axis_sequencer #(cfg) sequencer; |
|
|
// -------------------------------------------------------------------- |
// |
virtual function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
$display("^^^ %16.t | %m | ", $time); |
|
if(!uvm_config_db #(virtual axis_if #(.N(N), .I(I), .D(D), .U(U)))::get(this, "", "axis_bus", axis_bus)) |
`uvm_fatal(get_name(), "Couldn't get virtual interface!") |
if (!uvm_config_db #(virtual tb_dut_if #(.IN_N(N), .OUT_N(N), .I(I), .D(D), .U(U)))::get(this, "", "dut_bus", dut_bus)) |
`uvm_fatal(get_name(), "Could not get the virtual interface handle from the config database.") |
|
driver = axis_driver #(cfg)::type_id::create("driver", this); |
// monitor = my_monitor #(cfg)::type_id::create("monitor" , this); |
306,13 → 314,15
// |
virtual function void connect_phase(uvm_phase phase); |
super.connect_phase(phase); |
|
$display("^^^ %16.t | %m | ", $time); |
|
driver.axis_bus = axis_bus; |
driver.axis_bus = dut_bus.axis_in; |
// monitor.vif = vif; |
|
driver.seq_item_port.connect(sequencer.seq_item_export); |
endfunction |
|
|
// -------------------------------------------------------------------- |
// |
function new(string name, uvm_component parent); |
322,7 → 332,61
// -------------------------------------------------------------------- |
// |
endclass : axis_agent |
|
// -------------------------------------------------------------------- |
// |
|
class my_test extends uvm_test; |
`uvm_component_utils(my_test) |
|
localparam axis_config_t cfg_a = '{ 1, 1, 1, 1, 0, 0, 0}; |
|
axis_agent #(cfg_a) agent_h; |
// my_agent#(cfg_b) agent_b; |
|
function new(string name = "my_test", uvm_component parent); |
super.new(name, parent); |
endfunction |
|
virtual function void build_phase(uvm_phase phase); |
super.build_phase(phase); |
|
$display("^^^ %16.t | %m | ", $time); |
|
agent_h = axis_agent #(cfg_a)::type_id::create("agent_h", this); |
// agent_b = my_agent#(cfg_b)::type_id::create("agent_b", this); |
endfunction |
|
virtual function void end_of_elaboration_phase(uvm_phase phase); |
uvm_phase run_phase = uvm_run_phase::get(); |
run_phase.phase_done.set_drain_time(this, 300ns); |
endfunction |
|
virtual task run_phase(uvm_phase phase); |
axis_counting_sequence #(cfg_a) seq_a; |
super.run_phase(phase); |
|
$display("^^^ %16.t | %m | ", $time); |
|
phase.raise_objection(this); |
|
// fork |
// repeat (3) begin |
seq_a = axis_counting_sequence #(cfg_a)::type_id::create("seq_a"); |
seq_a.start(agent_h.sequencer); |
// end |
|
// repeat (3) begin |
// my_sequence#(cfg_b) seq_b = my_sequence#(cfg_b)::type_id::create("seq_b"); |
// seq_b.start(agent_b.sequencer); |
// end |
// join |
|
phase.drop_objection(this); |
endtask |
endclass |
|
|
// -------------------------------------------------------------------- |
// |
endpackage: axis_pkg |
/sim/tests/tb_axis_gear_box/init_test.do
23,9 → 23,7
vlog ./axis_pkg.sv |
|
vlog ./$env(SIM_TB)_pkg.sv |
vlog ./tests_base_pkg.sv |
vlog ./tests_pkg.sv |
vlog ./tb_dut_if.sv |
|
# simulation $root |
vlog ./$env(SIM_TB).sv |
/sim/tests/tb_axis_gear_box/tb_axis_gear_box.f
1,6 → 1,6
# |
|
${PROJECT_DIR}/src/axis_gear_box.sv |
|
./axis_pkg.sv |
|
${PROJECT_DIR}/src/axis_gear_box.sv |
|
/sim/tests/tb_axis_gear_box/tb_axis_gear_box.sv
57,7 → 57,7
|
// -------------------------------------------------------------------- |
// |
tb_dut_if #(dut_cfg) dut_bus(.*); |
tb_dut_if #(.IN_N(IN_N), .OUT_N(OUT_N), .I(I), .D(D), .U(U)) dut_bus(.*); |
|
// -------------------------------------------------------------------- |
// |
72,17 → 72,12
|
// -------------------------------------------------------------------- |
// |
assign dut_bus.axis_out.tready = 1; |
|
// -------------------------------------------------------------------- |
// |
tb_dut_config #(dut_cfg) cfg_h; |
|
initial |
begin |
cfg_h = new(dut_bus); |
uvm_config_db #(tb_dut_config #(dut_cfg))::set(null, "*env_h", "tb_dut_config", cfg_h); |
run_test("t_debug"); |
uvm_config_db #(virtual tb_dut_if)::set(null, "*", "dut_bus", dut_bus); |
// uvm_top.finish_on_completion = 0; |
// run_test("t_debug"); |
run_test("my_test"); |
end |
|
// -------------------------------------------------------------------- |
/sim/tests/tb_axis_gear_box/tb_axis_gear_box_pkg.sv
25,68 → 25,60
//// //// |
////////////////////////////////////////////////////////////////////// |
|
package tb_axis_gear_box_pkg; |
interface |
tb_dut_if |
#( |
IN_N = 1, // data bus width in bytes. axis_in. |
OUT_N = 1, // data bus width in bytes. axis_out. |
I = 1, // TID width |
D = 1, // TDEST width |
U = 1 // TUSER width |
) |
( |
input aclk, |
input aresetn |
); |
|
// -------------------------------------------------------------------- |
// |
import uvm_pkg::*; |
`include "uvm_macros.svh" |
import axis_pkg::*; |
// wire aclk; |
// wire aresetn; |
axis_if #(.N(IN_N), .I(I), .D(D), .U(U)) axis_in(.*); |
axis_if #(.N(OUT_N), .I(I), .D(D), .U(U)) axis_out(.*); |
|
// -------------------------------------------------------------------- |
// |
typedef struct |
{ |
axis_config_t axis_cfg_in; |
axis_config_t axis_cfg_out; |
} dut_config_t; |
// -------------------------------------------------------------------- |
// |
endinterface: tb_dut_if |
|
localparam dut_config_t dut_cfg = |
'{ |
'{ N : 2 // data bus width in bytes. |
, I : 1 // TID width |
, D : 1 // TDEST width |
, U : 1 // TUSER width |
, USE_TSTRB : 0 |
, USE_TKEEP : 0 |
, USE_ROUTING : 0 |
}, |
'{ N : 2 // data bus width in bytes. |
, I : 1 // TID width |
, D : 1 // TDEST width |
, U : 1 // TUSER width |
, USE_TSTRB : 0 |
, USE_TKEEP : 0 |
, USE_ROUTING : 0 |
} |
}; |
// -------------------------------------------------------------------- |
// |
package tb_axis_gear_box_pkg; |
|
// -------------------------------------------------------------------- |
// |
class tb_dut_config #(dut_config_t dut_cfg); |
import uvm_pkg::*; |
`include "uvm_macros.svh" |
import axis_pkg::*; |
|
virtual tb_dut_if #(dut_cfg) dut_bus; |
|
// -------------------------------------------------------------------- |
// |
function new(virtual tb_dut_if #(dut_cfg) dut_bus); |
this.dut_bus = dut_bus; |
endfunction : new |
|
// -------------------------------------------------------------------- |
// |
endclass : tb_dut_config |
|
localparam IN_N = 1; // data bus width in bytes. axis_in. |
localparam OUT_N = 1; // data bus width in bytes. axis_out. |
localparam I = 1; // TID width |
localparam D = 1; // TDEST width |
localparam U = 1; // TUSER width |
|
// -------------------------------------------------------------------- |
// |
class tb_env extends uvm_env; |
`uvm_component_utils(tb_env); |
|
// -------------------------------------------------------------------- |
// |
// coverage coverage_h; |
// scoreboard scoreboard_h; |
axis_agent #(dut_cfg.axis_cfg_in) agent_h; |
// sequencer sequencer_h; |
// coverage coverage_h; |
// scoreboard scoreboard_h; |
// driver driver_h; |
// command_monitor command_monitor_h; |
// result_monitor result_monitor_h; |
|
// -------------------------------------------------------------------- |
// |
97,34 → 89,28
// -------------------------------------------------------------------- |
// |
function void build_phase(uvm_phase phase); |
tb_dut_config #(dut_cfg) cfg_h; |
if (!uvm_config_db#(tb_dut_config #(dut_cfg))::get(this, "", "tb_dut_config", cfg_h)) |
`uvm_fatal(get_name(), "Couldn't get config object!") |
|
uvm_config_db |
#( |
virtual axis_if |
#( .N(dut_cfg.axis_cfg_in.N) |
, .I(dut_cfg.axis_cfg_in.I) |
, .D(dut_cfg.axis_cfg_in.D) |
, .U(dut_cfg.axis_cfg_in.U) |
) |
)::set(this, "*agent_h", "axis_bus", cfg_h.dut_bus.axis_in); |
|
// // stimulus |
// sequencer_h = new("sequencer_h",this); |
// driver_h = driver::type_id::create("driver_h",this); |
// // monitors |
// command_monitor_h = command_monitor::type_id::create("command_monitor_h",this); |
// result_monitor_h = result_monitor::type_id::create("result_monitor",this); |
// // analysis |
// coverage_h = coverage::type_id::create ("coverage_h",this); |
// scoreboard_h = scoreboard::type_id::create("scoreboard",this); |
endfunction : build_phase |
|
agent_h = axis_agent #(dut_cfg.axis_cfg_in)::type_id::create("agent_h", this); |
// -------------------------------------------------------------------- |
// |
function void connect_phase(uvm_phase phase); |
|
endfunction : build_phase |
// driver_h.seq_item_port.connect(sequencer_h.seq_item_export); |
|
// // -------------------------------------------------------------------- |
// // |
// function void connect_phase(uvm_phase phase); |
// command_monitor_h.ap.connect(coverage_h.analysis_export); |
// command_monitor_h.ap.connect(scoreboard_h.cmd_f.analysis_export); |
// result_monitor_h.ap.connect(scoreboard_h.analysis_export); |
endfunction : connect_phase |
|
// endfunction : connect_phase |
|
// -------------------------------------------------------------------- |
// |
endclass : tb_env |
/sim/tests/tb_axis_gear_box/tests_pkg.sv
33,160 → 33,69
// |
import uvm_pkg::*; |
`include "uvm_macros.svh" |
import axis_pkg::*; |
import tb_axis_gear_box_pkg::*; |
import tests_base_pkg::*; |
|
// -------------------------------------------------------------------- |
// |
class t_counting extends test_base; |
`uvm_component_utils(t_counting) |
virtual class test_base extends uvm_test; |
`uvm_component_utils(test_base); |
// tb_env env_h; |
|
// -------------------------------------------------------------------- |
// |
function new(string name = "my_test", uvm_component parent); |
super.new(name, parent); |
endfunction |
function void build_phase(uvm_phase phase); |
$display("^^^ %16.t | %m | ", $time); |
// env_h = tb_env::type_id::create("env_h",this); |
endfunction : build_phase |
|
// -------------------------------------------------------------------- |
// |
virtual function void end_of_elaboration_phase(uvm_phase phase); |
uvm_phase run_phase = uvm_run_phase::get(); |
run_phase.phase_done.set_drain_time(this, 300ns); |
endfunction |
|
function void end_of_elaboration_phase(uvm_phase phase); |
$display("^^^ %16.t | %m | ", $time); |
// sequencer_h = env_h.sequencer_h; |
endfunction : end_of_elaboration_phase |
|
// -------------------------------------------------------------------- |
// |
virtual task run_phase(uvm_phase phase); |
axis_counting_sequence #(dut_cfg.axis_cfg_in) seq_h; |
super.run_phase(phase); |
phase.raise_objection(this); |
fork |
repeat(3) |
begin |
seq_h = axis_counting_sequence #(dut_cfg.axis_cfg_in)::type_id::create("seq_h"); |
seq_h.start(env_h.agent_h.sequencer); |
end |
join |
phase.drop_objection(this); |
endtask : run_phase |
function new (string name, uvm_component parent); |
super.new(name,parent); |
$display("^^^ %16.t | %m | ", $time); |
endfunction : new |
|
// -------------------------------------------------------------------- |
// |
endclass : t_counting |
// -------------------------------------------------------------------- |
// |
endclass : test_base |
|
// -------------------------------------------------------------------- |
// |
class gear_box_sequence #(dut_config_t dut_cfg) |
extends uvm_sequence #(axis_sequence_item #(dut_cfg.axis_cfg_in)); |
`uvm_object_param_utils(gear_box_sequence #(dut_cfg)) |
class t_debug extends test_base; |
`uvm_component_utils(t_debug); |
|
rand int length = 7 * 3; |
|
// -------------------------------------------------------------------- |
// |
typedef logic [15:0] packed_data_t[7]; |
|
function packed_data_t next_data(int init); |
static logic [15:0] previous_value; |
logic [13:0] unpacked_data[8]; |
logic [15:0] packed_data[7]; |
|
if(init == 0) |
previous_value = 0; |
|
foreach(unpacked_data[i]) |
begin |
unpacked_data[i] = previous_value; |
// $display("^^^ %16.t | unpacked_data[%0.d] = %h", $time, i, unpacked_data[i]); |
previous_value++; |
end |
|
packed_data = {<<16{{<<14{unpacked_data}}}}; |
|
// $display("^^^ %16.t | %p", $time, packed_data); |
|
// foreach(packed_data[i]) |
// $display("^^^ %16.t | packed_data[%0.d] = %h", $time, i, packed_data[i]); |
|
next_data = packed_data; |
endfunction |
|
|
// -------------------------------------------------------------------- |
// |
virtual task body(); |
localparam CHUNKS = 3; |
axis_sequence_item #(dut_cfg.axis_cfg_in) item; |
logic [15:0] data[7]; |
|
item = axis_sequence_item #(dut_cfg.axis_cfg_in)::type_id::create("axis_sequence_item"); |
task run_phase(uvm_phase phase); |
$display("^^^ %16.t | %m | ", $time); |
// fibonacci_sequence fibonacci; |
// fibonacci = new("fibonacci"); |
|
for(int i = 0; i < CHUNKS; i++) |
begin |
data = next_data(i); |
|
foreach(data[k]) |
begin |
start_item(item); |
item.tdata = data[k]; |
item.tlast = (i == CHUNKS - 1) & (k == 0); |
item.tuser = 0; |
finish_item(item); |
// $display("^^^ %16.t | %d | %x", $time, (i * 7) + k, item.tdata); |
end |
end |
|
endtask |
// phase.raise_objection(this); |
// fibonacci.start(sequencer_h); |
// phase.drop_objection(this); |
endtask : run_phase |
|
// -------------------------------------------------------------------- |
// |
function new(string name = "gear_box_sequence"); |
super.new(name); |
endfunction |
// // -------------------------------------------------------------------- |
// // |
// task final_phase(uvm_phase phase); |
// super.final_phase(phase); |
// $display("^^^ %16.t | %m | ", $time); |
// $stop; |
// endtask : final_phase |
|
// -------------------------------------------------------------------- |
// |
endclass : gear_box_sequence |
|
// -------------------------------------------------------------------- |
// |
class t_debug extends test_debug_base; |
`uvm_component_utils(t_debug) |
|
// -------------------------------------------------------------------- |
// |
function new(string name = "t_debug", uvm_component parent); |
super.new(name, parent); |
endfunction |
function new(string name, uvm_component parent); |
super.new(name,parent); |
endfunction : new |
|
// -------------------------------------------------------------------- |
// |
function void end_of_elaboration_phase(uvm_phase phase); |
uvm_phase run_phase = uvm_run_phase::get(); |
run_phase.phase_done.set_drain_time(this, 300ns); |
endfunction |
|
// -------------------------------------------------------------------- |
// |
virtual task run_phase(uvm_phase phase); |
gear_box_sequence #(dut_cfg) seq_h; |
super.run_phase(phase); |
phase.raise_objection(this); |
|
fork |
repeat(3) |
begin |
seq_h = gear_box_sequence #(dut_cfg)::type_id::create("seq_h"); |
seq_h.start(env_h.agent_h.sequencer); |
end |
join |
|
phase.drop_objection(this); |
endtask : run_phase |
|
// -------------------------------------------------------------------- |
// |
endclass : t_debug |
/src/axis_gear_box.sv
25,17 → 25,17
//// //// |
////////////////////////////////////////////////////////////////////// |
|
|
module |
axis_gear_box |
#( |
IN_N = 2, // data bus width in bytes. axis_in. |
OUT_N = 2, // data bus width in bytes. axis_out. |
IN_W = 16, // width in bits |
OUT_W = 14, // width in bits |
U = 1, // TUSER width |
IN_N = 1, // data bus width in bytes. axis_in. |
IN_I = 1, // TID width |
IN_D = 1, // TDEST width |
IN_U = 1, // TUSER width |
USE_TSTRB = 0, // set to 1 to enable, 0 to disable |
USE_TKEEP = 0, // set to 1 to enable, 0 to disable |
ANTECEDENT = 7, // in:out ratio (ANTECEDENT:CONSEQUENT) |
ANTECEDENT = 7, // ANTECEDENT:CONSEQUENT ratio |
CONSEQUENT = 8 |
) |
( |
47,139 → 47,9
|
// -------------------------------------------------------------------- |
// |
localparam B_W = IN_W*ANTECEDENT; |
localparam UB_W = $clog2(B_W); |
localparam UB_A = $clog2(ANTECEDENT); |
localparam UB_C = $clog2(CONSEQUENT); |
|
// -------------------------------------------------------------------- |
// synthesis translate_off |
initial |
begin |
a_consequent: assert(B_W % CONSEQUENT == 0) else $fatal; |
a_in_w: assert(B_W % IN_W == 0) else $fatal; |
a_out_w: assert(B_W % OUT_W == 0) else $fatal; |
end |
// synthesis translate_on |
// -------------------------------------------------------------------- |
assign axis_in.tready = 1; |
|
// -------------------------------------------------------------------- |
// |
reg [UB_W:0] wr_index; |
reg [UB_A:0] wr_select; |
wire wr_en = axis_in.tvalid & axis_in.tready & aresetn; |
wire wr_end = wr_en & (wr_index == B_W - IN_W); |
wire [UB_W:0] wr_next_index = wr_end ? 0 : wr_index + IN_W; |
|
always_ff @(posedge aclk) |
if(~aresetn) |
wr_index <= 0; |
else if(wr_en) |
wr_index <= wr_next_index; |
|
always_ff @(posedge aclk) |
if(~aresetn) |
wr_select <= 0; |
else if(wr_en) |
wr_select <= wr_end ? 0 : wr_select + 1; |
|
// -------------------------------------------------------------------- |
// |
reg [UB_W:0] rd_index; |
reg [UB_C:0] rd_select; |
wire rd_en = axis_out.tvalid & axis_out.tready; |
wire rd_end = rd_en & (rd_index == B_W - OUT_W); |
wire [UB_W:0] rd_next_index = rd_end ? 0 : rd_index + OUT_W; |
|
always_ff @(posedge aclk) |
if(~aresetn) |
rd_index <= 0; |
else if(rd_en) |
rd_index <= rd_next_index; |
|
always_ff @(posedge aclk) |
if(~aresetn) |
rd_select <= 0; |
else if(rd_en) |
rd_select <= rd_end ? 0 : rd_select + 1; |
|
// -------------------------------------------------------------------- |
// |
reg [B_W:0] buffer; |
genvar j; |
|
generate |
begin: buffer_gen |
for(j = 0; j < B_W/IN_W; j++) |
always_ff @(posedge aclk) |
if(wr_en & (wr_select == j)) |
buffer[j*IN_W +: IN_W] <= axis_in.tdata[IN_W-1:0]; |
end |
endgenerate |
|
// -------------------------------------------------------------------- |
// |
// localparam C_DO = B_W/OUT_W; |
localparam MC_DO = 2**$clog2(CONSEQUENT); // max count |
wire [OUT_W-1:0] data_in[MC_DO-1:0]; |
wire [OUT_W-1:0] data_out; |
|
generate |
begin: data_out_gen |
for(j = 0; j < CONSEQUENT; j++) |
assign data_in[j] = buffer[j*OUT_W +: OUT_W]; |
if(MC_DO > CONSEQUENT) |
for(j = CONSEQUENT; j < MC_DO; j++) |
assign data_in[j] = 0; |
end |
endgenerate |
|
// -------------------------------------------------------------------- |
// |
recursive_mux #(.A($clog2(CONSEQUENT)), .W(OUT_W)) |
recursive_mux_i(.select(rd_select), .*); |
|
//--------------------------------------------------- |
// state machine binary definitions |
enum reg [1:0] |
{ |
SAME = 2'b01, |
WR_LAPPED = 2'b10 |
} state, next_state; |
|
//--------------------------------------------------- |
// state machine flop |
always_ff @(posedge aclk) |
if(~aresetn) |
state <= SAME; |
else |
state <= next_state; |
|
//--------------------------------------------------- |
// state machine |
always_comb |
case(state) |
SAME: if(wr_end & ~rd_end) |
next_state <= WR_LAPPED; |
else |
next_state <= SAME; |
|
WR_LAPPED: if(rd_end & ~wr_end) |
next_state <= SAME; |
else |
next_state <= WR_LAPPED; |
|
default: next_state <= SAME; |
endcase |
|
// -------------------------------------------------------------------- |
// |
wire empty = (state == SAME) ? rd_next_index > wr_index : 0; |
wire full = (state == SAME) ? 0 : wr_next_index > rd_index; |
assign axis_in.tready = ~full; |
assign axis_out.tvalid = ~empty; |
assign axis_out.tdata = data_out; |
|
// -------------------------------------------------------------------- |
// |
endmodule |