0
votes

The following code implements (or should implement) a 7 segment driver that reads a value from some switches and shows that value in the 4 7 segment displays. The simulation works fine, but when it runs in the FPGA the 7 segment displays show something for a fraction of time and then no segment lights up. I have no idea why it doesn't work. Also, I implemented a simple counter. When I had "<=" inside of the always blocks it worked and when I had "=" it didn't, but in simulation it worked with both. The difference between "<=" and "=" is just that "<=" runs in parallel and "=" in sequence?

I should also say that it works if instead of sending the value from the switches to the display module I send a constant value.

display.v:

module display(
    input [15:0] count,
    output reg [6:0] seg,
    output dp,
    output [3:0] an,
    input clk
    );

reg [3:0] an_temp;
reg [6:0] rom [9:0];

initial
begin
    an_temp <= 1;
    rom[0] <= 'b1000000;
    rom[1] <= 'b1111001;
    rom[2] <= 'b0100100;
    rom[3] <= 'b0110000;
    rom[4] <= 'b0011001;
    rom[5] <= 'b0010010;
    rom[6] <= 'b0000010;
    rom[7] <= 'b1111000;
    rom[8] <= 'b0000000;
    rom[9] <= 'b0110000;
end

assign dp = 1;
assign an = ~an_temp;

wire [3:0] disp [3:0];

assign disp[0] = count % 10;
assign disp[1] = ((count - disp[0])/10) % 10;
assign disp[2] = ((count - disp[1]*10 - disp[0])/100) % 10;
assign disp[3] = ((count - disp[2]*100 - disp[1]*10 - disp[0])/1000) % 10;

always @ (posedge clk)
begin
    if (an_temp == 'b1000) an_temp = 1;
    else an_temp = an_temp = 1;
    case (an_temp)
        'b0001: seg <= rom[disp[0]];
        'b0010: seg <= rom[disp[1]];
        'b0100: seg <= rom[disp[2]];
        'b1000: seg <= rom[disp[3]];
        default: seg <= 'b1111111;
    endcase
end

endmodule

disp_clk.v:

module disp_clk(
    input clk,
    output disp_clk
    );

reg [31:0] count;

initial count = 0;

always @ (posedge clk)
begin
    count = count + 1;
    if (count == 400000) count = 0;
end

assign disp_clk = (count > 200000) ? 1 : 0;

endmodule

top.v:

module top(
    input clk,
    input [15:0] sw,
    output [6:0] seg,
    output dp,
    output [3:0] an
    );

wire disp_clk;

disp_clk disp_clk0(
    .clk(clk),
    .disp_clk(disp_clk)
    );

display disp0(
    .count(sw),
    .seg(seg),
    .dp(dp),
    .an(an),
    .clk(disp_clk)
    );

endmodule

Thank you

1
Sorry, somehow it appeared that way after copying. The correct is: else an_temp = an_temp << 1;Ricardo Nunes
This works if I replace sw by some constant on the top module.Ricardo Nunes
Where do you change the value of the an_temp, for me, it looks like you always have an_temp=1 and you always show "'b0001: seg <= rom[disp[0]];"FarhadA
It's right above the switch block. Look the previous comments. Thank youRicardo Nunes

1 Answers

0
votes

I should also say that it works if instead of sending the value from the switches to the display module I send a constant value.

Sounds like you are not meeting your timing window. If count is a constant vector, then the disp assignments should all be precomputed in synthesis. Otherwise, they need to be computed on the fly, and the requisite logic is inferred (which is rather slow).

((count - disp[2]*100 - disp[1]*10 - disp[0])/1000) % 10 has a multiplier feeding into a division feeding into another division. One would hope that this is being inferred as cascading DSPs, but you should check your resource report to make sure, and as an added sanity check make sure the resource count for constant vs switched signaling shows a difference.

You may need to pipeline these operations if you cannot think of more optimal logic.

The difference between "<=" and "=" is just that "<=" runs in parallel and "=" in sequence?

Yes, in a sense. <= and = refer to non-blocking and blocking assignments respectively.

The simulator will compute logic assignment on every time step.

For non-blocking, the right hand side is computed and may be updated later in the time step if it is logically dependent on other signaling, then just before the next time step begins, the left hand side of all the non-blocking assignments are assigned to the updated right hand side.

In a blocking assignment, the simulator will evaluate the right hand side and immediately assign it to the left hand side, in this way other logic is blocked from altering the assignment.

You can consider this sequential, but keep in mind that the sequentiality is only true within a functional block. If you have two always blocks that perform co-dependent evaluations on the same time step, you are not guaranteed which block the simulator will evaluate first and you might see some bizarre behavior based on how the simulator does it's scheduling.

Best practice is to use blocking assignments for behaviors that are intended to be combinatorial (i.e. always@(*)), and non-blocking assignments for those that are intended to be sequential (i.e. always@(posedge Clock)).