Verilog design: Where should my counter live? - verilog

I am coding in Verilog a typical count-to-n-then-reset-to-0 counter. My module has the logic to increment and reset the counter.
My issue is that I don't know where the counter itself should be defined.
I could pass the counter (as inout?) to the module. That's ok, but the counter still has to be defined somewhere so it this doesn't do me any good.
Nothing else except this module should touch the counter, so I'd like to have the counter created within this module, and not passed in or out.
Is this reasonably standard, and if so, will someone point to a reference please on how to instantiate the counter?
(I'm on day 2 of Verilog, so be afraid, heh)
EDIT - here's the code. As far as I can tell, it works. I haven't implemented DIR == REVERSE yet.
Couple of interesting gotchas. The (now commented out) STEPPER=0 line was causing an error in a schematic; it thought that STEPPER was tied to ground as well as other logic.
Also, I use = instead of <= in some places involving counter - I was getting timing problems (I suppose.) The procedural assignment removed (hid?) the problem.
module cam(
input [7:0] DIVISOR,
input DIR,
input SPINDLE,
output reg STEPPER
);
parameter FORWARD = 1'b1;
parameter REVERSE = !FORWARD;
reg[7:0] counter = 0;
always #(posedge SPINDLE) begin
// STEPPER = 0;
if (DIR == FORWARD) begin
counter = counter + 1;
if (counter == DIVISOR) counter = 0;
end
else begin
// counter <= counter - 1;
// if (counter == (-1)) counter <= DIVISOR;
end
end
always #(negedge SPINDLE) begin
STEPPER = (counter == 0) ? 1 : 0;
end
endmodule

Should just be defined as a register within the module. Here's an example from some of my code.
module trigger(clk, rxReady, rxData, txBusy, txStart, txData);
input clk;
input [7:0] rxData;
input rxReady;
input txBusy;
output reg txStart;
output reg[7:0] txData;
integer count81; // Number of cells received over serial (start solving after 81)
reg[8:0] data[0:8][0:8];
integer state;
always #(posedge clk) begin
case (state)
read:
if (rxReady) begin
data[count81 % 9][count81 / 9] = rxData ? 1<<(rxData-1) : -1;
if (count81 < 80) count81 <= count81 + 1;
else begin
count81 <= 0;
state <= solving;
end
end
etc....
endcase
end
endmodule
Congrats on getting out of the Java world for the time being. FPGAs are the only thing that seems exciting anymore.

Related

System Verilog Loops

Im currently working on the Shift-Add Algorithm (32x32 bit Multiplication) in System Verilog. System Verilog cant find any error and my code is working correctly according to GTKwave. When I synthesize my circuit with yosys, Latches will be added. And that is the Problem. I dont want Latches in my Circuit. Heres my Code:
module multiplier(
input logic clk_i,
input logic rst_i,
input logic start_i,
input logic [31:0] a_i,
input logic [31:0] b_i,
output logic finished_o,
output logic [63:0] result_o
);
typedef enum logic [1:0] { STATE_A, STATE_B} state_t;
state_t state_p, state_n;
logic [63:0] fin_res;
logic [63:0] tmp;
logic rst_flag;
integer i;
always #(posedge clk_i or posedge rst_i) begin
if (rst_i == 1'b1) begin
state_p <= STATE_B;
end
else begin
state_p <= state_n;
end
end
always #(*)begin
state_n = state_p;
case (state_p)
STATE_A: if (start_i == 0) state_n = STATE_B;
STATE_B: if (start_i == 1) state_n = STATE_A;
default: state_n = state_p;
endcase
end
always #(*) begin
case (state_p)
STATE_A: begin
rst_flag = 1;
fin_res = 0;
finished_o = 0;
tmp = 0;
for (i = 0; i < 32; i = i + 1) begin
if (a_i[i] == 1'b1) begin
tmp = b_i;
tmp = tmp << i;
fin_res = fin_res + tmp;
end
end
end
STATE_B: begin
result_o = fin_res;
if (rst_flag == 1) finished_o = 1;
if (start_i == 1) finished_o = 0;
end
default: begin
finished_o = 0;
result_o = 0;
end
endcase
end
endmodule
After spending 2 days only with debugging and not finding any mistake I would like to ask if u could help me. I am assigning every output (at least I think so). So where is my mistake? Is it the for loop? But what would be wrong with it? Thanks in advance for your help :)
Some useful Information for the Code-Snippet: start_i is the starting signal. If this is set to 1 the multiplication should be started. finished_o is the finish flag. If this is set to 1 the CPU will know that the computation is completed. a_i and b_i are the inputs which should be multiplied. result_o is the result of the multiplication which can be read when finished_o is set to 1.
According to yosys i get the following latches:
64 DLATCH_N
64 DLATCH_P
I think something may be wrong with fin_res in the for loop cause that logic variable is exactly 64 bits long as are the Latches
From the comment you have a bunch of variables which are not assigned in the second case statement causing synthesis to generate latches. To avoid it you need to assign all the vars in all branches of the case statement and conditional statements recursively.
However, if there is a default value you can assign to all of them, you can use a pattern similar to the one from the second always block, just assigning default values before the 'case' statement. This way you do not even need the default clause and you can get rid of it in the second always block as well.
always #(*) begin
// set default values
rst_flag = 0;
fin_res = 0;
finished_o = 0;
tmp = 0;
result_o = 0;
case (state_p)
STATE_A: begin
rst_flag = 1;
for (i = 0; i < 32; i = i + 1) begin
if (a_i[i] == 1'b1) begin
tmp = b_i;
tmp = tmp << i;
fin_res = fin_res + tmp;
end
end
end
STATE_B: begin
result_o = fin_res;
// are you sure that you do not need a latch here?
if (rst_flag == 1) finished_o = 1;
if (start_i == 1) finished_o = 0;
end
// you do not need 'default' here.
endcase
end
My fixes will cause combinational behavior and should get rid of latches in synthesis, but it does not look like they will behave as you expected. It looks like you really need a latches here.
rst_flag must be a latch. You set it in STATE_A and use it in STATE_B. It has to keep the value between states. This is a latch behavior.
In STATE_B you change finished_o only if some of conditions met. What happens if the rst_flag and start_i are both 0. do you want finished_o to be 0 or the previous value? In the latter case you need a latch.
How about fin_res ? What do you want to do with it in other states? keep previous value (latch) or have a default value (no latch).
...

SIPO (Serial Input Parallel Output) FSM synthesis problem

I want to write a Serial to Parallel conversion in Verilog, and I can't realize what is wrong with my code. It doesn't synthesize, and not even the ISE shows what the problem is. Can anyone help me?
I guess the problem is around the second always block. The part:
if (STATE == TRANSMIT)
PAR_OUT[COUNTER] = SER_IN;
seems wrong to me, but I can't understand what to change or test.
module SIPO(
input SER_IN,
input RST,
input CLK,
input LOAD,
output reg READY,
output reg [7:0] PAR_OUT
);
parameter IDLE = 2'b00, START = 2'b01, TRANSMIT = 2'b10, STOP = 2'b11;
reg [1:0] STATE;
reg [2:0] COUNTER;
always # ( posedge CLK or negedge RST)
if (~RST)
begin
STATE <= IDLE;
READY <= 1;
COUNTER <= 0;
end
else
begin
if (STATE == IDLE)
begin
READY <= 1;
COUNTER <= 0;
if (LOAD)
begin
STATE <= START;
end
else
STATE <= IDLE;
end
else
if (STATE == START)
STATE <= TRANSMIT;
else
if (STATE == TRANSMIT)
begin
COUNTER <= COUNTER + 1;
if (COUNTER == 7)
STATE <= STOP;
end
else
begin
STATE <= IDLE;
READY <= 1;
end
end
always #( * )
begin
if (STATE == IDLE)
PAR_OUT = 1;
else
if (STATE == START)
PAR_OUT = 0;
else
if (STATE == TRANSMIT)
PAR_OUT[COUNTER] = SER_IN;
else
PAR_OUT = 1;
end
endmodule
I think your suspicion might be correct regarding PAR_OUT[COUNTER]. When I synthesize your code on edaplayground with Yosys, it infers latches for PAR_OUT, which you likely do not want.
PAR_OUT is 8 bits wide, but you only assign 1 of the 8 bits at a time in the TRANSMIT state, which means the other 7 bits retain their state. For example, if COUNTER=3, then only PAR_OUT[3] is assigned.
I recoded your combo logic, simplifying it with a case statement to make the issue more evident (it should be functionally equivalent to your if/else code):
always #* begin
case (STATE)
TRANSMIT: PAR_OUT[COUNTER] = SER_IN; // Assign to only 1 bit <---
START : PAR_OUT = 8'h00; // Assign to all 8 bits
default : PAR_OUT = 8'h01; // Assign to all 8 bits
endcase
end
If you can afford one cycle of latency, you could use sequential logic for PAR_OUT, such as a shift register.

Verilog Multiple Counters

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

registering and resetting the convolution output in verilog

so I have a module that does convolution, it takes a data input and the filter input , where input is array of 9 numbers , every posedge of the clk these two inputs are being multiplied and then added accumulatively, i.e I save every new multiplication product into a register. after each 9 iterations I have to save the result and reset it , but I have to do it in one clock cycle, since my new data is coming on the next posedge. So the issue that I am facing is how to not save data and reset the out without losing data? Please help if you have any suggestions. It also need to be mentioned that my conv_module is a sub-module and I will be instantiating it in a top module , so I have to access all the inputs and outputs from uptop.
This is the code that I've written so far, but it does not work the way I want it, cause I cannot tap the array of output numbers from the top module.
module mult_conv( input clk,
input rst,
input signed [4:0] a,
input signed[2:0] b,
output reg signed[7:0] out
);
wire signed [7:0] mult;
reg signed [7:0] sum;
reg [3:0] counter;
reg do_write;
reg [7:0] out_top;
assign mult = {{3{a[4]}},a} * {{5{b[2]}},b};
always #(posedge clk or posedge rst)
begin
if (rst)
begin
counter <= 4'h0;
addr <= 'h0;
sum <= 0;
do_write <= 1'b0;
end // rst
else
begin
if (counter == 4'h8)
begin // we have gathered 9 samples
counter <= 4'h0;
// start again so ignore old sum
sum <= mult;
out <= sum;
out_top <= out;
end
else
begin
counter <= counter + 4'h1;
// Add results
sum <= sum + mult;
out <= 0;
out_top <= out_top;
end
// Write signal has to be set one cycle early
do_write = (counter==4'h7);
end // clocked
end // always
endmodule
You have a plethora of errors in that code.
Apart from that you have a 3Mega bit memory from which you use only 1 in 9 locations.
You write out in two places. That does not work.
You use a %9. That can not be mapped onto hardware.
You have a sel signal which somehow controls your sum.
On top of that I understand you want to bring the whole memory out.
Your code because it needs to be drastically re-written.
But your biggest problem is that you definitely can't make the memory come out. What ever post-processing you want to do you have two choices:
Process the output data as it appears.
Store the data outside the module in a memory and have another process read that memory.
I think only (1) is the correct way because your signal can have infinite length.
As to fixing this code a bit:
Replace the %9 with a counter to count from 0 to 8.
Process out in in clocked section. See below
Move the addr and sel generating logic in here. Keep it all together.
Below is the basic code of how to do a 9-sequence convolution. I have to ignore 'sel' as I have no idea of the timing. I have also added address generation and a write signal so the result can be store in an external memory. But I still think you should process the result on the fly.
always #(posedge clk or posedge rts)
begin
if (rst)
begin
counter <= 4'h0;
addr <= 'h0;
sum <= 0;
do_write <= 1'b0;
end // rst
else
begin
if (counter == 4'h8)
begin // we have gathered 9 samples
counter <= 4'h0;
addr <= addr + 1;
// start again so ignore old sum
sum <= mult;
end
else
begin
counter <= counter + 4'h1;
// Add results
sum <= sum + mult;
end
// Write signal has to be set one cycle early
do_write = (counter==4'h7);
end // clocked
end // always
(Code above was entered on-the fly, may contain syntax, typing or other errors!!)
As you can see the trick is to know when to add the old result or when to ignore the old sum and start again.
(I spend about 3/4 of an hour on that so on my normal tariff you would have to pay me $93.75 :-)
I provided the basic code to let you work out the specifics. I did nothing with out but left that to you.
do_write and addr where for a possible memory to pick up the result. Without memory you can drop addr but do_write should tell you when a new convolution result is available, in which case you might want to give a it a different name. e.g. 'sum_valid'.

Keybord interface design in Verilog

I am new to Verilog and I am trying to create one of my first programs which should display something when key on keybord is pressed. I'd like to use example code from Verilog coursebook, but I have some problems with pin assingment (I use DE2-70 from Altera).
Why I have input ReadKB; while there is nothing like this in module definition?
I know which pins should be assign to KBclk and KBdata. (PS2_KBCLK PIN_F24 PS/2 Clock and (PS2_KBDAT PIN_E24 PS/2 Data) What about ResetKB?
In the coursebook there is no explanation and I am really courious about it.
Code:
module KeyboardInterface(KBclk, KBdata, ResetKB, SYNclk, ScanRdy, ScanCode, KeyReleased);
input KBclk;
input KBdata;
input ResetKB;
input ReadKB;
input SYNclk;
output ScanRdy;
output ScanCode;
output KeyReleased;
//Generate an internal synchronized clock
reg Clock;
always #(posedge SYNclk) Clock = KBclk;
reg[3:0] BitCount;
reg StartBitDetected, ScanRdy;
reg[7:0] ScanCode;
//Count the number of serial bits and collect data into ScanCode
always #(posedge Clock) begin
if(ResetKB) begin
BitCount=0; StartBitDetected =0;
end else begin
if(KBdata == 0 && StartBitDetected == 0) begin
StartBitDetected=1;
ScanRdy = 0;
end else if (StartBitDetected) begin
if(BitCount < 8) begin
BitCount = BitCount + 1;
ScanCode = {KBdata, ScanCode[7:1]};
end else begin
StartBitDetected = 0;
BitCount = 0;
ScanRdy = 1;
end
end
end
end
reg [1:0] CompletionState;
wire KeyReleased;
//keep track of the state of Scan Codes outputted
always #(posedge SYNclk) begin
if(ResetKB) CompletionState = 0;
else case(CompletionState)
0: if(ScanCode == 8'h70 && ScanRdy == 1) CompletionState =1;
else CompletionState =0;
1: if(ScanRdy == 1) CompletionState =1;
else CompletionState =2;
2: if(ScanRdy == 0) CompletionState = 2;
else CompletionState = 0;
3: CompletionState = 0;
endcase
end
assign KeyReleased = CompletionState == 3 ? 1 : 0;
endmodule
Thank you!
That looks like a typo, just go ahead and add the missing wire to the module definition.
There's probably not actually a 'reset' coming from your keyboard if that's what you're asking. I'd just tie it to some pushbutton on the Altera if it is available.
It is just a high-level reset signal. You can just connect it with a push button, then you can use the push button to reset the reg signals, bitcount and startbitdetect.
But one crucial thing you should note is that reg signals can not use "=" inside the always section, it should be "<=". This is the difference between blocking and non-blocking assignment that you should pay more attentions on. Good luck.:-)

Resources