what's wrong with this code?

FPGA projects on this site, or abroad

what's wrong with this code?

Postby leeguy » Sun Sep 28, 2008 9:11 pm

hi, i want to debounce a switch(even though the switches on my board have debounce caps, i wanna learn the theory)

here is my debouncer module:
Code: Select all
module debouncer(clk,button,out,counter);
input clk;
input button;
output reg out;


output reg [20:0] counter;
reg counting;
wire same = (out==button);

always @(posedge clk)
   begin
      if(!same)   counting <= 1;
      if(counting) counter <= counter + 1;
      if(counter == 100) counter <= 0; out <= button; counting <= 0;
   end
endmodule


the idea is that if the button input differs from the output register, the counter starts.
when the counter has finished counting, the counter is emptied, the output is set to the button input, and the counting ceases.

the compiler reduces the counting reg to GND, because the reg's D port is 'stuck'.
here is the actual message:
Code: Select all
Warning (14130): Reduced register "debouncer:inst1|counting" with stuck data_in port to stuck value GND

how is it stuck, shouldn't it be loaded with a 1 as soon as the input is different from the output?

i notice that this code is very small in comparison to the debouncer on this site, why would this circuit be inadequate?
leeguy
 
Posts: 9
Joined: Thu Sep 04, 2008 10:05 pm

Postby NickH » Sun Sep 28, 2008 10:25 pm

There's a few (mostly minor) things wrong with it:

1) The warning is because you forgot to put a begin/end around this group of statements (carriage returns are not significant in Verilog):
Code: Select all
if(counter == 100) begin
  counter <= 0;
  out <= button;
  counting <= 0;
end

Otherwise the compiler just sees "out <= button" and "counting <= 0" as unconditional statements.

2) Remember, all the code in the block will be considered before any of the variables change. If you set the same variable with "<=" in more than one place, only the last version is used.
Using "else" and maybe re-ordering the conditions, might make it clearer.

3) Asynchronous inputs should be synchronized to avoid metastability. It's best to buffer "button" with 2 flipflops before using it in any logic.

4) Depending on clock speed, you might want to increase the time-limit above 100. Give it a few milliseconds to settle.

Regards,

Nick
NickH
 
Posts: 88
Joined: Tue Sep 02, 2008 1:53 pm

Postby leeguy » Mon Sep 29, 2008 6:34 pm

thanks, nick, it's working as expected now.
so what kind of metastability could arise which could be fixed with 2 latches(why 2??)?

right now i'm having probs with my code for an ALU:
Code: Select all
module ALU(A, B, control, Y, Zflag, Cflag);

/*ALU Functions:
      000 - ADD
      001 - AND
      010 - OR
      011 - NOT A
      100 - XOR
      101 - SHIFT B(Bypass B)
      110 - MOV(Bypass A)
      */
      
input [15:0] A;
input [15:0] B;
input [2:0] control;
output [15:0] Y;
output Zflag;
output Cflag;
wire [16:0] result;
assign Y = result[15:0];
assign Zflag = (Y==0);
assign Cflag = result[16];

always @(A or B or control) begin
case(control)
   0:
      result=A+B;
   1:
      result=A&B;
   2:
      result=A|B;
   3:
      result=!(A);
   4:
      result=A^B;
   5:
      result=B;
   6:
      result=A;
endcase end

endmodule

my problem is that i am getting the error:
Code: Select all
Error (10137): Verilog HDL Procedural Assignment error at ALU.v(29): object "result" on left-hand side of assignment must have a variable data type

for each case.
the idea is to put the result on the "result" wires, the first 16 bits are assigned to Y(the ALU output) and the 17th bit is assigned to Cflag(the carry flag).
leeguy
 
Posts: 9
Joined: Thu Sep 04, 2008 10:05 pm

Postby leeguy » Tue Sep 30, 2008 12:30 am

all working now. also had to change !(A) to ~A.
i did it by using
Code: Select all
assign = (control==0)? A+B : (control==1)? A&B


