Verilog Multiple Counters - verilog

I have a Verilog module with the fowling input and outputs
module Foo
#(
parameter DATA_BITS = 32,
parameter ENUM_BITS = 8,
parameter LED_BITS = 8
)
(
//Module IO declarations
input logic Clk_i,
input logic Reset_i,
input logic NoGoodError_i,
input logic EncoderSignal_i,
input logic [DATA_BITS-1:0]DistanceCount_i,
//Enable the gate
output logic GateEnable_o
)
The overall design idea is the following. When I receive the positive edge of the NoGoodError_i start a counter and count up to the DistanceCount_i count via the positive edges of the EncoderSignal_i signal. That seems pretty straight forward, however my design challenge becomes that I could get another NoGoodError_i before I am finished counting the previous count. So, I need a way to get up to 10 NoGoodError_i signal in row and start counters. Then reuse the counters once they expire (Rollover). Please any design tips would be greatly appreciated.

I would take an array of counters each with a 'busy' bit. If the bit is set the counter is running.
Next you use a modulo-10 index which busy bit to set.
I would raise a flag if the counter you want to start is still busy.
I just typed this in on the fly: not parsed for syntax and typos are possible (even likely):
reg [DATA_BITS-1:0] counter [0:9];
reg [9:0] busy;
reg [3:0] cntr_to_start;
always #(posedge Clk_i or posedge Reset_i)
begin
if (Reset_i)
begin
busy <= 10'b0;
for (i=0; i=<10; i=i+1)
counter[i] <= 'b0;
cntr_to_start <= 'b0;
end
begin
// Run a counter if it's busy flag is set
// At max (rollover) stop and clear the busy flag
for (i=0; i<10; i=i+1)
begin
if (busy[i])
begin
if (counter[i]==(33'b1<<DATA_BITS)-1)
begin
counter[i] <= 1'b0;
busy[i] <= 1'b0;
end
else
counter[i] <= counter[i] + 1;
end
end
// If no good start the next counter
// If we have no next counter: ????
if (NoGoodError_i)
begin
if (busy[cntr_to_start])
// Houston: we have a problem!
// More errors then we have counters
else
begin
busy[cntr_to_start] <= 1'b1;
if (cntr_to_start==9)
cntr_to_start <= 'b0;
else
cntr_to_start <= cntr_to_start + 1;
end
end
end

Related

Verilog FSM being optimised away

New to Verilog, Basys3 board and Vivid 2021.2.
Trying to implement a typical stopwatch with Stop/Start and Lap/Reset buttons.
A divider produces 1kHz and 100Hz clock from the board clock, 100Hz is for button debounce (and seven segment display multiplexing, next todo), the 1kHz drives a 20 bit 5 x 4 bit BCD counter, the low 16 bits of which drive a latch to freeze the display, the latch drives the 16 on board LEDs.
I've test 'wired' this up and the modules perform as expected. It's only when I add the FSM I run into trouble.
The FSM is simple, the two buttons determine the state changes and the state sets three outputs to control the counter.
The state module as been through many versions, tried using buttons in the sensitivity list, tried with button edges and levels, tried *, tried blocking and non-blocking assignments, can't get it right. The current error is:
[Synth 8-3332] Sequential element (state/transfer_reg) is unused and will be removed from module stopwatch.
The error changes but it's always Synth 8-3332 removing something, even curr_state or next_state.
The RTL synthesis schematic shows exactly what I expect, later schematics show the two buttons, 16 LEDs and nothing in between.
I'm lost at this stage, have I missed something fundamental?
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
//
// Create Date: 02/02/2022 0800
//
// Module Name: state
// Project Name: Stop Watch
// Target Devices: BASYS 3
//
// state machine
//
// inputs:
// start-stop button via debounce (both edg and level are available)
// lap-reset buttonvia debounce (both edg and level are available)
//
// outputs:
// control 4 x 4 bit BCD counters and output latch
// clear state
// enabvble couter to count
//. transfer counter value to latch
//
////////////////////////////////////////////////////////////////////////////////
module state (
input clk,
input lap_reset,
input start_stop,
output reg clear,
output reg enable,
output reg transfer
);
// state encodings
localparam
RESET_0 = 3'd0,
STOPPED_1 = 3'd1,
RUNNING_2 = 3'd2,
PRELAP_3 = 3'd3,
LAP_4 = 3'd4;
// state reg
reg[2:0] curr_state;
reg[2:0] next_state;
// setup
initial
begin
curr_state <= RESET_0;
next_state <= RESET_0;
enable <= 0;
clear <= 0;
transfer <= 0;
end
// sync state transitons to clk
// always # (posedge clk)
// begin
// curr_state <= next_state;
// end
// state machine
always # (posedge clk)
begin
curr_state <= next_state;
case (curr_state)
RESET_0:
begin
// init, stop counter, clear counter
// transfer count to latch
enable <= 0;
clear <= 1;
transfer <= 1;
next_state <= STOPPED_1;
end
STOPPED_1:
begin
// stop counter, clear counter
enable <= 0;
clear <= 0;
transfer <= 0;
if (start_stop)
next_state <= STOPPED_1;
else if (lap_reset)
next_state <= RESET_0;
else
next_state <= curr_state;
end
RUNNING_2:
begin
// start or continue counting
// transfer count to latch
enable <= 1;
clear <= 0;
transfer <= 1;
if (start_stop)
next_state <= STOPPED_1;
else if (lap_reset)
next_state <= PRELAP_3;
else
next_state <= curr_state;
end
PRELAP_3:
begin
// start or continue counting
// don't update latch
enable <= 1;
clear <= 0;
transfer <= 0;
next_state <= LAP_4;
end
LAP_4:
begin
// continue counting
// transfer counter to latch
enable <= 1;
clear <= 0;
transfer <= 1;
if (start_stop)
next_state <= RUNNING_2;
else if (lap_reset)
next_state <= PRELAP_3;
else
next_state <= curr_state;
end
default:
begin
enable <= 0;
clear <= 0;
transfer <= 0;
next_state <= RESET_0;
end
endcase
end
endmodule
Getting somewhere at last, thankyou all.
After correcting a logical error and a couple of constants 0'b0 which make little sense (the compiler didn't complain about them) and doing suggested fixes my stopwatch works.
The SM structure is the 3 blocks, sync transitions, next state 'gotos' and state actions. I started with the suggested always # (*) but had to change to a posedge clk for it to work, not sure why.
Got rid of the inferred latches and now understand why they come about.
About generating a reset signal, I assume the Artix chip has one but it doesn't get a mention in the supplied xdc file, I was trying to simulate a reset held low (active) then going high a short time later, determined by a clock divider - which should have a reset... Also read Xilinx WP272 which tells a different story.
Thanks again.
Just from www.javatpoint.com/verilog-initial-block:
"An initial block is not synthesizable and cannot be converted into a
hardware schematic with digital elements. The initial blocks do not
have more purpose than to be used in simulations. These blocks are
primarily used to initialize variables and drive design ports with
specific values."
I am not sure now about the code for that FPGA, but in common ASICs I would remove the "initial" code section, which you use to implement the reset behaviour and add an actual reset section in the always#.
always#(posedge clk)
begin
if (rst) begin
// do the reset
curr_state <= RESET_0;
next_state <= RESET_0;
enable <= 0;
clear <= 0;
transfer <= 0;
end else begin
// the rest
end
end
EDITED:
Never leave a signal without a default value, as it will infer latches instead of flip-flops, which create problems when inferring sequential logic (of course latches are useful in some scenarios).
When one wants to build a finite state machine (FSM) there are two common approaches: Mealy and Moore. I will explain how the sequential logic should be implemented with a Moore FSM:
A synchronous always# block to write the state: cur_state <= next state.
A combinational block to generate next_state value based on cur_state and inputs.
A combinational block to generate outputs based on the state.
always#(posedge clk, rst)
begin
if (rst = '1') begin
cur_state <= State_0;
end else begin
cur_state <= next_state;
end
end
always_comb(cur_state, my_inputA)
begin
if (cur_state = State_0) begin
if(my_inputA)
next_state = State_1;
else
next_state = Stage_0;
end else if (cur_state = State_1) begin
next_state = State_2;
end
end
always_comb(cur_state)
begin
if (cur_state = State_0) begin
my_outputA = '1';
end else if (cur_state = State_1) begin
my_outputA = '0';
end else if (cur_state = State_2) begin
my_outputA = '1';
end
end

Find Maximum Number present in Verilog array

I have tried writing a small verilog module that will find the maximum of 10 numbers in an array. At the moment I am just trying to verify the correctness of the module without going into specific RTL methods that will to do such a task.
I am just seeing a a couple of registers when I am synthesizing this module. Nothing more that that. Ideally the output should be 7 which is at index 4 but I am seeing nothing neither on FPGA board or in the test bench. What I am doing wrong with this ?
module findmaximum(input clk,rst,output reg[3:0]max, output reg[3:0]index);
reg [3:0]corr_Output[0:9];
always#(posedge clk or posedge rst)
if(rst)
begin
corr_Output[0]=0;
corr_Output[1]=0;
corr_Output[2]=0;
corr_Output[3]=0;
corr_Output[4]=0;
corr_Output[5]=0;
corr_Output[6]=0;
corr_Output[7]=0;
corr_Output[8]=0;
corr_Output[9]=0;
end
else
begin
corr_Output[0]=0;
corr_Output[1]=0;
corr_Output[2]=0;
corr_Output[3]=0;
corr_Output[4]=7;
corr_Output[5]=0;
corr_Output[6]=0;
corr_Output[7]=0;
corr_Output[8]=0;
corr_Output[9]=0;
end
integer i;
always#(posedge clk or posedge rst)
if(rst)
begin
max=0;
index=0;
end
else
begin
max = corr_Output[0];
for (i = 0; i <= 9; i=i+1)
begin
if (corr_Output[i] > max)
begin
max = corr_Output[i];
index = i;
end
end
end
endmodule
Looking are your code, the only possible outputs are max=0,index=0 and a clock or two after reset max=7,index=4. Therefore, your synthesizer is likely optimizing the code with equivalent behavior with simpler logic.
For your find max logic to be meaningful, you need to change the values of corr_Output periodically. This can be done via input writes, LFSR (aka pseudo random number generator), and or other logic.
Other issues:
Synchronous logic (updated on a clock edge) should be assigned by with non-blocking (<=). Combinational logic should be assigned with blocking (=). When this guideline is not followed there is a risk of behavior differences between simulation and synthesis. In the event you need to compare with intermediate values (like your original max and index), then you need to separate the logic into two always blocks like bellow. See code bellow.
Also, FPGAs tend to have limited asynchronous reset support. Use synchronous reset instead by removing the reset from the sensitivity list.
always#(posedge clk) begin
if (rst) begin
max <= 4'h0;
index <= 4'h0;
end
else begin
max <= next_max;
index <= next_index;
end
always #* begin
next_max = corr_Output[0];
next_index = 4'h0;
for (i = 1; i <= 9; i=i+1) begin // <-- start at 1, not 0 (0 is same a default)
if (corr_Output[i] > next_max) begin
next_max = corr_Output[i];
next_index = i;
end
end
end

"ERROR: multiple drivers on net" when setting a register on both positive and negative edges

I was following a tutorial on SPI master in Verilog. I've been debugging this for about three hours now and cannot get it to work.
I've been able to break down the issue into a minimum representative issue. Here are the specifications:
We have two states, IDLE and COUNTING. Then, on the clock positive edge, we check:
If the state is IDLE, then the counter register is set to 0. If while in this state the dataReady pin is high, then the state is set to COUNTING and the counter is set to all 1s.
If the state is COUNTING, the state remains COUNTING as long as counter is not zero. Otherwise, the state is returned to IDLE.
Then, we count on the negative edge:
On the negative edge of clock if state is COUNTING, then decrement counter.
Here's the code I came up with to fit this specification:
// look in pins.pcf for all the pin names on the TinyFPGA BX board
module top (
input CLK, // 16MHz clock
input PIN_14,
output LED, // User/boot LED next to power LED
output USBPU // USB pull-up resistor
);
// drive USB pull-up resistor to '0' to disable USB
assign USBPU = 0;
reg [23:0] clockDivider;
wire clock;
always #(posedge CLK)
clockDivider <= clockDivider + 1;
assign clock = clockDivider[23];
wire dataReady;
assign dataReady = PIN_14;
parameter IDLE = 0, COUNTING = 1;
reg state = IDLE;
reg [3:0] counter;
always #(posedge clock) begin
case (state)
IDLE: begin
if (dataReady)
state <= COUNTING;
end
COUNTING: begin
if (counter == 0)
state <= IDLE;
end
endcase
end
always #(negedge clock) begin
if (state == COUNTING)
counter <= counter - 1;
end
always #(state) begin
case (state)
IDLE:
counter <= 0;
COUNTING:
counter <= counter;
endcase
end
assign LED = counter != 0;
endmodule
With this, we get the error:
ERROR: multiple drivers on net 'LED' (LED_SB_DFFNE_Q.Q and LED_SB_DFFNE_Q_1.Q)
Why? There is literally only one assign statement on the LED.
First of all it would not be easy to come up with a synthesizable model in such a case. But, you do not need any negedge logic to implement your model. Also you made several mistakes and violated many commonly accepted practices.
Now about some problems in your code.
By using non-blocking assignment in the clock line you created race condition in the simulation which will probably cause incorrect simulation results:
always #(posedge CLK)
clockDivider <= clockDivider + 1; // <<< this is a red flag!
assign clock = clockDivider[23];
...
always #(posedge clk)
you incorrectly used nbas in your always block
always(#state)
... counter <= conunter-1; // <<< this is a red flag again!
your state machine has no reset. Statements like reg state = IDLE; will only work in simulation and in some fpgas. It is not synthesizable in general. I suggest that you do not use it but provide a reset signal instead.
Saying that, i am not aware of any methodology which would use positive and negative edges in such a case. So, you should not. All your implementation can be done under the posedge, something like the following. However
always #(posedge clock) begin
if (reset) begin // i suggest that you use reset in some form.
state <= IDLE;
counter <= 0;
end
else begin
case (state)
IDLE: begin
if (dataReady) begin
state <= COUNTING;
counter <= counter - 1;
end
end
COUNTING: begin
if (counter == 0)
state <= IDLE;
else
counter <= counter - 1;
end
endcase
end
end
I hope i did it right, did not test.
Now you do not need the other two always blocks at all.

verilog sync issue with counter

i'm trying to create a 8 bit parallel to serial component that send the data and bit number.
the bit number and the transmitted serial data is not sent at the right time,
please see wave form
module counter
(
input clk,rst,
input [7:0]data,
output reg [7:0]cnt,
output reg data_Tx
);
parameter lim = 7;
always #(posedge clk or negedge rst)
if (!rst)
begin
cnt <= 0;
data_Tx <= 1'b1;
end
else
begin
if (clk)
begin
if (cnt < lim)
begin
data_Tx <= data[cnt];
cnt <= cnt +1;
end
else
cnt <= 0;
end
end
endmodule
please see wave form here
i have marked on the waveform (in blue) the bit numbers that supposed to be transmitted, as you can see they are shifted.
also, in red circle, the data_Tx needs to be '0' when transmitting the first bit from the parallel inputs, but i'ts '1'because of the rst line, how can i fix this situation?
should i use a state machine???
thank you
You have fallen into the standard trap all beginners with HDL have: your signals change after the clock edge. Take a few months of coding and dealing with this becomes second nature.
But before I deal with that: follow Greg's advice and remove the if (clk) from the code.
The first, simple solution, is to move the data_Tx <= data[cnt]; outside the clocked section:
assign data_Tx = data[cnt];
But beware that makes that after a reset (when cnt is zero) the data_Tx bit reflects your data[0] bit. So there is no guarantee that it is 1. Also it will change as soon as a new value is assigned to data.
If you want a synchronous data_Tx output and want the cnt to be inline you have to delay your cnt by a clock cycle:
....
reg [2:0] early_cnt;
always #(posedge clk or negedge rst)
if (!rst)
begin
cnt <= 0;
early_cnt <= 8'h00;
data_Tx <= 1'b1;
end
else
begin
cnt <= early_cnt;
if (early_cnt < lim)
begin
data_Tx <= data[early_cnt];
early_cnt <= early_cnt + 8'h01;
end
else
early_cnt <= 0;
end

Verilog Synchronous 4 bit Counter stay on max value until given signal

So I have my counter in verilog which is 4 bits and I want it to stay on max value, 1111, until I give it a signal to start counting from 0000 again.
Here's what I've been able to come up with so far:
module contadorAscMax
(
input iClk,
input iRst,
output oQ,
input iCE,
input iSignal,
output [3:0] orCnt
);
reg[3:0] rvCnt_d;
reg[3:0] rvCnt_q;
assign orCnt = rvCnt_q;
always #(posedge iClk or posedge iRst)
begin
if(iRst)
begin
rvCnt_q<=4'b0;
end
else
begin
if(iCE)
begin
rvCnt_q<=rvCnt_d;
end
else
begin
rvCnt_q<=rvCnt_q;
end
end
end
always #*
begin
rvCnt_d=rvCnt_q+4'b1;
if(rvCnt_d == 4'b1111)
begin
rvCnt_d = rvCnt_d;
end
else if(rvCnt_d == 4'b1111 & iSignal)
begin
rvCnt_d = 4'b0;
end
end
endmodule
But it just won't wait for the signal. I am very new to verilog so my code probable doesn't make much sense to a hardware guy, since I am a software engineer so sorry if there are some rookie mistakes here.
As for the testbench, here is what I have:
`timescale 1ns / 1ps
module vtfContMax;
// Inputs
reg iClk;
reg iRst;
reg iCE;
reg iSignal;
// Outputs
wire oQ;
wire [3:0] orCnt;
// Instantiate the Unit Under Test (UUT)
contadorAscMax uut (
.iClk(iClk),
.iRst(iRst),
.oQ(oQ),
.iCE(iCE),
.iSignal(iSignal),
.orCnt(orCnt)
);
initial begin
// Initialize Inputs
iClk = 1;
iRst = 1;
iCE = 1;
iSignal = 0;
// Wait 100 ns for global reset to finish
#10;
iRst = 0;
repeat(10)
begin
repeat(10)
begin
wait(iClk);
wait(!iClk);
end
end
$stop();
// Add stimulus here
end
always
begin
#5;
iClk = ~iClk;
#10
iSignal = ~iSignal;
end
endmodule
Thanks for any help :)
You have split the code in a register and combinatorial section. Although that is a good idea for complex logic, for a simple 4 bit counter it is a bit over the top.
For solving your problem you are close. The trick with code like this, is to make the definition using 'programming' language. Then the code flows from that.
I want to have a counter which goes from 1111 to 0000 when a signal is present, else I want it to count up.
This then leads to:
always #(clk or posedge reset)
begin
if (reset)
count <= 4'b1111;
else
begin
if (count==4'b1111 && start_signal)
count <= 4'b0000;
else
count <= count + 4'b0001
end
end
What you don't mention, but what I see from your code you also have an enable (iCE) and an unused output oQ. The total then becomes:
module contadorAscMax
(
input iClk,
input iRst,
// output oQ,
input iCE,
input iSignal,
output reg [3:0] orCnt
);
always #(iClk or posedge iRst)
begin
if (iRst)
orCnt <= 4'b0000; // or should that be 4'b1111
// Is this really what you want?
// It will start counting after a reset!
else
begin
if (iCE)
begin
if (orCnt==4'b1111 && iSignal)
orCnt <= 4'b0000;
else
orCnt <= orCnt+ 4'b0001;
end
end
end
endmodule
Some more remarks:
Your reset condition looks flawed to me but you have to solve that.
Give the counter enable signal a decent name: 'count_enable' not 'signal'.
Last: I would not use all the 'i's and 'o's. The 'o' signals from one module will be the 'i' of another. Thus you have to change the signal names somewhere. It is better to have a defined signal in your system. If only so you can find in the timing report or gates after synthesis.

Resources