verilog - Verilog 计数模块指南
问题描述
我正在尝试用 Verilog(或 VHDL)设计一个计数模块。它接收一个输入字节,并且在每个时钟脉冲上,它仅按字节中的“1”顺序计数。例如:如果输入字节是:'00001111;然后它计数并循环...... 00000001, 00000010, 00000100, 00001000,如果输入字节是:'00000011; 然后它计数并循环...... 00000001, 00000010,如果输入字节是:'01010101; 然后它计数并循环...... 00000001, 00000100, 00010000, 01000000,
我已经编写了这个 Verilog 代码。
module ripple_borrow ( req,
grant,
o_count,
o_shift_base1,
clk );
parameter WIDTH = 8;
parameter count_WIDTH = 3;
input [WIDTH-1:0] req; //input byte to enable which bits to count through
output [WIDTH-1:0] grant; //output byte to enable which bit has been chosen
output [count_WIDTH-1:0] o_count;
output [WIDTH-1:0] o_shift_base1;
input clk;
reg [WIDTH-1:0] shift_base1 = 8'b00000001; //bit to shift
wire [2*WIDTH-1:0] double_req = {req,req}; //double reg to accomodate roll over from calculations
wire [2*WIDTH-1:0] double_grant = double_req & ~(double_req-
shift_base1);//dounle grant to accomdate roll over
reg [count_WIDTH-1:0] count = 3'b000; //counter to drive shifted bit
always@(posedge clk)
begin
//adjust count via the grant to skip inactive clock cycles so granted value plays for one clock cycle only.
case(grant)
'h01: count = 3'b000;
'h02: count = 3'b001;
'h04: count = 3'b010;
'h08: count = 3'b011;
'h10: count = 3'b100;
'h20: count = 3'b101;
'h40: count = 3'b110;
'h80: count = 3'b111;
default: count = count;
endcase
count = count-1;
shift_base1 = 8'b00000001;
shift_base1 = shift_base1 << count; //shift bit by count amount.
end
assign grant = double_grant[WIDTH-1:0] | double_grant[2*WIDTH-1:WIDTH]; //concanterate double grant and pass to grant
assign o_count = count;
assign o_shift_base1 = shift_base1;
endmodule
这是测试台:
Heare is the testbench:
`timescale 1ns/1ns //Adjust to suit
module ripple_borrow_tb; // No ports!
parameter WIDTH = 8;
parameter count_WIDTH = 3;
reg [WIDTH-1:0]req ;
wire [WIDTH-1:0]grant ;
wire [count_WIDTH-1:0]o_count ;
wire [WIDTH-1:0]o_shift_base1 ;
reg clk ;
ripple_borrow uut (
.req ( req ),
.grant ( grant ),
.o_count ( o_count ),
.o_shift_base1 ( o_shift_base1 ),
.clk ( clk )
);
parameter PERIOD = 10; //adjust for your timescale
initial begin
$dumpvars(2, ripple_borrow_tb);
clk = 1'b0;
#(PERIOD/2);
forever
#(PERIOD/2) clk = ~clk;
end
initial begin
req='b11111111;
#(PERIOD*16);
req='b01010101;
#(PERIOD*8);
req='b00000011;
#(PERIOD*8);
$finish;
end
endmodule
在这个模拟中。一切都按预期工作。在每个时钟周期上,只有字节中有效的“1”被“授权”,并且它们仅在一个时钟周期内有效。然而。当我试着倒计时。“计数 = 计数-1”。授予的信号被卡住并保持在最高步骤。
如你看到的。除非整个字节都是'1'。它卡在 7 计数上。我的假设是,通过将 shift_base1 初始化为 '00000001,然后在每个时钟周期倒数到 7。它陷入了 0-7-0-7 循环。令人困惑的是,当整个字节处于活动状态时它才起作用。有人可以告诉我为什么会出错并帮助我解决问题。或者为我的问题提供更好的解决方案。甚至是VHDL中的东西。
我现在只使用 vivado 和编写 HDL 代码一两个月。我现在还在努力理解。我用 VHDL 和 Verilog 设计了一些基本的计数器。所以我的知识是有限的。任何帮助,将不胜感激。
谢谢你。
解决方案
在您的情况下,如果req == 3
then --> grant = 01
--> count = 7
--> ... 在您更改reqshift = 80
之前,没有任何算术方法可以解决这个问题。
正如评论中提到的,你应该在翻牌的代码中使用非阻塞赋值。
但在编码时,至少有两个错误:你使用count
andshift
作为临时变量和翻牌的输出。这是一个不好的做法。一般来说,使用临时变量,您应该使用以下方案:
always @(posedge clk) begin
tmp = some-expression;
out <= tmp;
end
否则会造成混乱。如果是计数器,我认为您的意思与使用临时变量不同,可能是默认值分配,例如
always @(posedge clk) begin
count <= count - 1;
case(grant)
h01: count = 3'b000;
...
endcase
```
或者默认使用它
default: count <= count - 1;
顺便说一句,永远不要使用像count = count;这样的表达式。这没有什么意义,可能会导致工具问题。
随着班次,你真的把它用作临时工。不。使用文字直接:shift_base1 <= 8'b1 << count;
或制作一个parameter one=8'b1; ... shift <= shift << one;
其他建议:
切勿在 DUT 模块的声明中使用reg、logic和其他 var 的初始化。它们可能无法合成。(电线没问题)。您应该使用重置信号创建正确的初始化。
推荐阅读
- xml - 为什么 XPath 表达式只选择第一个元素的文本?
- matlab - MATLAB 反向传播算法未按预期运行
- z3 - 在 Z3 中检查 N 路方程等价的最有效方法是什么?
- react-native - 使用异步初始化和设置函数测试 React (native) 钩子
- amazon-web-services - Istio Ingress 未显示地址(AWS 上的 Kubeflow)
- django - Django 通过模型预取 m2m
- python - 如何解决 TypeError: element_to_be_clickable() 需要 1 个位置参数?
- excel - 循环遍历 VBA 中的系列并根据单元格标准着色
- c# - 在数据表c#,asp.net核心中格式化文本
- windows - 为什么我的 npm install 不能与我的项目一起使用?