some more questions have been nagging at me:
what actually governs the sequence inside begin-end blocks,
is it always the clock connected to one of the dedicated clock inputs?
how can you tell the fpga what dedicated clock input you are using(there are about 8 in my fpga, which is a cyclone III, and only 1 is connected to the oscillator)?
is there a way to tell a begin-end block to use a different source for clocking?
does each 'operation' in a block take one clock cycle?

i have quite a few unknowns, and would appreciate any help with understanding them.
leeguy
 
Posts: 9
Joined: Thu Sep 04, 2008 10:05 pm

Postby NickH » Tue Sep 30, 2008 12:32 pm

The thing is, Verilog was a simulation language before it was a synthesis language. To understand it, you have to think like a simulator!

For a simulator, "always" means create a process [thread] in an endless loop. All the always blocks run in parallel with one another. The "@(posedge clock)" makes it wait until the next clock edge. Then everything inside the begin...end is executed, in order, without delay. Most operations take no time at all. But "<=" assignments don't take effect immediately: the variables only get updated when the simulator has run out of things to do in the current timestep.

What I just described is a model of an edge-triggered flipflop. So synthesis tools will detect it and generate flipflops.

Alternatively, if you write "always @(A or B or control)" then it will execute the block whenever any input changes. The "=" assignments mean that variables are updated immediately, so other blocks will get to see them straight away. That's a model of combinational logic.

[The reason it didn't work before is, "result" should have been declared "reg" (not "wire") because you wrote to it from an "always" block (not "assign").]

FPGAs can use only a small number of clocks. I don't know how it works on Cyclone, but on some FPGAs they must come from dedicated inputs, or special clock-handling modules. You should have something like a "constraints file" which tells the tools which pins correspond to what signal names, and how fast the clocks run. It's up to the synthesis tools to tell you whether or not your design can be implemented.

Nick
NickH
 
Posts: 88
Joined: Tue Sep 02, 2008 1:53 pm

Postby leeguy » Tue Sep 30, 2008 11:13 pm

ah, thankyou, i see what has been confusing me all of this time.
i thought that some kind of FSM was generated for each begin/end block, and the operations were actually carried out "sequentially", as in clocked, so that a block with 9 operations in it would take 9 cycles to complete, ive still got my programmer's head on.
now i realise that everything is carried out on the rising/falling edge.

ive been having a look at some of the high-end stratix FPGAs, £400 for just one chip! and i was on the altera forums, asking about the starter kit's absence of RS232, and i was recommended this all singing-all dancing adapter board for about £125.

Seems like this FPGA business can get expensive(i guess you could call me a hobbyist).

IP stuff gives me the creeps, is that unreasonable? i just like it all my own work.
leeguy
 
Posts: 9
Joined: Thu Sep 04, 2008 10:05 pm

Postby NickH » Fri Oct 03, 2008 9:46 am

Well the traditional way to write a FSM is with a big case statement like this:
Code: Select all
parameter ST_IDLE = 2'b00;
parameter ST_FOO  = 2'b01;

reg [1:0] state = ST_IDLE;

always @(posedge clock) case (state)
  ST_IDLE: begin
    if (myinput) begin
      myoutput <= 1;
      counter <= 0;
      state <= ST_FOO;
    end
  end
  ST_FOO: begin
    if (counter >= 42) begin
      myoutput <= 0;
      state <= ST_BAR;
    end
    else counter <= counter + 1;
  end
// ...etc...
endcase

...you get the idea. Each "if" basic block is one transition, and happens in a single cycle. You can write code in this style that looks pretty much like software. [Though the implementation gets bloaty when you have more than a few dozen states, because it's calculating all possibilities in parallel and selecting just one: the "where to go next" decision is physically made by multiplex logic in front of the state register.]

I know what you mean about IP, but if you want to talk a complicated protocol like USB or drive some weird peripheral, it's a necessary evil.

Regards,

Nick
NickH
 
Posts: 88
Joined: Tue Sep 02, 2008 1:53 pm


Return to General projects