Verilog 32位Galois LFSR代码case语句误触发default分支问题
32位Galois LFSR的Verilog代码错误排查
我正在学习Verilog,尝试实现一个抽头位于第32、22、2、1位(位编号1-based)的32位Galois型线性反馈移位寄存器(LFSR),但代码运行报错,相关代码和错误信息如下:
原代码
module top_module( input clk, input reset, // 高电平有效同步复位至32'h1 output [31:0] q ); always @(posedge clk) begin if (reset) q <= 32'h1; else begin integer i; for (i=0; i<32; i=i+1) begin case (i) 0 : q[i] <= q[0] ^ q[i+1]; 1 : q[i] <= q[0] ^ q[i+1]; 21 : q[i] <= q[0] ^ q[i+1]; 31 : q[i] <= q[0]; default : q[i] <= q[i+1]; endcase end end end endmodule
错误信息
Error (10232): Verilog HDL error at top_module.v(17): index 32 cannot fall outside the declared range [31:0] for vector "q" File: /home/h/work/hdlbits.14205831/top_module.v Line: 17
我的疑问:我猜测是i=31时误触发了case语句的default分支,但已经为该情况单独设置了分支,请问哪里出错了?
错误原因
问题不在于i=31时触发了default分支,而是Verilog编译器会检查case语句所有分支中的表达式合法性,无论该分支是否会被执行。当i=31时,default分支里的q[i+1]等价于q[32],超出了q[31:0]的位宽范围,因此编译器直接抛出越界错误,哪怕这个分支在i=31时根本不会被触发。
另外还有一个隐藏问题:原代码中output [31:0] q没有声明为reg类型,但在always块中对q进行了赋值,这也是不符合Verilog语法的,需要修正为output reg [31:0] q。
修正方案
方案一:直接按位赋值(推荐,逻辑更清晰)
避开for循环的潜在问题,直接按照Galois LFSR的移位规则编写逻辑:
module top_module( input clk, input reset, // 高电平有效同步复位至32'h1 output reg [31:0] q ); always @(posedge clk) begin if (reset) q <= 32'h1; else begin // 先将所有位右移一位 reg [31:0] next_q; next_q = q >> 1; // 处理抽头的反馈逻辑(抽头对应索引31、21、1、0,对应1-based的32、22、2、1位) next_q[31] = q[0]; // 最高位由原最低位反馈 next_q[21] = q[22] ^ q[0]; // 第22位(索引21)与原最低位异或 next_q[1] = q[2] ^ q[0]; // 第2位(索引1)与原最低位异或 next_q[0] = q[1] ^ q[0]; // 第1位(索引0)与原最低位异或 q <= next_q; end end endmodule
方案二:拆分for循环,单独处理最高位
将for循环限制在0~30位,避免出现i=31时的越界表达式,再单独处理第31位:
module top_module( input clk, input reset, // 高电平有效同步复位至32'h1 output reg [31:0] q ); always @(posedge clk) begin if (reset) q <= 32'h1; else begin integer i; // 处理0~30位 for (i=0; i<31; i=i+1) begin case (i) 0 : q[i] <= q[0] ^ q[i+1]; 1 : q[i] <= q[0] ^ q[i+1]; 21 : q[i] <= q[0] ^ q[i+1]; default : q[i] <= q[i+1]; endcase end // 单独处理第31位 q[31] <= q[0]; end end endmodule
内容的提问来源于stack exchange,提问作者Anish Das
相关产品推荐
相关产品推荐

