Verilog左右移位寄存器无移位输出问题求助
Verilog左右移位寄存器功能失效问题排查
我正在开发一款具备左右移位功能的Verilog移位寄存器,代码可正常编译,但测试时发现shift_left与shift_right操作均无法实现移位,输出始终为0。以下是代码的最小示例及测试平台代码,已查阅同类问题及Verilog文档但仍无法定位问题,恳请技术指导!
寄存器核心代码
module Shift_reg( output [3:0] dout, input [3:0] din, input shift_left, input shift_right, input clk, input rst ); wire d0, d1, d2, d3; wire q0, q1, q2, q3; wire s1 = shift_right & ~shift_left; wire s0 = shift_left & ~shift_right; Mux_4_1 mux0 (.f(d0), .i0(q0), .i1(q1), .i2(din[0]), .i3(1'b0), .s1(s1), .s0(s0)); Mux_4_1 mux1 (.f(d1), .i0(q1), .i1(q2), .i2(din[1]), .i3(q0), .s1(s1), .s0(s0)); Mux_4_1 mux2 (.f(d2), .i0(q2), .i1(q3), .i2(din[2]), .i3(q1), .s1(s1), .s0(s0)); Mux_4_1 mux3 (.f(d3), .i0(q3), .i1(1'b0), .i2(din[3]), .i3(q2), .s1(s1), .s0(s0)); D_flp dff0 (.dout(q0), .din(d0), .clk(clk), .rst(rst)); D_flp dff1 (.dout(q1), .din(d1), .clk(clk), .rst(rst)); D_flp dff2 (.dout(q2), .din(d2), .clk(clk), .rst(rst)); D_flp dff3 (.dout(q3), .din(d3), .clk(clk), .rst(rst)); assign dout = {q3, q2, q1, q0}; endmodule module Mux_4_1(f, i0, i1, i2, i3, s1, s0); input i0, i1, i2, i3, s1, s0; output f; wire s1_bar, s0_bar; wire w1, w2, w3, w4; not n1(s0_bar, s0); not n2(s1_bar, s1); and a1(w1, s1_bar, s0_bar, i0); and a2(w2, s1_bar, s0, i1); and a3(w3, s1, s0_bar, i2); and a4(w4, s1, s0, i3); or o1(f, w1, w2, w3, w4); endmodule module D_flp(dout, din, clk, rst); input din, clk, rst; output reg dout; always @(posedge clk or posedge rst) begin if (rst) dout <= 1'b0; else dout <= din; end endmodule
测试平台代码
module Shift_reg_mux_Sim; reg [3:0] din; reg shift_left; reg shift_right; reg clk; reg rst; wire [3:0] dout; Shift_reg uut ( .dout(dout), .din(din), .shift_left(shift_left), .shift_right(shift_right), .clk(clk), .rst(rst) ); initial begin clk = 0; forever #5 clk = ~clk; end initial begin rst = 1; din = 4'b0000; shift_left = 0; shift_right = 0; #10; rst = 0; #10 din = 4'b1010; #10 shift_left = 1; #10 shift_left = 0; #10 din = 4'b0000; #10 shift_right = 1; #10 shift_right = 0; #10 shift_left = 1; #10 shift_left = 0; #10 rst = 1; #10 rst = 0; #10 $finish; end initial begin $monitor("Time: %0t | din: %b | dout: %b | shift_left: %b | shift_right: %b | rst: %b", $time, din, dout, shift_left, shift_right, rst); end endmodule
问题根源分析
1. 数据加载逻辑未触发
测试平台中设置din=4'b1010后,没有触发寄存器的加载操作。根据多路选择器逻辑:
- 当
shift_left和shift_right都为0时,多路器选择i0输入(保持触发器当前值,复位后为0),不会加载din的数据; - 加载
din的条件是shift_right=1且shift_left=0,但测试流程中未设置该信号组合,导致寄存器始终保持复位后的0值。
2. 移位方向的多路器输入映射错误
移位逻辑方向完全搞反:
- 左移操作应让
q3←q2、q2←q1、q1←q0、q0←0,但当前代码中shift_left时,多路器选择的输入是右移逻辑(比如q0取q1); - 右移操作应让
q0←q1、q1←q2、q2←q3、q3←0,当前代码的输入映射也不符合该逻辑。
3. 测试平台时序控制问题
信号切换间隔为10ns(一个时钟周期),但未保证信号在时钟上升沿稳定生效,比如设置din后立即切换移位信号,可能导致加载操作根本未执行。
修正方案
1. 调整寄存器模块逻辑
新增load控制信号明确加载操作,修正多路器输入映射匹配正确移位方向:
module Shift_reg( output [3:0] dout, input [3:0] din, input shift_left, input shift_right, input load, // 新增加载控制信号 input clk, input rst ); wire d0, d1, d2, d3; wire q0, q1, q2, q3; // 定义选择信号:00=保持, 01=左移, 10=右移, 11=加载 wire [1:0] sel = {shift_right, shift_left}; // 修正多路器输入映射 Mux_4_1 mux0 (.f(d0), .i0(q0), .i1(1'b0), .i2(q1), .i3(din[0]), .s1(sel[1]), .s0(sel[0])); Mux_4_1 mux1 (.f(d1), .i0(q1), .i1(q0), .i2(q2), .i3(din[1]), .s1(sel[1]), .s0(sel[0])); Mux_4_1 mux2 (.f(d2), .i0(q2), .i1(q1), .i2(q3), .i3(din[2]), .s1(sel[1]), .s0(sel[0])); Mux_4_1 mux3 (.f(d3), .i0(q3), .i1(q2), .i2(1'b0), .i3(din[3]), .s1(sel[1]), .s0(sel[0])); D_flp dff0 (.dout(q0), .din(d0), .clk(clk), .rst(rst)); D_flp dff1 (.dout(q1), .din(d1), .clk(clk), .rst(rst)); D_flp dff2 (.dout(q2), .din(d2), .clk(clk), .rst(rst)); D_flp dff3 (.dout(q3), .din(d3), .clk(clk), .rst(rst)); assign dout = {q3, q2, q1, q0}; endmodule
2. 修改测试平台
加入加载操作,调整时序保证信号在时钟上升沿生效:
module Shift_reg_mux_Sim; reg [3:0] din; reg shift_left; reg shift_right; reg load; // 新增加载信号 reg clk; reg rst; wire [3:0] dout; Shift_reg uut ( .dout(dout), .din(din), .shift_left(shift_left), .shift_right(shift_right), .load(load), .clk(clk), .rst(rst) ); initial begin clk = 0; forever #5 clk = ~clk; end initial begin rst = 1; din = 4'b0000; shift_left = 0; shift_right = 0; load = 0; #10; rst = 0; // 加载数据:等待时钟上升沿完成加载 #5 din = 4'b1010; load = 1; #10 load = 0; // 左移一次 shift_left = 1; #10 shift_left = 0; // 右移一次 shift_right = 1; #10 shift_right = 0; // 左移两次 shift_left = 1; #20 shift_left = 0; rst = 1; #10 rst = 0; #10 $finish; end initial begin $monitor("Time: %0t | din: %b | dout: %b | shift_left: %b | shift_right: %b | load: %b | rst: %b", $time, din, dout, shift_left, shift_right, load, rst); end endmodule
3. 可选:简化多路选择器代码
用行为级描述代替门级描述,减少连线错误:
module Mux_4_1(f, i0, i1, i2, i3, s1, s0); input i0, i1, i2, i3, s1, s0; output reg f; always @(*) begin case({s1, s0}) 2'b00: f = i0; 2'b01: f = i1; 2'b10: f = i2; 2'b11: f = i3; endcase end endmodule
内容的提问来源于stack exchange,提问作者Kotupalli Venkata Siva Teja
相关产品推荐
相关产品推荐

