Designing counter on Verilog with input button - verilog

I'm creating some counter that counts +1, -1, and +2 with respect to button input 001, 010, 100.
Here is my code.
module binary_counter(
input clk,
input resetn,
input [2:0] push,
output [3:0] data_out
);
reg [3:0] data_temp_out;
always #(posedge clk or negedge resetn) begin
if(~resetn) begin
data_temp_out <= 4'b0; // all 0
end
else if(resetn == 1) begin // else
if(push == 3'b001) begin
data_temp_out <= data_temp_out +1; // count +1
end
else if(push == 3'b010) begin // count-1
data_temp_out <= data_temp_out -1;
end
else if(push == 3'b100) begin // count+3
data_temp_out <= data_temp_out +3;
end
end
end
assign data_out = data_temp_out;
endmodule
With some topModule and clock signal given, I implemented this counter on FPGA board. The push[2:0] is connected to three push button. What the problem is, if I keep pressing the button, the count keeps rising.
What I desired was to count only when button input is changed. I mean it only counts +1 even if I keep push button1 (001) and same for other button input.
Can you give me a hint or solution?

Because the condition push == 3'b001 is constantly met when you keep pushing button1.
Instead, you can create a push-value-change event which is single-cycle pulse, by comparing the current push with the last push.
reg [2:0] push_d;
wire push_chg;
always #(posedge clk or negedge resetn) begin
if(~resetn) begin
push_d <= 3'h0;
end
else begin
push_d <= push;
end
end
assign push_chg = (push != push_d);
Then evaluate the push value when the above event occurs.
if(push_chg & (push == 3'b001)) begin
...
end

Related

Verilog code, same structure, same style. How come one works but the other doesnt? Where did I go wrong?

I will get straight to the point. I have a simple counter that is trying to
mimic how a clock works pretty much. I have a module called counter60sec and another one called counter12hr
counter12hr
module counter12hr(reset, hourInc, overflowOut, hrCounter);
input reset;
input hourInc;
output overflowOut;
output [3:0] hrCounter;
reg overflowOut;
reg [3:0] hrCounter; //0'b1101 == 13 hours
//Initialize counter
initial begin
overflowOut = 1'b0;
hrCounter = 4'b0; //once hour reaches 12:59:59, it is supposed to go back to zero
end
//Everytime hrInc is one, increment hrCounter
always#(negedge reset or posedge hourInc) begin
overflowOut = 1'b0;
if(reset == 1'b0) begin
overflowOut = 1'b0;
hrCounter = 4'b0;
end
else begin
if (hourInc == 1'b1) begin
hrCounter = hrCounter + 1'b1;
end
end
end
always#(negedge hrCounter) begin
if (hrCounter == 4'b1100) begin
overflowOut = 1'b1;
hrCounter = 4'b0;
end
end
endmodule
counter60sec
module counter60sec(reset, secInc, minOut, secCounter);
input reset;
input secInc;
output minOut;
output [5:0] secCounter;
reg [5:0] secCounter; //0'b111100 == 60 seconds.
reg minOut;
//Initialize counter
initial begin
minOut = 1'b0;
secCounter = 6'b0;
end
//Everytime secInc is one, increment secCounter
always#(posedge secInc or negedge reset) begin
minOut = 1'b0;
if(reset == 1'b0) begin
minOut = 1'b0;
secCounter = 6'b0;
end
else begin
if (secInc == 1'b1) begin
secCounter = secCounter + 1'b1;
end
end
end
//output minOut to 1 to signal minute increase when secCounter hits 111100 in binary
always#(negedge secCounter) begin
if(secCounter == 6'b111100) begin
minOut = 1'b1;
secCounter = 6'b0;
end
end
endmodule
I have test bench set up for both. The counter60sec one works fine (Where when secCounter is at value of 60, the minOut becomes 1). The counter12hr follows the same concept, but the value of overflowOut never becomes 1.
For my hrCounter conditional statement in counter12hr.v, I have tried both 4'b1101 and 4'b1100 and neither of them worked. (Trying to get the overflowOut to become one when the hrCounter hits 13)
I've spent hours on this, taking break to relax my eyes etc. I still can't see where I am going wrong. Any help would be appreciated
you have a few issues. The main one is that you have a multiple-driven register in both cases:
always#(negedge reset or posedge hourInc) begin
overflowOut = 1'b0;
...
always#(negedge hrCounter) begin
if (hrCounter == 4'b1100) begin
overflowOut = 1'b1;
the overflowOut is driven from 2 different alsways blocks. Same as minOut in the second counter. The order in which those statements are executed is undefined and the resulting value would depend on the order.
You need to restructure your program in such a way that the registers are assigned in a single always block only.
Secondly, i think, that you have a logic bug, assigning your overflow to '0' in the first statement of the first block (same as in the second one).
Thirdly, you should have uset non-blocking assighments '<=' in finlal assignments to the registers.
something like the following should work.
always#(negedge reset or posedge hourInc) begin
if(reset == 1'b0) begin
hrCounter <= 4'b0;
overflowOut <= 1'b0;
end
else begin
if (hrCounter == 4'b1100) begin
overflowOut <= 1'b1;
hrCounter <= 4'b0;
end
else
hrCounter <= hrCounter + 1'b1;
overflowOut <= 1'b0;
end
end
end
Your code is wrong in so many ways...
Most likely it does not work because of:
#(negedge hrCounter)
You are using a vector but #... works with bits. So it will look at the LS bit only.
As to your code:first and most start using a clock. Do not use posedge and negedge of your signals to drive the other signals.
You use:
always#(posedge secInc ...
...
if (secInc == 1'b1)
Remove the 'if'. you have that condition already in your always statement. (But the signal should not be the 'always' anyway, it should be your clock)
Remove the 'initial' sections You have a reset which defines the start condition.
If you have an active low reset reflect that in the name. Call it reset_n or n_reset anything but 'reset' which is per convention a positive reset signal.
If your drive ANYTHING from an edge, be it from a clock or from other signals, use non-blocking assignments "<="
Do not use your generated signal edges to generate other signals. As mentioned use a clock for everything an in the clocking section use an if. Also do not drive signals from different 'always'. You can never know in which order they are executed and then you have a race condition. Thus the clear and the increment are all in one always block:
if (secCounter == 6'b111100) begin
minOut <= 1'b1;
secCounter <= 6'b0;
end
else
secCounter <= secCounter + 6'b000001;
Because of the timing aspect you now have to go to 59 not 60. Which is as you should expect as digital clocks and watches run from 00 to 59, not 00 to 60. You are allowed to use decimal numbers which will, again, make the code more readable: 6'd59, 4'd11

Keeping count of button clicks in verilog

I am creating a vending machine in verilog. There is one button on the FPGA board to act as the coin inserter, every time the button is pushed it will add a 'quarter' to the total amount the user can spend, and display the total on the left and right seven segment displays.
Ex.
1st button push : 25 cents
2nd button push : 50 cents
3rd button push : 75 cents
4th button push : $1.00 (10 on the seven segment display).
Wont increment after the 4th button press.
input quarterIn,
output reg [4:0] state,
output reg [4:0] next_state,
output reg totalChange,
output reg [7:0] RSSD,
output reg [7:0] LSSD
);
/***coin implementation***/
parameter
c0 = 0,
c1 = 1,
c2 = 2,
c3 = 3,
c4 = 4;
always #(posedge clock)
begin
state = next_state;
end
always # (quarterIn or totalChange)
begin
case(totalChange)
0: begin if(quarterIn == 1) totalChange = 1; state = c1; end
1: begin if(quarterIn == 1) totalChange = 2; state = c2; end
2: begin if(quarterIn == 1) totalChange = 3; state = c3; end
3: begin if(quarterIn == 1) totalChange = 4; state = c4; end
4: begin if(quarterIn == 1) totalChange = 4; state = c4; end
endcase
end
I am getting stuck on how to keep count of the button clicks. I can see the first value on the seven segment display, but am unsure as to how to increment the total coins. I couldn't find any sort of information on this from trying to research on my own.
From what I understood, you need a saturating counter to keep track of the button presses.
In order to count, you need a clock in the system:
input clock;
And you'll need a reset signal to initialize the counter to a known value, zero in this case:
input reset;
And the counter (equivalent to the state variable, let me just call it num_push):
reg [2:0] num_push;
The saturating counter can be specified this way:
always #(posedge clock) begin
if (reset) begin // Active high, synchronous reset
num_push <= 3'b0;
end else begin
if (quarterIn == 1'b1 && num_push != 3'b100) begin
num_push <= num_push + 3'b1;
end
end
end
This will synthesize to a counter with a count-enable on your FPGA and the enable will be equal to quarterIn == 1'b1 && num_push != 3'b100. You could press reset to start over.
Now, there are a few issues to be addressed before we put this on an FPGA. First of all, quarterIn needs to be synced for metastability:
reg quarterIn_f;
reg quarterIn_sync;
always #(posedge clock) begin
quarterIn_f <= quarterIn;
quarterIn_sync <= quarterIn_f;
end
We should use only quarterIn_sync in the design and never quarterIn directly. You should do the same with for the reset signal as well.
Second, the signals that come from the keys need to be debounced. Debouncing is a whole topic in itself, so I'll skip it for the time being :(
Another thing is that the clock needs to be pulled from the onboard clock generator circuitry and this clock will be running at a few MHz. A typical button-press lasts for about 500ms and this means our counter will sample a few hundred thousand keypresses in a single press. To avoid this, we should count the edge of quarterIn_sync, and not the level:
wire quarterIn_edge;
req quarterIn_sync_f;
always #(posedge clock) begin
if (reset) begin
quarterIn_sync_f <= 1'b0;
end else begin
quarterIn_sync_f <= quarterIn_sync;
end
end
assign quarterIn_edge = quarterIn_sync & ~quarterIn_sync_f; // Detects rising edge
Now, replace the quarterIn in the saturating counter code with quarterIn_edge:
always #(posedge clock) begin
if (reset) begin
num_push <= 3'b0;
end else begin
if (quarterIn_edge == 1'b1 && num_push != 3'b100) begin
num_push <= num_push + 3'b1;
end
end
end
And we're done!

internally generating resets verilog 2005

wanted to implement PWM sequence using top-level verilog 2005 module:
module PWM_ENHANCER (
input clk,
input rst,
input sent,
//input
input [7:0] BUF, //BUFFER - The PWM reads from it only when 'sent' signal is received, and the current run is done.
//output
output reg PWM_WAIT,
output reg PWM_OUT
);
reg [7:0] SAMPLE;
reg [7:0] counter;
reg WORK;
always#(posedge clk or negedge rst)
begin
if( !rst )
begin
WORK <= 1'b0; //When receiving a reset, everything zeroes.
counter <= 8'b0;
PWM_WAIT <= 1'b1;
SAMPLE <= 8'b0;
PWM_OUT <= 1'b0;
end
else if (sent == 1 && WORK == 0)
begin //If the pwm was OFF, and i received sign from the array, i start running PWM.
SAMPLE <= BUF;
WORK <= 1'b1;
PWM_WAIT <= 1'b0;
end
else if(WORK == 1)
begin //The running block - sending '0' and '1' as needed.
if ( (counter <= SAMPLE) && (SAMPLE != 0) )
begin
PWM_OUT <= 1'b1;
counter = counter + 1'b1;
end
else if ( counter > SAMPLE )
begin
if ( counter == 8'b11111111 )
begin
counter <= 8'b0;
WORK <= 1'b0;
end
else
begin
counter = counter + 1'b1;
PWM_OUT <= 1'b0;
end
end;
if(counter == 200)
begin // 50 cycles before the end, PWM sends acknowledge for the array to send the next sample.
PWM_WAIT <= 1'b1;
end
end
else
begin
; // if NOT receiving 'sent' from the array - the PWM does nothing.
end
end
endmodule
received error when compiling:
"Internally generated reset in top design unit 'PWM_ENHANCER' is not allowed."
How can i have a reset included in the #always statement?
Two possibility (both synthesis related):
Your synthesizer needs additional hand-holding for the asynchronous reset
if(!rst) begin
WORK <= 1'b0;
counter <= 8'b0;
PWM_WAIT <= 1'b1;
SAMPLE <= 8'b0;
PWM_OUT <= 1'b0;
end
else begin
// other logic in here
end
Your standard cell library lacks flops with asynchronous reset/preset. FPGA's tend to have a limited number of flops with asynchronous reset/preset. Some FPGA do not have any. If this is the case the simplest thing that can be done is change the for asynchronous reset to synchronous reset by changing the top of your always block to always#(posedge clk) (omitting the or negedge rst).
If you are on FPGA, then you may want to add an initial block to initialize the defaults of the registers.

Triangle waveform verilog

I'm trying to get a triangle waveform, but my code doesn't work! I think the "if conditions" are organised wrong but I can't find the mistake My wave goes up like it should be and it falls down by 90° after achieving the top
module pila(clk,res,out2);
input clk,res;
output [0:7]out2;
reg [0:7]out2;
always #(posedge clk)
begin
if (res)
begin
if(out2<=8'b11111111)
out2=out2+1;
else if(out2>=8'b00000000)
out2=out2-1;
else out2=8'b00000000;
end
else out2=8'b00000000;
end
endmodule
module testbench;
reg clk,res;
wire [0:7]out2;
pila Sevo(clk,res,out2);
always #2 clk=~clk;
initial
begin
clk=0;res=0;
#2 res=1;
end
initial #5000 $finish;
endmodule
You need some signal to indicate which direction you are currently counting. Also use the non-blocking assignment operator <= rather than the blocking assignment operator =.
module pila(clk,res,out2);
input clk,res;
output [0:7]out2;
reg [0:7]out2 = 8'h00;
reg count_down = 1'b0;
always #(posedge clk)
begin
if (count_down == 1'b0)
begin
if (out2==8'b11111111) // check for top of count
begin
count_down <= 1'b1;
out2<=out2-1;
end
else
out2<=out2+1;
end
else
begin
if(out2==8'b00000000) // check for bottom of count
begin
count_down <= 1'b0;
out2<=out2+1;
end
else
out2<=out2-1;
end
end
endmodule
The if(out2<=8'b11111111) condition is always evaluating to true. This is because out2 range is 0 to 255. Try adding another flop to control the direction, for example downup where 1 means decrement and 0 means increment.
if (out2 == 8'h00) begin
downup <= 1'b0; // up
out2 <= 8'h01;
end
else if (out2 == 8'hFF) begin
downup <= 1'b1; // down
out2 <= 8'hFE;
end
else if (downup) begin // down
out2 <= out2 - 1;
end
else begin // up
out2 <= out2 + 1;
end
Other issues:
Use non-blocking assignment (<=) for synchronous logic.
Typically reset (and set) conditions are declared before synchronous logic assignment
Little-Endian ([7:0]) is more commonly used for packed arrays (previously known as vectors) then Big-Endian ([0:7]), http://en.wikipedia.org/wiki/Endianness
Working example: http://www.edaplayground.com/x/4_b

Cannot find why value doesn't jump to expectation in the right time

I have the following code
module POLY(CLK,RESET_n,IN_VALID,IN,OUT_VALID,OUT);
input CLK,RESET_n,IN_VALID;
input [ 3:0] IN;
output OUT_VALID;
output [12:0] OUT;
reg OUT_VALID;
reg [12:0] OUT;
reg OUT_VALID_w;
reg [12:0] OUT_w;
reg [ 1:0] COUNT_IN, COUNT_IN_w;
reg [ 2:0] COUNT_DO, COUNT_DO_w;
always #(posedge CLK or negedge RESET_n)
begin
if(!RESET_n)
begin
COUNT_IN <= 2'd0;
COUNT_DO <= 3'd0;
end
else
begin
COUNT_IN <= COUNT_IN_w;
COUNT_DO <= COUNT_DO_w;
end
end
always #(*)
begin
if(IN_VALID == 1'b0)
begin
if(COUNT_DO == 3'd7)
begin
COUNT_DO_w = COUNT_DO;
end
else
begin
COUNT_DO_w = COUNT_DO + 1'b1;
end
end
else
begin
COUNT_DO_w = 3'd0;
end
end
I want to ask is that why COUNT_DO doesn't jump to 1 in 14ns?
I think that due to the sensitive list in the second always block is COUNT_DO and IN_VALID,
so at start, the reset signal trigger first always block and set the COUNT_DO = 0, which change the COUNT_DO value from high impedence to 0. So, it triggers the second always block COUNT_DO_w = 0 + 1 = 1. And , in the next postive edge clock, which trigger the first always block to do COUNT_DO <= COUNT_DO_w. But it seems to delay one clock to assign it(22ns). I have tried to figure it out but still cannot, why it delay one clock?
Thx in advance.
At time=14ns, reset is asserted (RESET_N=0), which means COUNT_DO=0 in the 1st always block. At time t=20ns, you release reset and COUNT_DO remains at 0. At time=22ns, you have your 1st posedge CLK which assigns COUNT_DO to COUNT_DO_w. The time at which COUNT_DO changes is controlled only by the 1st always block, not the 2nd.

Resources