0
votes

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?

1
@toolic you are correct ofcourse, just a typo from writing/deleting code constantly and trying out different things. thanks! on the 1st posedge clk, the one_bit_output should be equal to the MSB of the char_rom data, setting the counter to 6. so you are correct, the counter is not starting correctly. the problem is that i have ve tried to create a counter with multiplay ways, and some dont synthesize properly on my fpga.underhiscanvas
@toolic do u think its a problem that comes from the counter?underhiscanvas
@toolic i disagree. we need synchronisation with other modules, and for that to be possible we need a clk. the synchronnisation is based on the clock.underhiscanvas
the purpose of the code, as i said is to display on a vga screen the number that was pressed on the keybord. so, as hsync and vsync signals are sent to the vga (from top left, going to top right, then retracing back to the start).underhiscanvas
on a specific time or to be exact, on a specific clock pulse, we will enter a display area, which is ie 400x200(h_pixel_counter is 200, v_line_counter is 400). that signal will remain active until we exit the area, lets say until 600x400. since we need to send data to the vga screen on specific times (25Mhz), we need a clock to achieve that. so every 1/(25Mhz) second we have a signal that declares whether we are in the display area or not. as a result, we cant know earlier the value of the display area.underhiscanvas

1 Answers

1
votes

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