//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
// Scoreboard FSM
|
// Scoreboard FSM
|
//
|
//
|
// Keeps track of data regarding N items. Allows multiple entities
|
// Keeps track of data regarding N items. Allows multiple entities
|
// to track data about a particular item. Supports masked writes,
|
// to track data about a particular item. Supports masked writes,
|
// allowing only part of a record to be updated by a particular
|
// allowing only part of a record to be updated by a particular
|
// transaction.
|
// transaction.
|
//
|
//
|
// If masks are enabled,
|
// If masks are enabled,
|
//
|
//
|
// Naming convention: c = consumer, p = producer, i = internal interface
|
// Naming convention: c = consumer, p = producer, i = internal interface
|
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
// Author: Guy Hutchison
|
// Author: Guy Hutchison
|
//
|
//
|
// This block is uncopyrighted and released into the public domain.
|
// This block is uncopyrighted and released into the public domain.
|
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
|
|
// Clocking statement for synchronous blocks. Default is for
|
// Clocking statement for synchronous blocks. Default is for
|
// posedge clocking and positive async reset
|
// posedge clocking and positive async reset
|
`ifndef SDLIB_CLOCKING
|
`ifndef SDLIB_CLOCKING
|
`define SDLIB_CLOCKING posedge clk or posedge reset
|
`define SDLIB_CLOCKING posedge clk or posedge reset
|
`endif
|
`endif
|
|
|
// delay unit for nonblocking assigns, default is to #1
|
// delay unit for nonblocking assigns, default is to #1
|
`ifndef SDLIB_DELAY
|
`ifndef SDLIB_DELAY
|
`define SDLIB_DELAY #1
|
`define SDLIB_DELAY #1
|
`endif
|
`endif
|
|
|
module sd_scoreboard_fsm
|
module sd_scoreboard_fsm
|
#(parameter width=8,
|
#(parameter width=8,
|
parameter items=64,
|
parameter items=64,
|
parameter use_txid=0,
|
parameter use_txid=0,
|
parameter use_mask=0,
|
parameter use_mask=0,
|
parameter txid_sz=2,
|
parameter txid_sz=2,
|
parameter asz=$clog2(items))
|
parameter asz=$clog2(items))
|
(input clk,
|
(input clk,
|
input reset,
|
input reset,
|
|
|
input ip_srdy,
|
input ip_srdy,
|
output reg ip_drdy,
|
output reg ip_drdy,
|
input ip_req_type, // 0=read, 1=write
|
input ip_req_type, // 0=read, 1=write
|
input [txid_sz-1:0] ip_txid,
|
input [txid_sz-1:0] ip_txid,
|
input [width-1:0] ip_mask,
|
input [width-1:0] ip_mask,
|
input [width-1:0] ip_data,
|
input [width-1:0] ip_data,
|
input [asz-1:0] ip_itemid,
|
input [asz-1:0] ip_itemid,
|
|
|
output reg ic_srdy,
|
output reg ic_srdy,
|
input ic_drdy,
|
input ic_drdy,
|
output reg [txid_sz-1:0] ic_txid,
|
output reg [txid_sz-1:0] ic_txid,
|
output reg [width-1:0] ic_data,
|
output reg [width-1:0] ic_data,
|
|
|
input [width-1:0] d_out,
|
input [width-1:0] d_out,
|
output reg wr_en,
|
output reg wr_en,
|
output reg rd_en,
|
output reg rd_en,
|
output reg [width-1:0] d_in,
|
output reg [width-1:0] d_in,
|
output reg [asz-1:0] addr
|
output reg [asz-1:0] addr
|
);
|
);
|
|
|
localparam s_idle = 0, s_read = 1, s_rdmod = 2;
|
localparam s_idle = 0, s_read = 1, s_rdmod = 2;
|
|
|
reg [2:0] state, nxt_state;
|
reg [2:0] state, nxt_state;
|
reg [txid_sz-1:0] txid, nxt_txid;
|
reg [txid_sz-1:0] txid, nxt_txid;
|
|
|
always @*
|
always @*
|
begin
|
begin
|
ip_drdy = 0;
|
ip_drdy = 0;
|
ic_srdy = 0;
|
ic_srdy = 0;
|
ic_data = 0;
|
ic_data = 0;
|
wr_en = 0;
|
wr_en = 0;
|
rd_en = 0;
|
rd_en = 0;
|
d_in = 0;
|
d_in = 0;
|
addr = ip_itemid;
|
addr = ip_itemid;
|
nxt_state = state;
|
nxt_state = state;
|
nxt_txid = txid;
|
nxt_txid = txid;
|
if (use_txid)
|
if (use_txid)
|
ic_txid = txid;
|
ic_txid = txid;
|
else
|
else
|
ic_txid = 0;
|
ic_txid = 0;
|
|
|
nxt_state[s_read] = 0;
|
nxt_state[s_read] = 0;
|
|
|
if (state[s_idle])
|
if (state[s_idle])
|
begin
|
begin
|
if (ip_srdy & (ip_req_type==1))
|
if (state[s_read] & !ic_drdy)
|
|
begin
|
|
// output is busy, stall
|
|
end
|
|
else if (ip_srdy & (ip_req_type==1))
|
begin
|
begin
|
if ((use_mask==0) | (ip_mask=={width{1'b1}}))
|
if ((use_mask==0) | (ip_mask=={width{1'b1}}))
|
begin
|
begin
|
ip_drdy = 1;
|
ip_drdy = 1;
|
wr_en = 1;
|
wr_en = 1;
|
d_in = ip_data;
|
d_in = ip_data;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
rd_en = 1;
|
rd_en = 1;
|
nxt_state[s_rdmod] = 1;
|
nxt_state[s_rdmod] = 1;
|
nxt_state[s_idle] = 0;
|
nxt_state[s_idle] = 0;
|
end
|
end
|
end
|
end
|
else if (ip_srdy & (ip_req_type==0) & (!state[s_read] | ic_drdy))
|
else if (ip_srdy & (ip_req_type==0))
|
begin
|
begin
|
rd_en = 1;
|
rd_en = 1;
|
nxt_state[s_read] = 1;
|
nxt_state[s_read] = 1;
|
nxt_txid = ip_txid;
|
nxt_txid = ip_txid;
|
ip_drdy = 1;
|
ip_drdy = 1;
|
end
|
end
|
end // case: s_idle
|
end // case: s_idle
|
|
|
if (state[s_read])
|
if (state[s_read])
|
begin
|
begin
|
ic_srdy = 1;
|
ic_srdy = 1;
|
ic_data = d_out;
|
ic_data = d_out;
|
if (!ic_drdy)
|
if (!ic_drdy)
|
begin
|
begin
|
nxt_state[s_read] = 1;
|
nxt_state[s_read] = 1;
|
//nxt_state[s_idle] = 1;
|
//nxt_state[s_idle] = 1;
|
end
|
end
|
end // case: state[s_read]
|
end // case: state[s_read]
|
|
|
if (state[s_rdmod])
|
if (state[s_rdmod])
|
begin
|
begin
|
ip_drdy = 1;
|
ip_drdy = 1;
|
d_in = (d_out & ~ip_mask) | (ip_data & ip_mask);
|
d_in = (d_out & ~ip_mask) | (ip_data & ip_mask);
|
wr_en = 1;
|
wr_en = 1;
|
|
|
nxt_state[s_rdmod] = 0;
|
nxt_state[s_rdmod] = 0;
|
nxt_state[s_idle] = 1;
|
nxt_state[s_idle] = 1;
|
end
|
end
|
end // always @ *
|
end // always @ *
|
|
|
|
|
always @(`SDLIB_CLOCKING)
|
always @(`SDLIB_CLOCKING)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
begin
|
begin
|
state <= `SDLIB_DELAY 1;
|
state <= `SDLIB_DELAY 1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
state <= `SDLIB_DELAY nxt_state;
|
state <= `SDLIB_DELAY nxt_state;
|
end
|
end
|
end // always @ (`SDLIB_CLOCKING)
|
end // always @ (`SDLIB_CLOCKING)
|
|
|
generate
|
generate
|
if (use_txid != 0)
|
if (use_txid != 0)
|
begin : gen_txid_hold
|
begin : gen_txid_hold
|
always @(`SDLIB_CLOCKING)
|
always @(`SDLIB_CLOCKING)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
begin
|
begin
|
txid <= `SDLIB_DELAY 0;
|
txid <= `SDLIB_DELAY 0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
txid <= `SDLIB_DELAY nxt_txid;
|
txid <= `SDLIB_DELAY nxt_txid;
|
end
|
end
|
end // always @ (`SDLIB_CLOCKING)
|
end // always @ (`SDLIB_CLOCKING)
|
end // block: gen_txid_hold
|
end // block: gen_txid_hold
|
endgenerate
|
endgenerate
|
|
|
endmodule // sd_scoreboard_fsm
|
endmodule // sd_scoreboard_fsm
|
|
|