I try to write a program to test a hamming code with one error bit. My design part have finished, but my test bench still has some problem. When I hit start the program just keep running for a long period without result and never stops. My design is
// Code your design here
module hamming_code_checker(hamming_code, error_code);
input [1:32] hamming_code;
output reg [1:6] error_code;
reg [1:6]count = {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0};
always#(*)
begin
if(hamming_code[1] == 1)
count[5]=count[5]+1;
if(hamming_code[2] == 1)
count[5]=count[5]+1;
if(hamming_code[3] == 1)
begin
count[5]=count[5]+1;
count[4]=count[4]+1;
end
if(hamming_code[4] == 1)
count[3]=count[3]+1;
if(hamming_code[5] == 1)
begin
count[5]=count[5]+1;
count[3]=count[3]+1;
end
if(hamming_code[6] == 1)
begin
count[4]=count[4]+1;
count[3]=count[3]+1;
end
if(hamming_code[7] == 1)
begin
count[5]=count[5]+1;
count[4]=count[4]+1;
count[3]=count[3]+1;
end
if(hamming_code[8] == 1)
count[2]=count[2]+1;
if(hamming_code[9] == 5)
begin
count[5]=count[5]+1;
count[2]=count[2]+1;
end
if(hamming_code[10] == 1)
begin
count[4]=count[4]+1;
count[2]=count[2]+1;
end
if(hamming_code[11] == 1)
begin
count[5]=count[5]+1;
count[4]=count[4]+1;
count[2]=count[2]+1;
end
if(hamming_code[12] == 1)
begin
count[3]=count[3]+1;
count[2]=count[2]+1;
end
if(hamming_code[13] == 1)
begin
count[5]=count[5]+1;
count[3]=count[3]+1;
count[2]=count[2]+1;
end
if(hamming_code[14] == 1)
begin
count[4]=count[4]+1;
count[3]=count[3]+1;
count[2]=count[2]+1;
end
if(hamming_code[15] == 1)
begin
count[5]=count[5]+1;
count[4]=count[4]+1;
count[3]=count[3]+1;
count[2]=count[2]+1;
end
if(hamming_code[16] == 1)
begin
count[1]=count[1]+1;
end
if(hamming_code[17] == 1)
begin
count[5]=count[5]+1;
count[1]=count[1]+1;
end
if(hamming_code[18] == 1)
begin
count[4]=count[4]+1;
count[1]=count[1]+1;
end
if(hamming_code[19] == 1)
begin
count[5]=count[5]+1;
count[4]=count[4]+1;
count[1]=count[1]+1;
end
if(hamming_code[20] == 1)
begin
count[3]=count[3]+1;
count[1]=count[1]+1;
end
if(hamming_code[21] == 1)
begin
count[5]=count[5]+1;
count[3]=count[3]+1;
count[1]=count[1]+1;
end
if(hamming_code[22] == 1)
begin
count[4]=count[4]+1;
count[3]=count[3]+1;
count[1]=count[1]+1;
end
if(hamming_code[23] == 1)
begin
count[5]=count[5]+1;
count[4]=count[4]+1;
count[3]=count[3]+1;
count[1]=count[1]+1;
end
if(hamming_code[24] == 1)
begin
count[2]=count[2]+1;
count[1]=count[1]+1;
end
if(hamming_code[25] == 1)
begin
count[5]=count[5]+1;
count[2]=count[2]+1;
count[1]=count[1]+1;
end
if(hamming_code[26] == 1)
begin
count[4]=count[4]+1;
count[2]=count[2]+1;
count[1]=count[1]+1;
end
if(hamming_code[27] == 1)
begin
count[5]=count[5]+1;
count[4]=count[4]+1;
count[2]=count[2]+1;
count[1]=count[1]+1;
end
if(hamming_code[28] == 1)
begin
count[3]=count[3]+1;
count[2]=count[2]+1;
count[1]=count[1]+1;
end
if(hamming_code[29] == 1)
begin
count[5]=count[5]+1;
count[3]=count[3]+1;
count[2]=count[2]+1;
count[1]=count[1]+1;
end
if(hamming_code[30] == 1)
begin
count[4]=count[4]+1;
count[3]=count[3]+1;
count[2]=count[2]+1;
count[1]=count[1]+1;
end
if(hamming_code[31] == 1)
begin
count[5]=count[5]+1;
count[4]=count[4]+1;
count[3]=count[3]+1;
count[2]=count[2]+1;
count[1]=count[1]+1;
end
if(hamming_code[32] == 1)
begin
count[6]=count[6]+1;
count[5]=count[5]+1;
count[4]=count[4]+1;
count[3]=count[3]+1;
count[2]=count[2]+1;
count[1]=count[1]+1;
end
end
always#*
begin
if(count[6]%2==0)
error_code[6]=1'B0;
else
error_code[6]=1'B1;
if(count[5]%2==0)
error_code[5]=1'B0;
else
error_code[5]=1;
if(count[4]%2==0)
error_code[4]=1'B0;
else
error_code[4]=1;
if(count[3]%2==0)
error_code[3]=1'B0;
else
error_code[3]=1;
if(count[2]%2==0)
error_code[2]=1'B0;
else
error_code[2]=1;
if(count[1]%2==0)
error_code[1]=1'B0;
else
error_code[1]=1;
end
/*xor(error_code[1], count[1]);
xor(error_code[2], count[2]);
xor(error_code[3], count[3]);
xor(error_code[4], count[4]);
xor(error_code[5], count[5]);
xor(error_code[6], count[6]);*/
endmodule
My test bench is
// Code your testbench here
// or browse Examples
//`timescale 10ns/1ns
reg error_bit = 1'D0;
wire [1:6] error_code;
module hamming_error_detect();
reg [1:32] hamming_code;
//int i;
hamming_code_checker dut(hamming_code, error_code);
initial begin
hamming_code = 32'B11001000010100100110110100011000;
#20
trans();
$display("The error codes you enter are: %b", hamming_code);
$display("The position of a specific error code is at the %d th bit.", error_bit);
$finish;
end
endmodule
task trans();
//error_bit = 0;
integer i;
for(i=1 ; i<=6 ; i++)
begin
error_bit += error_code[i]*$pow(2, 6-i);
end
endtask
I don't know what's wrong with my code.
entire execute message
[2023-01-10 05:23:53 EST] vcs -licqueue '-timescale=1ns/1ns' '+vcs+flush+all' '+warn=all' '-sverilog' design.sv testbench.sv && ./simv +vcs+lic+wait
Warning-[LINX_KRNL] Unsupported Linux kernel
Linux kernel '3.13.0-71-generic' is not supported.
Supported versions are 2.4* or 2.6*.
Chronologic VCS (TM)
Version S-2021.09 -- Tue Jan 10 05:23:54 2023
Copyright (c) 1991 - 2021 Synopsys, Inc.
This software and the associated documentation are proprietary to Synopsys,
Inc. This software may only be used in accordance with the terms and conditions
of a written license agreement with Synopsys, Inc. All other use, reproduction,
or distribution of this software is strictly prohibited. Licensed Products
communicate with Synopsys servers for the purpose of providing software
updates, detecting software piracy and verifying that customers are using
Licensed Products in conformity with the applicable License Key for such
Licensed Products. Synopsys will use information gathered in connection with
this process to deliver software updates and pursue software pirates and
infringers.
Inclusivity & Diversity - Visit SolvNetPlus to read the "Synopsys Statement on
Inclusivity and Diversity" (Refer to article 000036315 at
https://solvnetplus.synopsys.com)
Parsing design file 'design.sv'
Parsing design file 'testbench.sv'
Top Level Modules:
hamming_error_detect
TimeScale is 1 ns / 1 ns
Starting vcs inline pass...
1 module and 0 UDP read.
recompiling module hamming_error_detect
rm -f _cuarc*.so _csrc*.so pre_vcsobj_*.so share_vcsobj_*.so
if [ -x ../simv ]; then chmod a-x ../simv; fi
g++ -o ../simv -m32 -m32 -rdynamic -Wl,-rpath='$ORIGIN'/simv.daidir -Wl,-rpath=./simv.daidir -Wl,-rpath=/apps/vcsmx/vcs/S-2021.09/linux/lib -L/apps/vcsmx/vcs/S-2021.09/linux/lib -Wl,-rpath-link=./ -Wl,--no-as-needed objs/amcQw_d.o _320_archive_1.so SIM_l.o rmapats_mop.o rmapats.o rmar.o rmar_nd.o rmar_llvm_0_1.o rmar_llvm_0_0.o -lvirsim -lerrorinf -lsnpsmalloc -lvfs -lvcsnew -lsimprofile -luclinative /apps/vcsmx/vcs/S-2021.09/linux/lib/vcs_tls.o -Wl,-whole-archive -lvcsucli -Wl,-no-whole-archive /apps/vcsmx/vcs/S-2021.09/linux/lib/vcs_save_restore_new.o /apps/vcsmx/vcs/S-2021.09/linux/lib/ctype-stubs_32.a -ldl -lc -lm -lpthread -ldl
../simv up to date
CPU time: .429 seconds to compile + .550 seconds to elab + .382 seconds to link
Chronologic VCS simulator copyright 1991-2021
Contains Synopsys proprietary information.
Compiler version S-2021.09; Runtime version S-2021.09; Jan 10 05:23 2023
I have tried putting some variables that will be used to the top of my program, because I don't know the way to pass values is the same as C++ or not. I also tried add $finish; in my test bench and expect it to stop automatically, but in vain.
I have reproduced it in a stand-alone vcs. The issue is that you introduced a series of zero-delay loops in simulation:
always #* begin
if(hamming_code[1] == 1)
count[5]=count[5]+1;
....
end
What happens here is that as soon as hamming_code[1] becomes '1', the value of count[5] will change. As soon as it changes, it will re-evaluate the always block. hamming_code[1] stays the same, so the count[5] will change again and so on.
To break a loop, you will need a clock (and a flop).
A good vcs run-time qualifier to use to detect such loops is +vcs+loopdetect+100000 or any other big number.
Also note, that count[5] in your case is a one-bit signal. Adding '1' to it does not make much sense in particular in combination with 'count[num]%2'. Same story with error_bit.
Related
I am receiving this error from Quartus when trying to compile:
Error (10200): Verilog HDL Conditional Statement error at
time_of_day_FSM.v(166): cannot match operand(s) in the condition to
the corresponding edges in the enclosing event control of the always
construct
Here is some background. I am making a clock, and for this always block, I want to increment and set certain values to resemble the behavior of a clock in the format of hh:mm:ss. I have a clock source that goes high every millisecond, and am using a counter to set the secondPassed reg.
I want the code in the block to update every time a second passes, like a clock, or KEY[2] is pressed on my board (down = 0), as this is what the user uses to increment the hours, minutes, or seconds when setting the clock time. Here is the always block in question (sorry for the nested if statements, I can't think of a better way to do it):
// every second. Used just to keep time going. Independent of states.
always #(posedge secondPassed, negedge KEY[2], negedge KEY[0]) begin
if(KEY[0] == 0) begin
hr1 <= 1;
hr0 <= 2;
min1 <= 0;
min0 <= 0;
sec1 <= 0;
sec0 <= 0;
end
else if(secondPassed == 1 || KEY[2] == 0) begin // I don't care about explicitly stating the conditions, as the sensitivity list covers that right?
if(sec0 == 9) begin
sec0 <= 0;
if(sec1 == 5) begin
sec1 <= 0;
if(min0 == 9) begin
min0 <= 0;
if(min1 == 5) begin
min1 <= 0;
if(hr1 == 1) begin
if(hr0 == 2) begin
hr0 <= 1; // go to 1 o'clock
hr1 <= 0;
end
else hr0 <= hr0 + 1;
end
else hr0 <= hr0 + 1;
end
else min1 <= min1 + 1;
end
else min0 <= min0 + 1;
end
else sec1 <= sec1 + 1;
end
else begin
sec0 <= sec0 + 1;
end
just_flashed <= ~just_flashed;
end // end big else
end // end always
My question is: Why does the Quartus compiler complain if I try to make the non-reset scenario JUST AND ELSE, like this:
// every second. Used just to keep time going. Independent of states.
always #(posedge secondPassed, negedge KEY[2], negedge KEY[0]) begin
if(KEY[0] == 0) begin
hr1 <= 1;
hr0 <= 2;
min1 <= 0;
min0 <= 0;
sec1 <= 0;
sec0 <= 0;
end
else begin // this is causing the issue. compiler complains .
// same logic to drive clock as above
just_flashed <= ~just_flashed;
end // end big else
end // end always
I feel I have seen many examples where people simply use and else begin end for their code. My code seems to want my to EXPLICITLY restate the conditions of the sensitivity list for the else if. Any explanation? I am new to large verilog projects.
You are mixing combinational logic and synchronous logic in the always block and this is bad habit of coding. Generally, there are 2 main always blocks in most designs.
A combinational:
always#(*) // * adds anything under this always block to sensitivity list.
begin // Which makes this always block combinational.
count_reg_d <= somelogic;
end
Then these combinational logic is assigned to proper registers in the sequental
always block:
always#(posedge clk, negedge rst)
begin
if(~rst)
count_reg_q <= 0;
else
begin
count_reg_q <= count_reg_d;
end
end
By coding this way you avoid mixed always blocks, and the code is much more readable and closer to hardware that is being synthesized. So if you update the always blocks' sensitivity list properly the problems has to be solved.
I would like to know if I can put below code in a for loop so I can parameterize my code. Thank you.
always#(*) begin
if (exist_reg[0] == 'd0) begin
nth_empty_location_descending = 'd1; // specify
end
else if (exist_reg[1] =='d0) begin
nth_empty_location_descending = 'd2;
end
else if (exist_reg[2] =='d0) begin
nth_empty_location_descending = 'd4;
end
else if (exist_reg[3] =='d0) begin
nth_empty_location_descending = 'd8;
end
else if (exist_reg[4] =='d0) begin
nth_empty_location_descending = 'd16;
end
else if (exist_reg[5] =='d0) begin
nth_empty_location_descending = 'd32;
end
else if (exist_reg[6] =='d0) begin
nth_empty_location_descending = 'd64;
end
else if (exist_reg[7] =='d0) begin
nth_empty_location_descending = 'd128;
end
else if (exist_reg[8] =='d0) begin
nth_empty_location_descending = 'd256;
end
else if (exist_reg[9] =='d0) begin
nth_empty_location_descending = 'd512;
end
else begin
nth_empty_location_descending = 'd0;
end
end
It is basically checking an "exist_reg" bits, if it encounters any bit from left to right is zero then it will rise that bit in "nth_empty_location_descending" register(any better approach?). Now I want to create parameterized code for the width of the register. Currently, it is 10-bit hardcoded code.
Thank you experts.
first of all it, the best solution is probably using casez statement instead of the if/else chain:
always#(*) begin
casez (exist_reg)
10'b?????????0: nth_empty_location_descending1 = 'd1;
10'b????????01: nth_empty_location_descending1 = 'd2;
10'b???????011: nth_empty_location_descending1 = 'd4;
10'b??????0111: nth_empty_location_descending1 = 'd8;
10'b?????01111: nth_empty_location_descending1 = 'd16;
10'b????011111: nth_empty_location_descending1 = 'd32;
10'b???0111111: nth_empty_location_descending1 = 'd64;
10'b??01111111: nth_empty_location_descending1 = 'd128;
10'b?011111111: nth_empty_location_descending1 = 'd256;
10'b0111111111: nth_empty_location_descending1 = 'd512;
default : nth_empty_location_descending1 = 'd0;
endcase // casez (exist_reg)
end // always# (*)
however, if you insist, there is a loop-based solution:
always #* begin
nth_empty_location_descending2 = 'd0;
for (j = 0; j < 10; j = j + 1) begin
if (exist_reg[j] == 1'b0) begin
if (nth_empty_location_descending2 == 0)
nth_empty_location_descending2 = (10'b1 << j);
end
end
end // always # *
parameter WIDTH = 10;
reg [WIDTH-1:0] exist_reg, nth_empty_location_descending2;
integer ii;
always #* begin
nth_empty_location_descending2 = 0;
for(ii=0;ii<WIDTH;ii=ii+1)
if (exist_reg[j] == 1'b0 && nth_empty_location_descending2 == 0)
nth_empty_location_descending2[ii] = 1'b1;
end
In SystemVerilog
parameter WIDTH = 10;
logic [WIDTH-1:0] exist_reg, nth_empty_location_descending2;
always_comb begin
nth_empty_location_descending2 = 0;
for(int ii=0;ii<WIDTH;ii++)
if (exist_reg[j] == 1'b0) begin
nth_empty_location_descending2[ii] = 1'b1;
break;
end
end
I'm trying to add a second level of nesting to my generate loop in the following code, but iverilog is throwing an error that the register j is unknown:
../crc.v:119: register ``j'' unknown in crc_tb.U_crc.loop[31].
So is it possible to use multiple genvars in verilog? It looks like j is being interpreted as a register.
Code snippet:
genvar i;
genvar j;
reg [DATA_WIDTH-1:0] temp;
generate
for(i = 0; i < CRC_WIDTH; i= i + 1)
begin : loop
always #(posedge clock or posedge reset)
begin
if (reset)
begin
crc_out[i+:1] = SEED[i+:1];
end
else if (init)
begin
crc_out[i+:1] = SEED[i+:1];
end
else if (data_enable)
begin
if (DEBUG)
$display("\n\nCRC OUT[%0d]\n***************************************************************************", i);
if (REVERSE)
begin
for (j = DATA_WIDTH-1; j >= 0; j = j - 1)
begin : reverse_loop
temp[DATA_WIDTH-1-j] = data[i][j];
end
crc_out[i+:1] <= prev(DATA_WIDTH-1,i,temp,crc_out);
end
else
begin
crc_out[i+:1] <= prev(DATA_WIDTH-1,i,data,crc_out);
end
end
end
end
endgenerate
You can nest multiple generate loops, but your inner generate loop is inside a procedural block of code - that is illegal. Perhapsj should just be a local variable instead of a genvar.
I am struggling for some time already and I can't find a simple and useful solution.
I would like to simulate triangular signal in size of 16 bits
and add a random noise to it with values 1 , 0, -1. It is important that signal with noise never differs for more than 1 from original noise and from previous value in noised signal.
For example, I would like values in that way:
ORIGINAL SIGNAL: 11111 22222 33333 44444 55555 ...
NOISED SIGNAL : 12321 12332 23434 34345 45665 ...
I simulated signal for values between 0 and 30766 because main focus now is adding noise to this original signal. This code work properly because I removed the conditions which limit the difference between values for maximum 1.
This signal is used for test bench.
reg [15:0] SIGNAL_i;
reg [15:0] SIGNAL_ii;
reg [15:0] SIGNAL_noise_i;
reg [15:0] SIGNAL_noise_reg; //za hranjenje zasumljenega signala
int RANDOM_noise_i;
int COUNT_end;
int COUNT;
initial SIGNAL_i=1;
initial COUNT_end=0;
initial COUNT=3'd4;
initial SIGNAL_ii=0;
initial SIGNAL_noise_i=1;
initial SIGNAL_noise_reg=0;
initial RANDOM_noise_i=1;
initial CLK = 1;
always #5 CLK = ~CLK;
always #10
begin
SIGNAL_noise_reg <= SIGNAL_noise_i;
RANDOM_noise_i = $signed($urandom_range(0,2))-1; //random noise generation
//upcount
if ((SIGNAL_i<16'd30766) && (SIGNAL_ii<SIGNAL_i)) //32765
begin
begin
if (COUNT_end==COUNT)
begin
assign SIGNAL_noise_i=SIGNAL_i + (RANDOM_noise_i);
SIGNAL_i=SIGNAL_i + 1;
SIGNAL_ii=SIGNAL_ii + 1;
COUNT_end=0;
COUNT_end=0;
end
else
begin
assign SIGNAL_noise_i=SIGNAL_i + (RANDOM_noise_i);
COUNT_end= COUNT_end + 1;
end
end
end
//counter on zero
else if (SIGNAL_i == 0)
begin
SIGNAL_i = 1;
SIGNAL_ii = 0;
SIGNAL_noise_i = SIGNAL_i + RANDOM_noise_i;
end
//down count
else
begin
if (COUNT_end==COUNT)
begin
assign SIGNAL_noise_i=SIGNAL_i + (RANDOM_noise_i);
SIGNAL_i=SIGNAL_i - 1;
SIGNAL_ii=SIGNAL_ii + 1;
COUNT_end=0;
COUNT_end=0;
end
else
begin
assign SIGNAL_noise_i=SIGNAL_i + (RANDOM_noise_i);
COUNT_end= COUNT_end + 1;
end
end
end
end
I would really appreciate your help!
Thank you.
I got the signal I wanted but for sure there are also beter ways to implement it. I simplified it a bit.
always #10
begin
SIGNAL_noise_reg <= SIGNAL_noise_i;
RANDOM_noise_i = $signed($urandom_range(0,2))-1;
if ((SIGNAL_i<16'd30766) && (SIGNAL_ii<SIGNAL_i)) //32765
begin
if(COUNT_end==COUNT-1)
begin
assign SIGNAL_noise_i=SIGNAL_i-1;
SIGNAL_i=SIGNAL_i + 1;
SIGNAL_ii=SIGNAL_ii + 1;
COUNT_end=0;
end
else if (COUNT_end == 0)
begin
assign SIGNAL_noise_i=SIGNAL_i -1;
COUNT_end= COUNT_end + 1;
end
else
begin
if (SIGNAL_i + RANDOM_noise_i - SIGNAL_noise_i > 1)
begin
assign SIGNAL_noise_i=SIGNAL_i;
COUNT_end= COUNT_end + 1;
end
else
begin
assign SIGNAL_noise_i=SIGNAL_i + RANDOM_noise_i;
COUNT_end= COUNT_end + 1;
end
end
end
else if (SIGNAL_i == 0)
begin
SIGNAL_i = 1;
SIGNAL_ii = 0;
SIGNAL_noise_i = SIGNAL_i + RANDOM_noise_i;
end
else
begin
if(COUNT_end==COUNT-1)
begin
assign SIGNAL_noise_i=SIGNAL_i+1;
SIGNAL_i=SIGNAL_i - 1;
SIGNAL_ii=SIGNAL_ii + 1;
COUNT_end=0;
end
else if (COUNT_end == COUNT-2)
begin
assign SIGNAL_noise_i=SIGNAL_i;
COUNT_end= COUNT_end + 1;
end
else
begin
if (SIGNAL_i + RANDOM_noise_i - SIGNAL_noise_i > 1)
begin
assign SIGNAL_noise_i=SIGNAL_i;
COUNT_end= COUNT_end + 1;
end
else
begin
assign SIGNAL_noise_i=SIGNAL_i + RANDOM_noise_i;
COUNT_end= COUNT_end + 1;
end
end
end
end
I do not understand why the timer counter in this code does not work. At the end of every clock cycle the value resets to 0, so the output would look like this:
clock: 0 timer: 0
clock: 1 timer: 1
clock: 0 timer: 0
clock: 1 timer: 1
Code:
module controller(clock, reset, enable, lightN, lightS, lightE, lightW, NScolor, EWcolor);
input clock, reset, enable, lightN, lightS, lightE, lightW;
output NScolor, EWcolor;
wire clock, reset, enable, lightN, lightS, lightE, lightW;
reg NScolor, EWcolor;
reg timer;
always # (posedge clock)
begin: COUNT
$display("TIMER = %d", timer);
if (reset == 1) begin
$display("Resetting!");
NScolor<= 1;
EWcolor<= 0;
timer <= 0;
end
else if (enable == 1) begin
timer <= timer + 1;
if (timer == 7) begin
switchLights;
end
else if (timer >= 10) begin
timer <= 0;
switchLights;
end
end
end
task switchLights;
begin
if (NScolor == 0 && EWcolor == 2) begin
NScolor<= 1;
EWcolor<= 0;
end
else if (NScolor == 1) begin
NScolor<= 2;
EWcolor<= 0;
end
else if (NScolor == 2) begin
NScolor<= 0;
EWcolor<= 1;
end
if (EWcolor == 0 && NScolor == 2) begin
EWcolor<= 1;
NScolor<= 0;
end
else if (EWcolor == 1) begin
EWcolor<= 2;
NScolor<= 0;
end
else if (EWcolor == 2) begin
EWcolor<= 0;
NScolor<= 1;
end
end
endtask
endmodule
You have declared timer as:
reg timer;
which is a single-bit register. Hence, it only assumes values 0 an 1 in your simulation.
You may declare it as a multi-bit register, or declare it as an integer variable (assuming this code is anyway for simulation-purposes only, not for synthesis).
Note that you also have other issues in your code. For instance you declare EWColor as a single bit, but still attempt to assign it to 2, and compare it against 2.