verilog - 我需要生成如图所示的波形。在verilog代码中
问题描述
我需要生成一个波形,如图所示。但是使用我的代码,我没有得到预期的波形
在设计中,零件从测试台获得了随机周期内的最后一个有效值。我的问题是为什么我的值在有效不等于一时增加
设计代码:
module design_d(clk,valid,last,data);
input clk,valid,last;
output reg [7:0] data;
reg [7:0] i;
initial
begin
data=0;
i=0;
end
always @(posedge clk,valid)
begin
if (valid)
begin
data<=i;
i=i+1;
$display("i=%d data=%d ",i,data);
end
else
begin
data <=8'bz;
end
end
endmodule
测试台代码:
module test;
reg clk,valid,last;
wire [7:0] data;
parameter clk_period=2;
design_d dut(clk,valid,last,data);
initial
begin
clk=1;
valid=1;
last=0;
end
always #(clk_period/2) clk=~clk;
always @(posedge clk)
begin
last=0;
#4 last=1;
#clk_period last=0;
#8 last=1;
#clk_period last=0;
#10 last=1;
#clk_period last=0;
#16last=1;
#clk_period last=0;
#20 last=1;
#clk_period last=0;
end
always @(posedge clk or last)
begin
valid<=1;
wait(last==1)
#clk_period;
valid<=0;
#clk_period;
valid<=1;
end
initial
begin
$dumpfile("dump.vcd");
$dumpvars(1);
#24 $finish;
end
endmodule
解决方案
看来你的英语有困难,这不是你的错,但正因为如此,我可能会错误地解释你的问题。
你有一个你需要实现的波形。这对我来说表明这是一项学校作业,因此我会这样对待它。这意味着我**不会*给你一个完整的答案,但会给你一些关于你哪里出错的指示。(这都应该在评论中,但现在有合适的方式)。
...从测试台获得随机时间段内的最后一个有效值。
首先要意识到的是,编写测试平台与编写 RTL 代码本身一样困难,如果不是更困难的话。
在您的测试台中您正在使用always @(posedge clk)
但在该部分中您使用#...
语句。这本身并没有错。危险,是的,但没必要错。
但是
您的时钟的时间周期为 2 ( parameter clk_period=2;
),并且在您的 posedge 时钟内,您使用的延迟等于或大于时钟周期。正如您所发现的,这通常会导致灾难。
阅读 Verilog 的工作原理,尤其是在使用敏感度列表时always @...
:在处理完该部分中的所有语句之前不会触发它。在您的情况下,这意味着它将需要几个时钟边沿,直到再次启动 always 块。
测试台
我不知道任务是什么,所以我会使用你给出的波形。作为模块last
的valid
输入,我将为您提供如何制作这些的指示。
valid
4 个时钟周期为高电平,然后在 1 个时钟周期为低电平,然后重复。这意味着您需要一个每 5 个时钟周期重复一次的模式,因此您需要制作一个计数 0、1、2、3、4、0、1、2、3、4、...的计数器
你不应该这样做 using#.....
语句。您应该使用测试台时钟并制作一个计数的计数器!
制作一个如上所述计数的计数器是您需要在 HDL 中学习的第一件事!你会发现你必须一遍又一遍地这样做……在每一段 RTL 代码和每一个测试台上。
模 5 计数器。
我更喜欢我的所有模块和我的测试台进行重置。如果它允许我从已知状态开始新测试就好了。
reg [2:0] counter;
always @(posedge clk or negedge reset_n)
begin
if (reset_n)
counter <= ...
else // clocked section
begin
if (..)
counter <= ...
else
counter <= ...
end
end
重新开始并首先运行上述代码。观察计数器确实在运行 0,1 2, 3, 4, 0, .. 在继续之前。
派生信号。
接下来学习从中获取信号。
基本规则:在时钟部分,如果您需要计数器值为 X 的信号,则必须在周期 X-1 生成该信号。
因此,要在计数器为 3 时设置为最后一个高电平,您必须在计数器为 2 时设置它:
always @(posedge clk...
...
if (counter==3'h2)
last <= 1'b1;
else
last <= 1'b0;
我把有效的留给你。
一旦你开始运行你的测试台,就开始使用你的 design_d 模块。
一些技巧:
<=
在时钟部分中始终使用非阻塞分配。**不要使用 2 的时钟周期,使用 100 或 1000。您会在适当的时候发现为什么这样更好。
always @(posedge clk or [one or more signals] )
除非按照我的示例,否则不要使用。**注意缩进。我不得不对您的代码进行一些市长编辑。
**抱歉,我无法详细说明为什么大多数时候这是一种好习惯,因为这会使这个答案的大小增加三倍。现在请按照提示操作。
我本可以在我编写所有代码所用时间的十分之一的时间内编写实际代码,因此我希望您不会删除该问题,因为其他人可能会从中受益。
推荐阅读
- c++ - clang --version 权限被拒绝错误
- c# - 列出服务器共享
- ruby-on-rails - 在重命名键和自定义属性时覆盖 Rails as_json
- r - 直接使用 dplyr 改变数据库表中的变量
- jquery - 页面更改后,角度中的 Vendor.min.js 无法正常工作
- c# - Windows 应用程序打包项目试图打包两个相同的文件导致错误
- reactjs - 我似乎无法让 React 工作
- java - 使用 jackson 使用接口解析 Json
- mongodb - LoopBack 警告:id 属性不能从更改为
- sql - Presto 数组包含一个喜欢某种模式的元素