Verilog $display用来在哪里输出信息?过程与步骤

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Verilog $display用来在哪里输出信息?过程与步骤相关的知识,希望对你有一定的参考价值。

在Verilog中调用$display系统函数,在哪儿显示?要求用什么软件,过程与步骤写清楚,谢谢!

调用$display系统函数,会在仿真工具的一个交互窗口显示,还有存在于仿真过程的log文件
比如,我使用仿真工具 modelsim/vcs, 对于modelsim来说,你运行run_simulation后会在左上的那个窗口显示$display内部的信息;对于vcs来说,如果你跑仿真了,那么中途可能就会出现你希望的那些信息,最后在仿真的log里面,会有所有的仿真过程中出现的所有信息
参考技术A 不可综合的语言,调试用的吧。顶层函数,目前我都只用,电路图连接。呵呵 参考技术B Verilog提供了丰富的系统函数,这为Testbench的编写提供了方便。尤其是IEEE1364-2005,其系统级建模的能力更强。

以前我一般常用到的系统函数只有几个:$readmemb,$readmemh,$display,$fmonitor,$fwrite,$fopen,$fclose等。通常需要对文件作预处理,才能用于Testbench读取。今天又尝试了几个其他的文件输入输出函数,不需要对文件进行预处理,直接使用需要的文件,只对需要的部分进行读取。

$fseek,文件定位,可以从任意点对文件进行操作;

$fscanf,对文件一行进行读写。

Verilog always@(..) 输出未按预期工作

【中文标题】Verilog always@(..) 输出未按预期工作【英文标题】:Verilog always@(..) output not working as expected 【发布时间】:2016-01-28 19:13:13 【问题描述】:

所以,我试图合成我的 verilog 代码以从 ps2 键盘->fpga->vga 发送数据。只是为了代码的背景,我想按下按钮“1”,它会出现在屏幕的中心(称为 display_area)

我意识到有些事情没有按预期工作。 经过仔细调试,我意识到问题在于将并行数据总线从 rom 转换为串行输出的模块,以在每个像素中分配一个值。

代码本身很简单,我只是提供尽可能多的信息。

我们需要时钟的上升沿进入始终区域(或复位)。如果 display_area_enable 的值为 1,我们将激活一个从 7 到 0(8 个周期)的计数器来索引来自 rom 的数据。

但是,在第一个时钟上,如果显示区域在 vga_clk 脉冲变为 1 的确切时刻变为 1,则计数器会得到应有的值,但 one_bit_output(模块的输出)不会。 One_bit_output 在第二次访问 always 块时获得其第一个正确值。因此,我们需要 9 个周期来访问 8 位总线。

我会提供代码和modelsim测试台

module shifter(reset,char_rom_data_out,vga_clk,display_area_enable,one_bit_output,counter);
input [7:0]char_rom_data_out;
input vga_clk,display_area_enable,reset;
output reg one_bit_output;
output reg [2:0]counter;
always @(posedge vga_clk or posedge reset)
begin
if (reset)
    begin
        counter=3'd7;
        one_bit_output=0;
    end
    else if (display_area_enable==1)
        begin 
        one_bit_output<=(char_rom_data_out[counter]==1);
        counter<=counter-1;
        end
    else if (display_area_enable==0) 
    begin
    counter<=3'd7;
    one_bit_output<=0;
   end
end
endmodule

module testbz();
reg reset,vga_clk,display_area_enable;
reg [7:0]char_rom_data_out;
wire [2:0] counter;
wire one_bit_output;

shifter dignitas(reset,char_rom_data_out,vga_clk,display_area_enable,one_bit_output,counter);

initial 
begin
reset<=1; char_rom_data_out<=8'b11110001; vga_clk<=0;display_area_enable=0; //sto 10 skaei o prwtos kyklos, kai meta ana 20
#5 reset<=0; display_area_enable<=0;
#5 display_area_enable<=1;
#160 display_area_enable<=0;
end
always
begin
 #10 vga_clk=~vga_clk;
 end

endmodule

模拟是:

有人可以向我解释为什么在 vga_clk 的第一个脉冲上,输出不是预期的吗?

【问题讨论】:

