所以,我试图综合我的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
,模拟是:
有人可以向我解释为什么在vga_clk的第一个脉冲上,输出不是预料到的吗?
答案 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