Reset If-Else statement produces improper results - if-statement

I've been trying to debug this code, but I cannot find an error in it. However, it's not producing the results that I expect. Here's the code:
module countAdd( btn, reset, thousands, hundreds, tens, ones, led);
//Port Assignments
input [2:0] btn;
input reset;
output [0:7] thousands, hundreds, tens, ones;
output reg led;
//Internal Port Assignments
reg [15:0] sum;
wire [15:0] sumBCD;
reg [15:0] inc;
//Add some stuff
always #(btn or reset)
begin
//Determine which button is active
case(btn)
3'b110: inc <= 1;
3'b101: inc <= 10;
3'b011: inc <= 100;
default: inc <= 0;
endcase
//Add
sum <= sum + inc;
//Should we reset?
if(reset)
begin
sum <= 0;
led <= 1;
end
else
begin
led <= 0;
end
end
//translate sum to sumBCD
binToBCD translate (sum, sumBCD[15:12], sumBCD[11:8], sumBCD[7:4], sumBCD[3:0]);
//display results on SS display
ssFromBCD seg0 (sumBCD[3:0], ones);
ssFromBCD seg1 (sumBCD[7:4], tens);
ssFromBCD seg2 (sumBCD[11:8], hundreds);
ssFromBCD seg3 (sumBCD[15:12], thousands);
endmodule
module binToBCD(sum, thousands, hundreds, tens, ones);
//Port Assignments
input [15:0] sum;
output reg [3:0] thousands;
output reg [3:0] hundreds;
output reg [3:0] tens;
output reg [3:0] ones;
//Begin conversion
integer i;
always #(sum)
begin
//set 1000's, 100's, 10's, and 1's to 0
thousands = 4'd0;
hundreds = 4'd0;
tens = 4'd0;
ones = 4'd0;
for(i = 15; i >= 0; i=i-1)
begin
//Add 3 to columns >= 5
if(thousands >= 5)
thousands = thousands + 3;
if(hundreds >= 5)
hundreds = hundreds + 3;
if(tens >= 5)
tens = tens + 3;
if(ones >= 5)
ones = ones + 3;
//Shift left ones
thousands = thousands << 1;
thousands[0] = hundreds[3];
hundreds = hundreds << 1;
hundreds[0] = tens[3];
tens = tens << 1;
tens[0] = ones[3];
ones = ones << 1;
ones[0] = sum[i];
end
end
endmodule
module ssFromBCD(in, ssOut);
//Port Assignments
input [3:0] in;
output reg [0:7] ssOut;
always #(in)
begin
case(in)
4'b0000: ssOut = 8'b00000011;
4'b0001: ssOut = 8'b10011111;
4'b0010: ssOut = 8'b00100101;
4'b0011: ssOut = 8'b00001101;
4'b0100: ssOut = 8'b10011001;
4'b0101: ssOut = 8'b01001001;
4'b0110: ssOut = 8'b01000001;
4'b0111: ssOut = 8'b00011111;
4'b1000: ssOut = 8'b00000001;
4'b1001: ssOut = 8'b00011001;
default: ssOut = 8'b11111111;
endcase
end
endmodule
This code does not have a testbench; it's instead loaded onto a DE0 board. The idea is that when I press button 1, the sum is supposed to increment by 1. Button 2 increments it by 10, and button 3 increments it by 100. However, the if-else module that encapsulates reset seems to be causing some serious issues.
For instance, when I activate the switch controlling reset, the sum goes to 0 as expected. However, when I try to increment the sum with any of the three buttons, a random number is added - not a 1, 10, or 100.
I've also tried moving the if-else statement before the case statement. Another issue arises. Even if the switch is not activated, the sum is set to 0 as if it ignores the reset condition. However, if I activate the switch, an led turns on. If I turn it off, the led deactivates. However, sum will always be set to 0 regardless of the state of the switch. In this case, though, if I hold a button I see that a 1, 10, or 100 is added to the sum. As soon as I release it, the sum is reset to 0.
Obviously, I believe something is wrong with my if-else statement. I'm not sure why it's not working as I intended. Basically, the logic is as follows:
Determine which button is depressed, assign an increment accordingly
Add the increment value to sum
Should the sum be reset? If yes, set sum to 0.
Note that the last two modules are straightforward. bintoBCD converts the binary string sum into its BCD equivalency. Then ssFromBCD is simply a seven segment display encoder.