@toolic 你是对的,当然,只是不断编写/删除代码并尝试不同的东西的一个错字。谢谢!在第一个 posedge clk 上,one_bit_output 应该等于 char_rom 数据的 MSB,将计数器设置为 6。所以你是对的,计数器没有正确启动。问题是我已经尝试创建一个具有多重播放方式的计数器,但有些无法在我的 fpga 上正确合成。 @toolic 你认为这是来自柜台的问题吗? @toolic 我不同意。我们需要与其他模块同步,为此我们需要一个 clk。同步基于时钟。 代码的目的,正如我所说的,是在 vga 屏幕上显示在键盘上按下的数字。因此,当 hsync 和 vsync 信号被发送到 vga 时(从左上角,到右上角,然后回溯到起点)。 在特定的时间,或者准确的说,在特定的时钟脉冲上,我们会进入一个显示区域,即400x200(h_pixel_counter为200,v_line_counter为400)。该信号将保持活动状态,直到我们离开该区域,比如说直到 600x400。因为我们需要在特定时间(25Mhz)向VGA屏幕发送数据,所以我们需要一个时钟来实现这一点。所以每 1/(25Mhz) 秒我们就会有一个信号表明我们是否在显示区域中。结果,我们无法提前知道显示区域的值。 【参考方案1】:

更改one_bit_output,使其不随时钟沿而更改,但相对于display_area_enable 异步更改。计数器跟踪要输出的元素。这本质上是一个以display_area_enable 作为选择器的多路复用器,或者更可能是一个输入为display_area_enable 的与门。

正如toolic所说,同步one_bit_output不能在与其激活信号相同的周期内改变。这是因为触发器的建立时间,信号必须在时钟沿之前稳定一段时间。现在,如果您使用one_bit_output 驱动一些触发器,那么它必须在下一个边缘更新。不要试图通过使用锁存器来避免这种情况,这会使综合变得非常困难。

module shifter(reset,char_rom_data_out,vga_clk,display_area_enable,one_bit_output,counter);
input [7:0]char_rom_data_out;
input vga_clk,display_area_enable,reset;
output reg one_bit_output;
output reg [2:0]counter;
always @(posedge vga_clk or posedge reset)
begin
if (reset)
    begin
        counter<=3'd7;
        //one_bit_output<=0;
    end
    else if (display_area_enable==1)
        begin 
        //one_bit_output<=(char_rom_data_out[counter]==1);
        counter<=counter-1;
        end
    else if (display_area_enable==0) 
    begin
    counter<=3'd7;
    //one_bit_output<=0;
   end
end

  assign one_bit_output = display_area_enable ? char_rom_data_out[counter] : 0;


endmodule

【讨论】:

好的。生病尝试和生病让你知道。感谢所有反馈! 只是为了澄清(或混淆?):现在one_bit_output 是一个异步输出。这意味着在将其连接到其他模块时需要小心。具体来说,您必须知道display_area_enable 仅在上升沿发生变化。如果没有,您可能会将out_bit_output 更改得太接近时钟边缘。这可能会在连接到out_bit_output 的模块上损坏(创建 X),并且这会在您的设计中传播。良好的设计实践是让所有输出与时钟同步,尽管这并不总是可行的。 我还无法执行您的建议,但我很快就会执行。 Display_area_enable 是一个信号,就像您的建议一样声明:我们有一些计数器在“always”块内计数到某个值。在 always 块之外,我们将值分配给 display_area_enable。所以我想不会有问题。因此,one_bit_output 变成了伪异步输出,因为它可能会根据信号的值改变它的值,这会根据 clk! 改变它的值!我理解正确吗? 我已经模拟了你的建议,它似乎在我的测试台上运行良好。我必须综合它才能确定,但​​我几乎可以肯定它会起作用。 :) 。谢谢大家的建议。可能我需要更多地提高我的verilog技能:) 你似乎明白了,是的。 :-) 如果您想了解更多关于在您的设计中传播未知数的危险,您可以查看clock domain crossing。祝你好运!

以上是关于Verilog $display用来在哪里输出信息?过程与步骤的主要内容,如果未能解决你的问题,请参考以下文章

Verilog中的$display和$write任务

verilog $*命令

verilog之display

Verilog设计中#,$display,initial为啥不可综合?

verilog 中顶层模块实例引用多个模块时端口怎么连接

verilog里面always 与reg分别代表啥意思,有啥功用?为啥只对输出用reg,对输入不用?