Quartus中Verilog HDL语法错误10170排查求助
平方根计算Verilog模块Quartus编译语法错误排查
问题概述
复制的平方根计算Verilog模块在Quartus中编译时触发Error(10170)语法错误,错误指向输入端口定义的wire logic处,移除wire关键字后问题仍未解决。
错误信息
- Error (10170): Verilog HDL syntax error at sqrtvg.sv(5) near text "logic"; expecting an identifier ("logic" is a reserved keyword ), or "[", or "signed", or "unsigned"
- Error (10170): Verilog HDL syntax error at sqrtvg.sv(6) near text "logic"; expecting an identifier ("logic" is a reserved keyword ), or "[", or "signed", or "unsigned"
- Error (10170): Verilog HDL syntax error at sqrtvg.sv(9) near text "logic"; expecting an identifier ("logic" is a reserved keyword ), or "[", or "signed", or "unsigned"
- Error (10112): Ignored design unit "sqrtvg" at sqrtvg.sv(1) due to previous errors
原代码
module sqrt #( parameter WIDTH=8, // width of radicand parameter FBITS=0 // fractional bits (for fixed point) ) ( input wire logic clk, input wire logic start, // start signal output logic busy, // calculation in progress output logic valid, // root and rem are valid input wire logic [WIDTH-1:0] rad, // radicand output logic [WIDTH-1:0] root, // root output logic [WIDTH-1:0] rem // remainder ); logic [WIDTH-1:0] x, x_next; // radicand copy logic [WIDTH-1:0] q, q_next; // intermediate root (quotient) logic [WIDTH+1:0] ac, ac_next; // accumulator (2 bits wider) logic [WIDTH+1:0] test_res; // sign test result (2 bits wider) localparam ITER = (WIDTH+FBITS) >> 1; // iterations are half radicand+fbits width logic [$clog2(ITER)-1:0] i; // iteration counter always_comb begin test_res = ac - {q, 2'b01}; if (test_res[WIDTH+1] == 0) begin // test_res ≥0? (check MSB) {ac_next, x_next} = {test_res[WIDTH-1:0], x, 2'b0}; q_next = {q[WIDTH-2:0], 1'b1}; end else begin {ac_next, x_next} = {ac[WIDTH-1:0], x, 2'b0}; q_next = q << 1; end end always_ff @(posedge clk) begin if (start) begin busy <= 1; valid <= 0; i <= 0; q <= 0; {ac, x} <= {{WIDTH{1'b0}}, rad, 2'b0}; end else if (busy) begin if (i == ITER-1) begin // we're done busy <= 0; valid <= 1; root <= q_next; rem <= ac_next[WIDTH+1:2]; // undo final shift end else begin // next iteration i <= i + 1; x <= x_next; ac <= ac_next; q <= q_next; end end end endmodule
问题根源与解决方法
核心原因
代码使用了SystemVerilog语法(logic关键字、always_comb、always_ff、$clog2),但Quartus默认可能以Verilog-2001或更早标准编译,而logic在传统Verilog中是保留关键字但不能用于端口声明,导致语法报错。
解决方案
方案1:切换Quartus编译标准为SystemVerilog
- 打开Quartus工程,点击
Assignments→Settings - 在左侧导航栏选择
Language Settings→Verilog HDL Input - 将
Verilog HDL version设置为SystemVerilog - 重新编译工程
此时可保留SystemVerilog语法,只需移除端口声明中冗余的wire(logic会自动根据端口方向推断类型:输入为wire,输出为reg),修正后的端口声明如下:
input logic clk, input logic start, // start signal output logic busy, // calculation in progress output logic valid, // root and rem are valid input logic [WIDTH-1:0] rad, // radicand output logic [WIDTH-1:0] root, // root output logic [WIDTH-1:0] rem // remainder
方案2:修改代码兼容Verilog-2001标准
如果需要兼容传统Verilog环境,将SystemVerilog特有的语法替换为Verilog兼容写法:
- 端口声明中,
input wire logic改为input wire,output logic改为output reg - 内部
logic替换为reg(always块内的信号用reg) always_comb改为always @*,always_ff @(posedge clk)改为always @(posedge clk)$clog2替换为手动计算的位宽(可根据参数范围设定固定位宽,或开启Quartus扩展支持使用$clog2)
修正后的Verilog兼容代码示例:
module sqrt #( parameter WIDTH=8, // width of radicand parameter FBITS=0 // fractional bits (for fixed point) ) ( input wire clk, input wire start, // start signal output reg busy, // calculation in progress output reg valid, // root and rem are valid input wire [WIDTH-1:0] rad, // radicand output reg [WIDTH-1:0] root, // root output reg [WIDTH-1:0] rem // remainder ); reg [WIDTH-1:0] x, x_next; // radicand copy reg [WIDTH-1:0] q, q_next; // intermediate root (quotient) reg [WIDTH+1:0] ac, ac_next; // accumulator (2 bits wider) reg [WIDTH+1:0] test_res; // sign test result (2 bits wider) localparam ITER = (WIDTH+FBITS) >> 1; // iterations are half radicand+fbits width // 手动计算位宽,适配WIDTH=8的场景,可根据参数范围调整 reg [3:0] i; // iteration counter always @* begin test_res = ac - {q, 2'b01}; if (test_res[WIDTH+1] == 0) begin // test_res ≥0? (check MSB) {ac_next, x_next} = {test_res[WIDTH-1:0], x, 2'b0}; q_next = {q[WIDTH-2:0], 1'b1}; end else begin {ac_next, x_next} = {ac[WIDTH-1:0], x, 2'b0}; q_next = q << 1; end end always @(posedge clk) begin if (start) begin busy <= 1; valid <= 0; i <= 0; q <= 0; {ac, x} <= {{WIDTH{1'b0}}, rad, 2'b0}; end else if (busy) begin if (i == ITER-1) begin // we're done busy <= 0; valid <= 1; root <= q_next; rem <= ac_next[WIDTH+1:2]; // undo final shift end else begin // next iteration i <= i + 1; x <= x_next; ac <= ac_next; q <= q_next; end end end endmodule
内容的提问来源于stack exchange,提问作者Antel
相关产品推荐
相关产品推荐

