I have a problem with verilog if-else statement. I'm trying to make a digital clock and my tick_counter module code like this. I pointed to error line with comment line. I cant find the solve, please help me.
module tick_counter(
input clk,
input tick_in,
output [3:0] ssd_2, ssd_4,
output [2:0] ssd_3
);
reg [5:0] count1, count_next1;
reg [2:0] count2, count_next2;
reg [3:0] count3, count4, count_next3, count_next4;
always#(posedge clk)
begin
count1 <= count_next1;
count2 <= count_next2;
count3 <= count_next3;
count4 <= count_next4;
end
//next state logic
always#*
begin
if(tick_in)
begin
if(count1==6'b111100) //second counter
begin
count_next1 = 6'b0;
count_next2 = count2 + 1'b1;
end
else
count_next1 = count1 + 1'b1;
if(count2==4'b1001) //minutes counter of LSB digit
begin
count_next2 = 4'b0000;
count_next3 = count3 + 1'b1;
end
else
count_next2 = count2 + 1'b1;
if(count3==3'b101) //minutes counter of MSB digit
begin
count_next3 = 3'b000;
count_next4 = count4 + 1'b1;
end
else
count_next3 = count3 + 1'b1;
if(count4==4'b1001) //counter hour
begin
count_next4 = 4'b0000;
end
else
count_next4 = count4 + 1'b1;
else //---THE POINT OF ERROR------
begin
count_next1 = count1;
count_next2 = count2;
count_next3 = count3;
count_next4 = count4;
end
end
end
assign ssd_2 = count2;
assign ssd_3 = count3;
assign ssd_4 = count4;
endmodule
Of course endmodule is missing. But this may be your typo mistake.
Proper indentation is greatly encouraged for large designs. Here, after indenting your code, I came to know that one end after the else part of // counter hour condition is missing. So, your main if condition's end is mis-placed. Just add end at the specified position and remove one end from the last of always block.
Kindly do proper indentation so that it becomes easy to debug.
Related
I want to know if these two codes would be doing the same? And what is the practical difference between them? If they are doing the same operation, is the second case faster than the first case?
In the first case, because I have to wait until it comes out to the "cycle statement" to recognize the rising of the flag "modi_varx_f" and "modi_vary_f" in order to "activate" in the next cycle and operate the increase of the variable, then it's slower than to do it at once as in the second case that seems to "activate" and run the operation within the same cycle.
First case:
always#(posedge clk or negedge rst) begin
if (~rst) begin
modi_varx_f = 0;
modi_vary_f = 0;
end
else if (cond1) begin
modi_varx_f = 1; // increase variable x on 1.
modi_vary_f = 1; // add 3'd6 to variable.
end
end
always#(posedge clk or negedge rst)
if (~rst)
varx = 0;
else if (modi_varx_f)
varx = varx + 1;
end
always#(posedge clk or negedge rst)
if (~rst)
vary = 0;
else if (modi_vary_f)
vary = vary + 3'd6;
end
Second case:
always#(posedge clk or negedge rst) begin
if (~rst) begin
varx = 0;
vary = 0;
end
else if (cond1) begin;
varx = vary + 1;
vary = vary + 3'd6;
end
end
just to summarize the comment stream. In general, you can collapse multiple sequential always blocks into one without loosing functionality. I guess that you made a mistake in the second example and used varx = vary + 1; while in the first case you used varx = varx + 1;. This makes the difference.
However, if the second example uses varx, than both are equivalent.
Since you used sequential elements (flops with asynchronous reset) in your examples, you should have used non-blocking assignments there, according to industry-wide practices. And the right answer for collapsing should look like this:
always#(posedge clk or negedge rst) begin
if (~rst) begin
varx <= 0;
vary <= 0;
end
else if (cond1) begin;
varx <= varx + 1; // << varx
vary <= vary + 3'd6;
end
end
I'm trying to create a procedure in Maple 12 that takes an input "n" and outputs all the numbers in the sequence 1!, 1! + 2!, 1! + 2! + 3!, ... etc up to the user input and one value over (i.e the first number in the sequence greater than n).
Here is my current code:
fact := proc (n);
local i, a;
a = 1
i = 1
while i < n do
list(a) = i;
a = a + 1
i = b(1..(a! + list(a - 1)));
od
return(b)
end
I'm almost completly new to Maple so the code is probably rubbish and haven't been given much information to work with, so anything to help would be gladly accepted.
Many Thanks
Here are a few ways.
restart:
fact:=proc(n::posint)
local i, a, b;
a := 1;
b[1] := 1;
for i from 2 to n+1 do
a := a*i;
b[i] := b[i-1] + a;
end do;
return seq(b[i],i=1..n+1);
end proc:
for k from 1 to 10 do
fact(k);
end do;
restart:
fact2:=proc(n::posint)
local i;
seq(add(i!,i=1..k),k=1..n+1);
end proc:
for k from 1 to 10 do
fact2(k);
end do;
restart:
fact3:=proc(n::posint)
option rememeber;
local i,t;
if n=1 then
return 1,3;
else
t:=fact3(n-1);
return t, t[-1]+(n+1)!;
end if;
end proc:
for k from 1 to 10 do
fact3(k);
end do;
The second approach above is the least efficient, as it recomputes the factorials over and over, without re-use. The third approach is recursive.
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.
I am getting a warning when i try synthesize,implement, and generate program file from my VHDL Code.
When i try to synthesize i get this error
WARNING:Xst:647 - Input <BTN_3> is never used.
This port will be preserved and left unconnected if it
belongs to a top-level block or it belongs to a sub-block and
the hierarchy of this sub-block is preserved.
When i Implement it i get this
WARNING:PhysDesignRules:367 - The signal <BTN_3_IBUF> is incomplete. The signal
does not drive any load pins in the design.
WARNING:Par:288 - The signal BTN_3_IBUF has no load.
PAR will not attempt to route this signal.
WARNING:Par:283 - There are 1 loadless signals in this design.
This design will cause Bitgen to issue DRC warnings.
and when i generate program file i get this error
WARNING:PhysDesignRules:367 - The signal <BTN_3_IBUF> is incomplete.
The signal does not drive any load pins in the design.
What could cause this error..
The code can be found here [http://pastebin.com/eK05tyEb][1]
[1]: http://pastebin.com/eK05tyEb - link to the code
User constrain file /.Ucf
NET "Switch_0" LOC = "G18";
NET "Switch_1" LOC = "H18";
NET "Switch_2" LOC = "K18";
NET "Switch_3" LOC = "K17";
NET "Switch_4" LOC = "L14";
NET "Switch_5" LOC = "L13";
NET "Switch_6" LOC = "N17";
NET "Switch_7" LOC = "R17";
NET "LED_0" LOC = "J14";
NET "LED_1" LOC = "J15";
NET "LED_2" LOC = "K15";
NET "LED_3" LOC = "K14";
NET "LED_4" LOC = "E17";
NET "LED_5" LOC = "P15";
NET "LED_6" LOC = "F4";
NET "LED_7" LOC = "R4";
NET "BTN_3" LOC = "H13";
Your code as you have posted may not tell the entire story. Normally there is an interface (user constraints, thanks Bob) file that defines pin edge inputs and outputs to a port of a circuit internal to the FPGA you define. I am not seeing that.
Secondly, I also see in your code that you have 2 differing circuits driving each one of your output LEDs.
You have an if statement that checks for BTN_3 being 1, which will drive ALL of the LEDs to 0, then a set of If statements checking the input state of each "Switch_X" which individually drives a 0 or one to each LED. This is actually illegal. You can only have one circuit driving any output port.
What you should do is write this circuit as follows:
architecture Behavioral of Switch_led is
begin
Process(Switch_0, Switch_1, Switch_2, Switch_3, Switch_4, Switch_5, Switch_6 , Switch_7, BTN_3)
begin
if BTN_3 = '1' then
Led_0 <= '0';
Led_1 <= '0';
Led_2 <= '0';
Led_3 <= '0';
Led_4 <= '0';
Led_5 <= '0';
Led_6 <= '0';
Led_7 <= '0';
else
if Switch_0 = '1' then
Led_0 <= '1';
else
Led_0 <= '0';
end if;
if Switch_1 = '1' then
Led_1 <= '1';
else
Led_1 <= '0';
end if;
if Switch_2 = '1' then
Led_2 <= '1';
else
Led_2 <= '0';
end if;
if Switch_3 = '1' then
Led_3 <= '1';
else
Led_3 <= '0';
end if;
if Switch_4 = '1' then
Led_4 <= '1';
else
Led_4 <= '0';
end if;
if Switch_4 = '1' then
Led_4 <= '1';
else
Led_4 <= '0';
end if;
if Switch_5 = '1' then
Led_5 <= '1';
else
Led_5 <= '0';
end if;
if Switch_6 = '1' then
Led_6 <= '1';
else
Led_6 <= '0';
end if;
if Switch_7 = '1' then
Led_7 <= '1';
else
Led_7 <= '0';
end if;
end if;
end process;
end Behavioral;
What I have essentially done is to bring all of your individual Switch_X checking into the else clause of the btn_3 check. This forces what I was stating before, that only one logic circuit will drive any LED at any point in time.
Ok, here's the function I'm a bit mystified by(Little rusty bitwise operators)
void two_one(unsigned char *in,int in_len,unsigned char *out)
{
unsigned char tmpc;
int i;
for(i=0;i<in_len;i+=2){
tmpc=in[i];
tmpc=toupper(tmpc);
if((tmpc<'0'||tmpc>'9') && (tmpc<'A'||tmpc>'F'))tmpc='F';
if(tmpc>'9')
tmpc=toupper(tmpc)-'A'+0x0A;
else
tmpc-='0';
tmpc<<=4; //Confused here
out[i/2]=tmpc;
tmpc=in[i+1];
tmpc=toupper(tmpc);
if((tmpc<'0'||tmpc>'9') && (tmpc<'A'||tmpc>'F'))tmpc='F';
if(tmpc>'9')
tmpc=toupper(tmpc)-'A'+0x0A;
else
tmpc-='0';
out[i/2]|=tmpc; //Confused Here
}
}
I marked the two places that I don't quite understand.
If anyone could help me convert those pieces to Vb.Net, or at least help me understand what's going on there, that'd be awesome.
Thanks.
Update
So this is what I came up with, but it's not quite giving me back the right data...Anything look wrong here?
Public Function TwoOne(ByVal inp As String) As String
Dim temp As New StringBuilder()
Dim tempc As Char
Dim tempi As Byte
Dim i As Integer
Dim len = inp.Length
inp = inp + Chr(0)
For i = 0 To len Step 2
If (i = len) Then Exit For
tempc = Char.ToUpper(inp(i))
If ((tempc < "0"c Or tempc > "9"c) AndAlso (tempc < "A"c Or tempc > "F"c)) Then
tempc = "F"c
End If
If (tempc > "9"c) Then
tempc = Char.ToUpper(tempc)
tempc = Chr(Asc(tempc) - Asc("A"c) + &HA)
Else
tempc = Chr(Asc(tempc) - Asc("0"c))
End If
tempc = Chr(CByte(Val(tempc)) << 4)
Dim tempcA = tempc
tempc = Char.ToUpper(inp(i + 1))
If ((tempc < "0"c Or tempc > "9"c) AndAlso (tempc < "A"c Or tempc > "F"c)) Then
tempc = "F"c
End If
If (tempc > "9"c) Then
tempc = Char.ToUpper(tempc)
tempc = Chr(Asc(tempc) - Asc("A"c) + &HA)
Else
tempc = Chr(Asc(tempc) - Asc("0"c))
End If
temp.Append(Chr(Asc(tempcA) Or Asc(tempc)))
Next
TwoOne = temp.ToString()
End Function
tmpc <<= 4 shifts the bits in tmpc 4 places to the left, then assigns the value back to tmpc. Hence if tmpc was 00001101, it becomes 11010000
out[i/2]|=tmpc bitwise-ors the array value with tmpc. Hence if out[i/2] is 01001001 and tmpc is 10011010, then out[i/2] becomes 11011011
EDIT (updated question):
The lines tmpc-='0'; in the original are not exactly the same as your new code tempc = "0"c. -= subtracts the value from the variable, and hence you need tempc = tempc - "0"c or similar
tmpc<<=4; (or tmpc = tmpc << 4;) shifts tmpc left by 4 bits.
out[i/2]|=tmpc; (or out[i/2] = out[i/2] | tmpc;) bitwise-ORs out[i/2] with tmpc.