I am using the open source pulp_platform_common_cells
which has been implemented for Xilinx FPGAs, and I want to convert it so it also works in Quartus. In Vivado, the project synthesizes fine, but in Quartus, I get the following errors for the stream_throttle.sv
file:
This error happens at the FF(credit_q, credit_d, '0, clk_i, rst_ni)
part where `FF is a macro.
If I put the contents of the macro there instead, everything synthesizes just fine. What could be the issue with this macro?
The error happens near the end of the code. I marked what does work and what doesn't with comments. For simplicity, I put the macro its complaining about at the top.
`define FF (__q, __d, __reset_value, __clk , __arst_n ) \
always_ff @(posedge (__clk) or negedge (__arst_n)) begin \
if (!__arst_n) begin \
__q <= (__reset_value); \
end else begin \
__q <= (__d); \
end \
end
/// Throttles a ready valid handshaked bus. The maximum number of outstanding transfers have to
/// be set as a compile-time parameter, whereas the number of outstanding transfers can be set
/// during runtime. This module assumes either in-order processing of the requests or
/// indistinguishability of the request/responses.
module stream_throttle (clk_i, rst_ni, req_valid_i, req_valid_o, req_ready_i, req_ready_o, rsp_valid_i, rsp_ready_i, credit_i);
/// The maximum amount of allowable outstanding requests
parameter MaxNumPending = 1,
/// The width of the credit counter (*DO NOT OVERWRITE*)
CntWidth = cf_math_pkg::idx_width(MaxNumPending);
/// The type of the credit counter (*DO NOT OVERWRITE*)
typedef logic [cf_math_pkg::idx_width(MaxNumPending)-1:0] credit_t;
/// Clock
input logic clk_i;
/// Asynchronous reset, active low
input logic rst_ni;
/// Request valid in
input logic req_valid_i;
/// Request valid out
output logic req_valid_o;
/// Request ready in
input logic req_ready_i;
/// Request ready out
output logic req_ready_o;
/// Response valid in
input logic rsp_valid_i;
/// Response ready in
input logic rsp_ready_i;
/// Amount of credit (number of outstanding transfers)
input credit_t credit_i;
// we use a credit counter to keep track of how many transfers are pending at any point in
// time. Valid is passed-through if there is credit.
credit_t credit_d;
credit_t credit_q;
// we have credit available
logic credit_available;
// implement the counter. If credit is available let the valid pass, else block it. Increment
// the counter once a request happens, decrement once a response arrives. Assumes in-order
// responses.
always_comb begin : proc_credit_counter
// default: keep state
credit_d = credit_q;
// on valid outgoing request: count up
if (req_ready_o & req_valid_o) begin
credit_d = credit_d + 'd1;
end
// on valid response: count down
if (rsp_valid_i & rsp_ready_i) begin
credit_d = credit_d - 'd1;
end
end
// credit is available
assign credit_available = credit_q <= (credit_i - 'd1);
// a request id passed on as valid if the input is valid and we have credit.
assign req_valid_o = req_valid_i & credit_available;
// a request id passed on as ready if the input is ready and we have credit.
assign req_ready_o = req_ready_i & credit_available;
// state
`FF(credit_q, credit_d, '0, clk_i, rst_ni) // THIS DOES NOT WORK
// always_ff @(posedge (clk_i) or negedge (rst_ni)) begin // THIS DOES WORK
// if (!rst_ni) begin
// credit_q <= ('0);
// end else begin
// credit_q <= (credit_d);
// end
// end
endmodule : stream_throttle
The probelm is the whitespace between FF
and (
in the macro declaration. Change:
`define FF (__q, __d, __reset_value, __clk , __arst_n ) \
to:
`define FF(__q, __d, __reset_value, __clk , __arst_n ) \
Refer to IEEE Std 1800-2017, section 22.5.1 `define:
The left parenthesis shall follow the text macro name immediately, with no space in between.
Since Vivado accepted your syntax, Vivado does not comply with the Std in this case.