underhiscanvas
underhiscanvas

Reputation: 37

Verilog always@(..) output not working as expected

So, im trying to synthesize my verilog code to send data from ps2 keybord ->fpga->vga. Just for the background of the code, I want to press the button "1", and that to appear on the center of the screen (called the display_area)

I realised that something is not working as expected. After carefull debugging, i realised that the problem lies in the module that converts the parallel data bus from the rom, into serial output, to assign a value in each pixel.

The code itself is pretty simple, im just providing as much info as i can.

We need a positive edge of the clock to enter the always area (or a reset). If the value display_area_enable is 1, we activate a counter from 7 till 0 (8 cycles) to index the data from the rom.

However, on the first clock, if the display area becomes 1 the exact moment when the vga_clk pulse becomes 1, the counter gets the value as it should, but the one_bit_output (the output of the module) doesnt. One_bit_output gets its first correct value the 2nd time that the always block is accessed. as a result we need 9 cycles to access an 8 bit bus.

I ll provide the code and a modelsim testbench

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

and the simulation is :

verilog simulation code

Can someone explain to me why on the first pulse of the vga_clk, the output is not expected?

Upvotes: 0

Views: 3611

Answers (1)

Hida
Hida

Reputation: 798

Change one_bit_output so that it does not change in relation to the clock edge, but asynchronously in relation to the display_area_enable. The counter keeps track of which element to output. This is essentially a multiplexer with display_area_enable as the selector, or more likely an AND gate with one input being display_area_enable.

As toolic said, the synchronous one_bit_output cannot change on the same cycle as its activating signal. This is because of the set-up times of the flip-flops, the signal must be stable for some time before the clock edge. Now, if you are using one_bit_output to drive some flip-flop, then it MUST update on the next edge. Don't try to avoid this by using latches, that will make synthesis quite hard.

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

Upvotes: 1

Related Questions