Verilog总是@(..)输出不按预期工作

时间:2016-01-28 19:13:13

标签: verilog

所以,我试图综合我的verilog代码从ps2 keybord发送数据 - > fpga-> vga。仅仅为了代码的背景,我想按下按钮“1”,然后出现在屏幕的中心(称为display_area)

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

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

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

但是,在第一个时钟上,如果显示区域变为1,即vga_clk脉冲变为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

,模拟是:

verilog simulation code

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

1 个答案:

答案 0 :(得分:1)

更改one_bit_output,使其不会相对于时钟边缘发生变化,而是相对于display_area_enable异步变化。计数器跟踪要输出的元素。这本质上是一个多路复用器,display_area_enable作为选择器,或者更可能是AND门,其中一个输入为display_area_enable

正如工具所说,同步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