1
\$\begingroup\$

I am trying to create an program that bit bangs a value from an FPGA to an arduino. In the module I created, every other clock cycle, the FPGAdata output should be set to the next bit of t. The problem is that FPGAdata equals 1 the entire time. What is causing this?

module fpgaread(ARDUINOclk, FPGAclk, FPGAdata);
input ARDUINOclk;
output reg FPGAdata;
output reg FPGAclk;


reg [15:0] count=0;
reg [127:0] t =3542638353836;

always @ (posedge ARDUINOclk) begin
        count=count+1;
        if(count%2==0) begin
            FPGAclk = 0;
        end else if (count <= 256) begin
            FPGAdata=t[(count-1)/2];
            FPGAclk = 1;
        end else begin
            count = 0;
        end
end

endmodule

Note t is just a number that I am testing with. In the future I want to make it be a variable and not just constant.

The purpose of the <256 is that I want to send 128 bits. In the future I would add more code in the else for a reset, but this does not effect the question because the output is 1's before it even gets to the end.

I am using quartus II v13 with a Cyclone II

EDIT: Here is a schematic of what quartus sees from the program. FPGAdata is just set to 1. enter image description here

\$\endgroup\$
  • \$\begingroup\$ Not sure if they will solve the issue, but I have several comments/suggestions. Firstly, declare the width of your constants - 128'd3542638353836, 16'd256, etc. Secondly, try to avoid blocking assignments for registers, use non-blocking (<=) instead - to do this you would have to rearrange your logic a bit to do that though. Thirdly, split up your logic - you are embedding a counter, a clock signal, and the data signal all in one always block which just gets messy - lines of code doesn't equate to number of logic elements, so use as many as you need. \$\endgroup\$ – Tom Carpenter Mar 17 '16 at 2:59
  • \$\begingroup\$ This infers correctly. I've made the changes I suggested above. Once you synthesise it, you should notice that there are several differences in the indexes being used on various signals purely because the constants are scaled to the correct widths. \$\endgroup\$ – Tom Carpenter Mar 17 '16 at 3:06
2
\$\begingroup\$

I think the issue is most likely down to a combination of not setting the correct bit widths for constants, and using blocking assignments.

Generally it is important to set the width of any constants you use. Not only does this eliminate warnings from the synthesiser from truncation of signals, but it also helps give the synthesiser a better impression of what you are trying to infer. Remember, you are not writing code like you would for an Arduino, you are describing hardware.

Because you are describing hardware, it doesn't actually matter how many lines of code you take up - reducing the number of lines doesn't necessarily have any impact on the size of the design, it just makes it harder to read for both you and the synthesis tools. To that end, split up your design into blocks - use multiple always blocks for different signal groups. If you have a counter, use a separate block for it so it is clear what code is for the counter - you can even put it in a separate module if you want to make the RTL output easier to read.

It is also good practice to stick to non-blocking assignments. I'm not going to go into details on the differences as there are questions both here and on StackOverflow that describe them nicely. But suffice it to say, there are subtle differences that can catch you out if you are not careful. Using all non-blocking helps to keep these subtleties at bay, but I accept it also takes a little extra thought because it reinforces the fact that this is an HDL language not a procedural one.

With the above in mind, I have tidied up your code based on the above. The counter is separated from the other signals, only non-blocking statements are being used, and I have fixed the constant widths:

module fpgaread(ARDUINOclk, FPGAclk, FPGAdata);

input ARDUINOclk;
output reg FPGAdata;
output reg FPGAclk;


reg [15:0] count= 16'd0;
reg [127:0] t = 128'd3542638353836;

//Counter
always @ (posedge ARDUINOclk) begin
    if (count < 16'd256) begin
        count <= count + 16'd1;
    end else begin
        count <= 16'd0;
    end
end

//External interface
always @ (posedge ARDUINOclk) begin
    if (!count[0]) begin //see if it is even by checking the LSB. You can use %2 if you want, but in complex cases it can infer horrid logic.
        FPGAclk <= 1'b0; //Falling edge
    end else if (count < 16'd256) begin
        FPGAclk <= 1'b1; //Rising edge
        FPGAdata <= t[count[15:1]]; //data goes out on rising edge.
    end
end

endmodule

As a result, the inferred RTL is now this:

Inferred Logic

Much better.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.