This code does not have a testbench
Firstly: Create a testbench! It's not difficult (you can even do it online) and for logical errors it is way faster to debug in simulation than iterating on real hardware.
Secondly: There's no clock in your code. Is this the top level? FPGAs aren't very good at asynchronous design particularly if you are trying to store state (in this case sum). It's not clear what Quartus will have inferred - it might have hooked one of your inputs up to a clock network. You should check the synthesised design in the RTL viewer and go through the synthesis logs.
However, when I try to increment the sum with any of the three buttons, a random number is added
Are you debouncing your switch input? If you aren't then it's very likely that for each button press you'll get a random number of toggles.
Note that your sensitivity list is incorrect here - it should include sum too:
always #(btn or reset)
Ironically (given my opening comment) this won't affect synthesis but would change the behaviour in simulation. You're better off using always_comb (or always #(*) if you're stuck with Verilog).

It depends what you want from the following line:
always #(btn or reset)
Combinatorial logic or Sequential (flip-flops)?
Combinatorial use always #* or always_comb if SystemVerilog is supported. The automatic sensitivity list behaves as combinatorial hardware does cutting down on simulation mismatches.
Also use = Blocking assignments for combinatorial.
Sequential use something like always #(posedge clk or negedge rst) and do use <= This will allow simulation to match hardware.
You issues look like they could be coming from sum <= sum + inc; which is then followed by optional reset statements. The use of <= is incorrect here as it is a combinatorial block with a manual sensitivity list. The scheduling of <= assignments might be throwing some thing off.
As it stands think about what hardware you might expect from :
always #* begin
sum = sum + 1;
end
Against what you get from:
always #(posedge clk or negedge rst_n) begin
if (~rst) begin
sum <= 'b0;
end
else begin
sum <= sum + 1;
end
end
I think if you add a clock to your design and imply a flip-flop for the counter (sum) you will have a big step in the right direction.

A random number is being displayed because sum is continuously being incremented while btn is changing states. A clear start and stop point must be explicit.
Try sampling btn with a clock. In a combination block assign inc. If past_btn equals btn, then assign inc to zero. sum should be assigned in a clocked block.
alwasy #* begin
if (past_btn == btn) inc = 'b0;
else begin
// case(btn) ...
end
end
always #(posedge clk) begin
past_btn <= btn;
if (!reset) sum <= 'b0;
else sum <= sum + inc;
end
If you are still getting random numbers, then the buttons are likely not denounced. In this case add another stage to the button sampling and use only the sampled values.
alwasy #* begin
if (past_btn == sync_btn) inc = 'b0;
else begin
// case(sync_btn) ...
end
end
always #(posedge clk) begin
sync_btn <= btn;
past_btn <= sync_btn;
if (!reset) sum <= 'b0;
else sum <= sum + inc;
end
Always make a test bench and run in simulation. Debugging from FPGA is difficult with logic bugs and implementation issues.

Related

if-else latch SystemVerilog

i was trying to make a floating point adder in SystemVerilog. When i saw the schematic generated i noticed the presence of a latch. The code is:
module ADDER (
input ieee_effloat In1_ADD, In2_ADD,
input ieee_float A_ADD,
output ieee_float Out_ADD
);
logic [24:0] MantissaSum; //Can generate an overflow, expand at 25 bit
always_comb
begin
MantissaSum = In1_ADD.Eff_Mantissa + In2_ADD.Eff_Mantissa; //Sum the mantissas
if(MantissaSum[24] == 1'b1) //If overflow
begin
MantissaSum >>= 1; //Shift the mantissa of 1
Out_ADD.Exponent = A_ADD.Exponent + 1; //<== Here is the latch (?)
Out_ADD.Mantissa = MantissaSum [22:0]; //Select the first 23 bit
end
else
begin
Out_ADD.Mantissa = MantissaSum [22:0]; //Select the first 23 bit
end
end
assign Out_ADD = '{1'b0, Out_ADD.Exponent, Out_ADD.Mantissa};
endmodule
The types are defined:
`ifndef FPU_MACROFLAG
`define FPU_MACROFLAG
package FPU_DEFINITION;
typedef struct packed {
logic Sign;
logic [7:0] Exponent;
logic [22:0] Mantissa;
} ieee_float; //IEEE-753 floating point number rapresentation
typedef struct packed {
logic Eff_Sign;
logic [7:0] Eff_Exponent;
logic [23:0] Eff_Mantissa;
} ieee_effloat; //IEEE-753 floating point number rapresentation effective mantissa
endpackage
import FPU_DEFINITION::*;
`endif
I don't know why this happen, I even closed the if with the else...
The way the latch is created in verilog is when you do not assign all outputs in all branches of an always block. In your situation:
always_comb
begin
you create a default value for MantissaSum. This way it is always assigned.
MantissaSum = In1_ADD.Eff_Mantissa + In2_ADD.Eff_Mantissa;
now, when you shift it in one of the branches and do not do anything in the other one the previous statement will take care of it.
if(MantissaSum[24] == 1'b1) //If overflow
begin
MantissaSum >>= 1; //Shift the mantissa of 1
However, here is you problem. your Out_ADD.Exponent is only assigned in the true branch of the if statement. If ManticcaSum[24] is not 1, then its value is supposed to be the same as before. This is a latch behavior.
Out_ADD.Exponent = A_ADD.Exponent + 1; //<== Here is the latch (?)
The rest is ok. Out_ADD.Mantissa is assigned in all branches.
Out_ADD.Mantissa = MantissaSum [22:0]; //Select the first 23 bit
end
else
begin
Out_ADD.Mantissa = MantissaSum [22:0]; //Select the first 23 bit
end
end
If this is what you want, you shold split this always block in two: one with always_comb, the second as always_latch, which takes care of the exponent. Or you should review your algorithm.
I believe the problem lies in the line Out_ADD.Mantissa = MantissaSum [22:0]; because in the true and the false condition this statement is executed, I think the synthesized version of your code will infer a latch with the enable = !MantissaSum[24] ( not 100% sure), I think the following change will keep the same logic and remove the latch.. just remove the line Out_ADD.Mantissa = MantissaSum [22:0]; from both the true and the false conditions and instead outside of the always_comb block type the following assign Out_ADD.Mantissa = MantissaSum [22:0];, tell me if that solved your problem

if statement inside of for loop not being executed

Writing a program to solve problem four of project euler: Find the largest palindrome made from the product of two 2-digit numbers. Heres my reprex:
#include <iostream>
int reverseNumber(int testNum)
{
int reversedNum, remainder = 0;
int temp = testNum;
while(temp != 0)
{
remainder = temp % 10;
reversedNum = reversedNum * 10 + remainder;
temp /= 10;
}
return reversedNum;
}
int main()
{
const int MIN = 100;
int numOne = 99;
int product = 0;
for(int numTwo = 10; numTwo < 100; numTwo++)
{
product = numOne * numTwo;
if (reverseNumber(product) == product)
{
int solution = product;
std::cout << solution << '\n';
return 0;
}
}
return 0;
}
My main thought process behind this is that the for loop will go through every number from 10 to 99 and multiply it by 99. My intended outcome is for it to print 9009 which is the largest palindrome with 2 factors of 2 digits. So what I think should happen here is the for loop will go from 10 to 99, and each loop it should go through the parameters of the if statement which reverses the number and sees if it equals itself.
I've made sure it wasn't a compiler issue, as this is recurring between different compilers. The reverseNumber() function returns the proper number every time I've tested it, so that shouldn't be the problem, however this problem only occurs when the function is involved in the logical comparison. By this I mean if that even I set it equal to a variable and put the variable in the if parameters, the issue still occurs. I'm pretty much stumped. I just hope it's not some silly mistake as I've been on this for a couple days now.
int reversedNum, remainder = 0;
You should be aware that this gives you (in an automatic variable context) a zero remainder but an arbitrary reversedNum. This is actually one of the reasons some development shops have the "one variable per declaration" rule.
In other words, it should probably be:
int reversedNum = 0, remainder;
or even:
int reversedNum = 0;
int remainder;
One other thing that often helps out is to limit the scope of variable to as small an area as possible, only bringing them into existence when needed. An example of that would be:
int reverseNumber(int testNum) {
int reversedNum = 0;
while (testNum != 0) {
int remainder = testNum % 10;
reversedNum = reversedNum * 10 + remainder;
testNum /= 10;
}
return reversedNum;
}
In fact, I'd probably go further and eliminate remainder altogether since you only use it once:
reversedNum = reversedNum * 10 + testNum % 10;
You'll notice I've gotten rid of temp there as well. There's little to gain by putting testNum into a temporary variable since it's already a copy of the original (as it was passed in by value).
And one other note, more to do with the problem rather than the code. You seem to be assuming that there is a palindrome formed that is a multiple of 99. That may be the case but a cautious programmer wouldn't rely on it - if you're allowed to assume things like that, you could just replace your entire program with:
print 9009
Hence you should probably check all possibilities.
You also get the first one you find which is not necessarily the highest one (for example, let's assume that 99 * 17 and 99 * 29 are both palindromic - you don't want the first one.
And, since you're checking all possibilities, you probably don't want to stop at the first one, even if the nested loops are decrementing instead of incrementing. That's because, if 99 * 3 and 97 * 97 are both palindromic, you want the highest, not the first.
So a better approach may be to start high and do an exhaustive search, while also ensuring you ignore the palindrome check of candidates that are smaller that your current maximum, something like (pseudo-code)
# Current highest palindrome.
high = -1
# Check in reverse order, to quickly get a relatively high one.
for num1 in 99 .. 0 inclusive:
# Only need to check num2 values <= num1: if there was a
# better palindrome at (num2 * num1), we would have
# already found in with (num1 * num2).
for num2 in num1 .. 0 inclusive:
mult = num1 * num2
# Don't waste time doing palindrome check if it's
# not greater than current maximum - we can't use
# it then anyway. Also, if we find one, it's the
# highest possible for THIS num1 value (since num2
# is decreasing), so we can exit the num2 loop
# right away.
if mult > high:
if mult == reversed(mult):
high = mult
break
if high >= 0:
print "Solution is ", high
else:
print "No solution"
In addition to properly initializing your variables, if you want the largest palindrome, you should switch the direction of your for loop -- like:
for(int numTwo = 100; numTwo > 10; numTwo--) {
...
}
or else you are just printing the first palindrome within your specified range

Trying to understanding a for loop that iterates through 40 bits

I recently ordered a DHT22 temperature and humidity sensor to play around with as well as some arduino nanos that I am still waiting on, and I was reading up on a few tutorials and things I am going to do with them when I get them and was reading through how to use the DHT22 which was pretty simple, and after reading the data sheet was interested in how they iterate through the 40 bits of data as I have never played around with bytes in code before so looked up the library for it which is here https://github.com/markruys/arduino-DHT.
Datasheet for DHT22 is here https://cdn-shop.adafruit.com/datasheets/Digital+humidity+and+temperature+sensor+AM2302.pdf
This is the main block of code that loops through the bits.
This is what I think is happening; you have an 8 bit int of i that starts at -3 because it uses 3 bits to start communicating with the sensor. i < 2 * 40 keeps i below 2 but iterates through 40 times (this is a stab in the dark, i haven't seen it before).
Next is the bit I'm not quite understanding at all, the while loop, where if the pin is high - 1 and is == (i(i being 0) & 1) then the while loop will be LOW, or if i is 1 then the loop will be high. Which then flows into the if statement where if ( i >= 0 && (i & 1)), but won't i eventually always be 1? If not what is modifying i? From what I have looked at you don't want to move the bits when the signal is LOW?
I can see what the rest of the code is doing I'm just not understanding it, the first if statement moves the bits i data left through every loop and if the signal is high for > 30 micro secs then the bit is 1 and a 1 is added to data.
// We're going to read 83 edges:
// - First a FALLING, RISING, and FALLING edge for the start bit
// - Then 40 bits: RISING and then a FALLING edge per bit
// To keep our code simple, we accept any HIGH or LOW reading if it's max 85 usecs long
uint16_t rawHumidity = 0;
uint16_t rawTemperature = 0;
uint16_t data = 0;
for ( int8_t i = -3 ; i < 2 * 40; i++ ) {
byte age;
startTime = micros();
do {
age = (unsigned long)(micros() - startTime);
if ( age > 90 ) {
error = ERROR_TIMEOUT;
return;
}
} while ( digitalRead(pin) == (i & 1) ? HIGH : LOW );
if ( i >= 0 && (i & 1) ) {
// Now we are being fed our 40 bits
data <<= 1;
// A zero max 30 usecs, a one at least 68 usecs.
if ( age > 30 ) {
data |= 1; // we got a one
}
}
switch ( i ) {
case 31:
rawHumidity = data;
break;
case 63:
rawTemperature = data;
data = 0;
break;
}
}
// Verify checksum
if ( (byte)(((byte)rawHumidity) + (rawHumidity >> 8) + ((byte)rawTemperature) + (rawTemperature >> 8)) != data ) {
error = ERROR_CHECKSUM;
return;
}
This is what I think is happening; you have an 8 bit int of i that starts at -3 because
it uses 3 bits to start communicating with the sensor. i < 2 * 40 keeps i below 2 but
iterates through 40 times (this is a stab in the dark, i haven't seen it before)
https://en.cppreference.com/w/cpp/language/operator_precedence
* (as the multiplication operator) has higher precedence than < (as less-than), so the terms are grouped such that * is resolved first.
So (i < 2 * 40) gets resolved (i < (2 * 40)). It's equivalent to (i < 80).
Next is the bit I'm not quite understanding at all, the while loop, where if the pin
is high - 1 and is == (i(i being 0) & 1) then the while loop will be LOW, or if i is
1 then the loop will be high.
do {
...
}
while ( digitalRead(pin) == (i & 1) ? HIGH : LOW );
Here, == has the higher precedence, so (digitalRead(pin) == (i & 1) is resolved first. ie, true when either digitalRead(pin) is 0 and i is even, digitalRead(pin) is 1 and i is odd. [since (i & 1) effectively tests the lowest bit]
Then the ternary subexpression is resolved, returning HIGH if true and LOW if false.
Have to run, hopefully that gets you there.
// We're going to read 83 edges:
// - First a FALLING, RISING, and FALLING edge for the start bit
// - Then 40 bits: RISING and then a FALLING edge per bit
The data bits shift left when the 'while' loop breaks: that happens when
the conditional's ternary operator result (HIGH or LOW) evaluates false. It's somewhat unclear exactly when that should occur since we lack definitions for HIGH and LOW.
However, since:
all-caps identifiers generally indicate that the identifier represents a macro,
HIGH and LOW having strictly constant truth value would make having the ternary expression in there at all totally pointless (if true then true else false??),
something in all this supposedly distinguishes rising-edge values from falling edges,
there's pretty much no other sensible place for that to happen (unless the pin read function does it internally and the comments discussion is just watercooler stuff)
...we should probably assume they each expand to an expression of some sort, and the result of THAT determines whether the loop should stop.
So, most likely, data <<= 1; occurs when:
digitalRead(pin) is high and *~something~*
digitalRead(pin) is low and *~something else~*
From what I can see, it would make the most sense if ~something~ and ~something else~ depend on the value of age.

Why is My Program not Working [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am a noob programmer,who just started in C++. I wrote a program, to answer a question. When I try to run it from my cmd.exe, windows tells me "a problem has caused this program to stop working, we'll close the program and notify you when a solution is available".
I have included a link to the well documented source code. Please take a look at the code, and help me out.
link: http://mibpaste.com/ZRevGf
i believe, that figuring out the error, with my code may help several other noob programmers out there, who may use similar methods to mine.
Code from link:
//This is the source code for a puzzle,well kind of that I saw on the internet. I will include the puzzle's question below.
//Well, I commented it so I hope you understand.
//ALAFIN OLUWATOBI 100L DEPARTMENT OF COMPUTER SCIENCE BABCOCK UNIVERSITY.
//Future CEO of VERI Technologies inc.
/*
* In a corridor, there are 100 doors. All the doors are initially closed.
* You walk along the corridor back and forth. As you walk along the corridor, you reverse the state of each door.
* I.e if the door is open, you close it, and if it is closed, you open it.
* You walk along the corrdor, a total of 200 times.
* On your nth trip, You stop at every nth door, that you come across.
* I.e on your first trip, you stop at every door. On your second trip, every second door, on your third trip every third door and so on and so forth
* Write a program to display, the final states of the doors.
*/
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;
inline void inverse(bool args[]); //The prototype of the function. I made the function inline in the declaration, to increase efficiency, ad speed of execution.
bool doors [200]; //Declaring a global array, for the doors.
int main ()
{
inverse(doors); //A call to the inverse function
cout << "This is the state of the 100 doors...\n";
for (int i = 0 ; i<200 ; i++) //Loop, to dis play the final states of the doors.
{
cout << "DOOR " << (i+1) << "\t|" << doors[i] << endl;
}
cout << "Thank you, for using this program designed by VERI Technologies. :)"; //VERI Technologies, is the name of the I.T company that I hope to establish.
return 0;
}
void inverse(bool args [])
{
for (int n = 1 ; n<= 200 ; n++) //This loop, is for the control of every nth trip. It executes 100 times
{
if (n%2 != 0) //This is to control the reversal of the doors going forward, I.e on odd numbers
{
for (int b = n, a = 1 ; b<=200 ;b = n*++a) //This is the control loop, for every odd trip, going forwards. It executes 100 times
args [b] = !args[b] ; //The reversal operation. It reverses the boolean value of the door.
}
/*
* The two variables, are declared. They will be used in controlling the program. b represents the number of the door to be operated on.
* a is a variable, which we shall use to control the value of b.
* n remains constant for the duration, of the loop, as does (200-n)
* the pre increment of a {++a} multiplied by n or (200-n) is used to calculate the value of b in the update.
* Thus, we have the scenario, of b increasing in multiples of n. Achieving what is desired for the program. Through this construct, only every nth door is considered.
*/
else if((n%2) == 0) //This is to control the reversal of the doors going backwards, I.e on even numbers
{
for (int b = (200-n), a = 1 ; b>=1 ; b = (200-n)*++a) //This is the control loop for every even trip, going backwards. It executes 100 times.
args [b] = !args[b] ; //The reversal operation. It reverses the boolean value of the door.
}
}
}
I believe the exception is due to the line:
for (int b = (200 - n), a = 1; b >= 1; b = (200 - n)*++a)
When the exception occurs the following values are assigned to the variables:
b = 3366
n = 2
a = 17
From what I can see, b is calculated by (200 - n) * a.
If we substitute the values given we have: 198 * 17
This gives us the value of 3366 which is beyond the index of doors and throws the exception when the line
args[b] = !args[b];
is executed.
I have created the following solution that should provide the desired results if you wish to use it.
void inverse(bool args[])
{
//n represents what trip you are taking down the hallway
//i.e. n = 1 is the first trip, n = 2 the second, and so on
for (int n = 1; n <= 200; n++){
//We are on trip n, so now we must change the state of all the doors for the trip
//The current door is represented by i
//i.e. i = 1 is the first door, i = 2 the second, and so on
for (int i = 1; i <= 200; i++){
//If the current door mod the trip is 0 then we must change the state of the door
//Only the nth door will be changed which occurs when i mod n equals 0
//We modify the state of doors[i - 1] as the array of doors is 0 - 199 but we are counting doors from 1 to 200
//So door 1 mod trip 1 will equal 0 so we must change the state of door 1, which is really doors[0]
if (i % n == 0){
args[i - 1] = !args[i - 1];
}
}
}
EUREKA!!!!!!
I finally came up with a working solution. No more errors. I'm calling it version 2.0.0
I've uploaded it online, and here's the link
[version 2.0.0] http://mibpaste.com/3NADgl
All that's left is to go to excel, and derive the final states of the door and be sure, that it's working perfectly. Please take a look at my solution, and comment on any error that I may have made, or any way you think that I may optimize the code.I thank you for your help, it allowed me to redesign a working solution to the program. I'm sstarting to think that an Out-of-bounds error, might have caused my version 1 to crash, but the logic was flawed, anyway, so I'm scrapping it.
This is ths code:
/**********************************************************************************************
200 DOOR PROGRAM
Version 2.0.0
Author: Alafin OluwaTobi Department of Computer Science, Babcock University
New Additions: I redrew, the algorithm, to geneate a more logically viable solution,
I additionally, expanded the size of the array, to prevent a potential out of bounds error.
**********************************************************************************************/
//Hello. This a program,I've written to solve a fun mental problem.
//I'll include a full explanation of the problem, below.
/**********************************************************************************************
*You are in a Hallway, filled with 200 doors .
*ALL the doors are initially closed .
*You walk along the corridor, *BACK* and *FORTH* reversing the state of every door which you stop at .
*I.e if it is open, you close it .
*If it is closed, you open it .
*On every nth trip, you stop at every nth door .
*I.e on your first trip, you stop at every door. On your second trip every second door, On your third trip every third door, etc .
*Write a program to display the final state of the doors .
**********************************************************************************************/
/**********************************************************************************************
SOLUTION
*NOTE: on even trips, your coming back, while on odd trips your going forwards .
*2 Imaginary doors, door 0 and 201, delimit the corridor .
*On odd trips, the doors stopped at will be (0+n) doors .
*I.e you will be counting forward, in (0+n) e.g say, n = 5: 5, 10, 15, 20, 25
*On even trips, the doors stopped at will be (201-n) doors.
*I.e you will be counting backwards in (201-n) say n = 4: 197, 193, 189, 185, 181
**********************************************************************************************/
#include <iostream>
#include <cstdlib> //Including the basic libraries
bool HALLWAY [202] ;
/*
*Declaring the array, for the Hallway, as global in order to initialise all the elements at zero.
*In addition,the size is set at 202 to make provision for the delimiting imaginary doors,
*This also serves to prevent potential out of bound errors, that may occur, in the use of thefor looplater on.
*/
inline void inverse (bool args []) ;
/*
*Prototyping the function, which will be used to reverse the states of the door.
*The function, has been declared as inline in order to allow faster compilation, and generate a faster executable program.
*/
using namespace std ; //Using the standard namespace
int main ()
{
inverse (HALLWAY) ; //Calling the inverse function, to act on the Hallway, reversing the doors.
cout << "\t\t\t\t\t\t\t\t\t\t200 DOOR TABLE\n" ;
for(int i = 1 ; i <= 200 ; i++ )
//A loop to display the states of the doors.
{
if (HALLWAY [i] == 0)
//The if construct allows us to print out the state of the door as closed, when the corresponding element of the Array has a value of zero.
{
cout << "DOOR " << i << " is\tCLOSED" << endl ;
for (int z = 0 ; z <= 300 ; z++)
cout << "_" ;
cout << "\n" ;
}
else if (HALLWAY [i] == 1)
//The else if construct allows us to print out the state of the door as open, when the corresponding element of the Array has a value of one.
{
cout << "DOOR " << i << " is\tOPEN" << endl ;
for (int z = 0 ; z <= 300 ; z++)
cout << "_" ;
cout << "\n" ;
}
}
return 0 ; //Returns the value of zero, to show that the program executed properly
}
void inverse (bool args[])`
{
for ( int n = 1; n <= 200 ; n++)
//This loop, is to control the individual trips, i.e trip 1, 2, 3, etc..
{
if (n%2 == 0)
//This if construct, is to ensure that on even numbers(i,e n%2 = 0), that you are coming down the hallway and counting backwards
{
for (int b = (201-n) ; b <= 200 && b >= 1 ; b -= n)
/*
*This loop, is for the doors that you stop at on your nth trip.
*The door is represented by the variable b.
*Because you are coming back, b will be reducing proportionally, in n.
*The Starting value for b on your nth trip, will be (201-n)
* {b -= n} takes care of this. On the second turn for example. First value of b will be 199, 197, 195, 193, ..., 1
*/
args [b] = !(args [b]) ;
//This is the actual reversal operation, which reverses the state of the door.
}
else if (n%2 != 0)
//This else if construct, is to ensure that on odd numbers(i.e n%2 != 0), that you are going up the hallway and counting forwards
{
for (int b = n ; b <= 200 && b >= 1 ; b += n)
/*
*This loop, is for the doors that you stop at on your nth trip.
*The door is represented by the variable b.
*Because you are going forwards, b will be increasing proportionally, in n.
*The starting value of b will be (0+n) whch is equal to n
* {b += n} takes care of this. On the third turn for example. First value of b will be 3, 6, 9, 12, ...., 198
*/
args [b] = !(args [b]) ;
//This is the actual reversal operation, which reverses the state of the door
}
}
}

Generate Block Compile Time If-Else Parameterized

I'm looking to be able to parametric some behavioral level Verilog using the generate block. The module is for a re-configurable readout and FIFO block, mainly so we can code this up one and just use a parameter at the top level.
Lets say we have:
always #(posedge write_out_clk or posedge RESETN)
begin
if (RESETN)
SENSE_ADDR <= 0;
else if (enb[0] == 1)
SENSE_ADDR <= 1; // for example but may be some other wire/bus etc
else if (enb[1] == 2)
SENSE_ADDR <= 1; // for example but may be some other wire/bus etc
else
SENSE_ADDR <= SENSE_ADDR;
end
end
This is behavioral so the specifics of implementation are left to the compiler with user given timing constraints etc. This works for 'n' else-if statements within the block if I hard code them, currently synthesis and simulation are both working for 16 statements.
My question however is how to parameterise this using generate? Clearly if 'n=8' its not too much of a big deal to hard code it. What if 'n=64' or 'n=128' etc. Seems a shame to hard code it if the rest of the module is fully parameterized using the generate for 'n'...
I have tried doing something like:
genvar elseif_generate;
generate
for (elseif_generate=0; elseif_generate<FIFO_SUB_BLOCKS; elseif_generate=elseif_generate+1)
begin: elseif_generate_logic
always #(posedge write_out_clk or posedge RESETN)
begin
if (RESETN)
SENSE_ADDR <= 0;
else if (enb[elseif_generate] == 1)
SENSE_ADDR <= some_wire[elseif_generate];
else
SENSE_ADDR <= SENSE_ADDR;
end
end
endgenerate
This however leads to Multi-source errors for the output wire 'SENSE_ADDR'. This leads me to the further question. Clearly a generate block is not suitable here but how would I go about implementing parameterised code replication for this block? Basically I want the functionality of the behavioral, hard coded if-else always block in a parameterised form...
Does this serve your needs? No generate required.
module mux #(
parameter WIDTH = 5,
parameter NUM = 2,
parameter NUMLG = $clog2(NUM)
) (
input [NUMLG -1:0] sel,
input [WIDTH - 1:0] in [0:NUM-1],
output [WIDTH - 1:0] out
);
assign out = in[sel];
endmodule
If your simulator doesn't support SystemVerilog that well you'll have to modify this to blow out the input array but the concept is the same.
You don not need a generate block. Add a combination always block to calculate next_SENSE_ADDR that will be flopped to SENSE_ADDR.
always #(posedge write_out_clk or posedge RESETN)
begin
if (RESETN)
SENSE_ADDR <= 0;
else
SENSE_ADDR <= next_SENSE_ADDR;
end
integer idx;
always #* begin // #(SENSE_ADDR or enb or some_wire)
next_SENSE_ADDR = SENSE_ADDR; // default, value if enb is all 0
// count down because lsb has higher priority
for ( idx=FIFO_SUB_BLOCKS-1; idx>=0; idx-- ) begin
if ( enb[idx] )
next_SENSE_ADDR = some_wire[idx];
end
end