I'm trying to simulate this module, but during the simulation all the variables 'x's. why ?
is there anything wrong with variable definition and use ?
I'm new at verilog, and I'm not sure if the usage that I did with the variable is right..
this is the module and the test-bench:
module viterbi_decoder(
clock , // Clock input of the design
reset , // active high, synchronous Reset input
in_vector ,
out_vector
);
//inputs
input clock;
input reset;
input [7:0]in_vector;
//outputs
output [7:0] out_vector;
reg [7:0] out_vector;
//local variables
integer index;
integer row00[4:0];
integer row01[4:0];
integer row10[4:0];
integer row11[4:0];
integer prev_row00[4:0];
integer prev_row01[4:0];
integer prev_row10[4:0];
integer prev_row11[4:0];
integer who;
integer from;
integer mini;
integer ham_dist_1;
integer ham_dist_2;
reg in[1:0];
always # (posedge clock)
begin
if (reset)
begin
//reset device
row00[0] <= 3;
row01[0] <= 3;
row10[0] <= 3;
row11[0] <= 3;
end
else
begin
row00[0] <= 3;
row01[0] <= 3;
row10[0] <= 3;
row11[0] <= 3;
for (index=0; index < 8; index = index + 2)
//mini([n-1,0],[n-1,1])
ham_dist_1 <= in_vector[index] ^ 0 + in_vector[index + 1] ^ 0 + row00[(index / 2)];
ham_dist_2 <= in_vector[index] ^ 1 + in_vector[index + 1] ^ 1 + row01[(index / 2)];
if (ham_dist_1 > ham_dist_2 )
begin
row00[index / 2 + 1] <= ham_dist_1;
prev_row00[index / 2 + 1] <= 0;
end
else
begin
row00[index / 2 + 1] <= ham_dist_2;
prev_row00[index / 2 + 1] <= 1;
end
ham_dist_1 <= in_vector[index] ^ 1 + in_vector[index + 1] ^ 0 + row10[(index / 2)];
ham_dist_2 <= in_vector[index] ^ 0 + in_vector[index + 1] ^ 1 + row11[(index / 2)];
if (ham_dist_1 > ham_dist_2 )
begin
row01[index / 2 + 1] <= ham_dist_1;
prev_row01[index / 2 + 1] <= 2;
end
else
begin
row01[index / 2 + 1] <= ham_dist_2;
prev_row01[index / 2 + 1] <= 3;
end
ham_dist_1 <= in_vector[index] ^ 0 + in_vector[index + 1] ^ 0 + row00[(index / 2)];
ham_dist_2 <= in_vector[index] ^ 1 + in_vector[index + 1] ^ 1 + row01[(index / 2)];
if (ham_dist_1 > ham_dist_2 )
begin
row10[index / 2 + 1] <= ham_dist_1;
prev_row10[index / 2 + 1] <= 0;
end
else
begin
row10[index / 2 + 1] <= ham_dist_2;
prev_row10[index / 2 + 1] <= 1;
end
ham_dist_1 <= in_vector[index] ^ 0 + in_vector[index + 1] ^ 1 + row10[(index / 2)];
ham_dist_2 <= in_vector[index] ^ 1 + in_vector[index + 1] ^ 0 + row11[(index / 2)];
if (ham_dist_1 > ham_dist_2 )
begin
row11[index / 2 + 1] <= ham_dist_1;
prev_row11[index / 2 + 1] <= 2;
end
else
begin
row11[index / 2 + 1] <= ham_dist_2;
prev_row11[index / 2 + 1] <= 3;
end
//trace back algorithm
who <= 00;
from <= prev_row00[4];
mini <= row00[4];
if (row01[4] < mini)
begin
who <= 01;
from <= prev_row01[4];
mini <= row01[4];
end
if (row10[4] < mini)
begin
who <= 10;
from <= prev_row10[4];
mini <= row10[4];
end
if (row11[4] < mini)
begin
who <= 11;
from <= prev_row11[4];
mini <= row11[4];
end
for (index=3; index > 0; index = index - 1 )
begin
if (who == 00 && from == 00)
begin
out_vector[(index + 1) * 2] <= 0;
out_vector[((index + 1) * 2 )- 1] <= 0;
who <= 00;
from <= prev_row00[index -1];
end
else if (who == 00 && from == 01)
begin
out_vector[(index + 1) * 2] <= 1;
out_vector[((index + 1) * 2 )- 1] <= 1;
who <= 01;
from <= prev_row01[index -1];
end
else if (who == 01 && from == 10)
begin
out_vector[(index + 1) * 2] <= 1;
out_vector[((index + 1) * 2 )- 1] <= 0;
who <= 10;
from <= prev_row10[index -1];
end
else if (who == 01 && from == 11)
begin
out_vector[(index + 1) * 2] <= 0;
out_vector[((index + 1) * 2 )- 1] <= 1;
who <= 11;
from <= prev_row11[index -1];
end
else if (who == 10 && from == 00)
begin
out_vector[(index + 1) * 2] <= 1;
out_vector[((index + 1) * 2 )- 1] <= 1;
who <= 00;
from <= prev_row00[index -1];
end
else if (who == 10 && from == 01)
begin
out_vector[(index + 1) * 2] <= 0;
out_vector[((index + 1) * 2 )- 1] <= 0;
who <= 01;
from <= prev_row01[index -1];
end
else if (who == 11 && from == 10)
begin
out_vector[(index + 1) * 2] <= 0;
out_vector[((index + 1) * 2 )- 1] <= 1;
who <= 10;
from <= prev_row10[index -1];
end
else if (who == 11 && from == 11)
begin
out_vector[(index + 1) * 2] <= 1;
out_vector[((index + 1) * 2 )- 1] <= 0;
who <= 11;
from <= prev_row11[index -1];
end
end
end
end
endmodule
`timescale 1ns /1ps
module Testbench;
reg clock_t;
reg reset_t;
reg [7:0] in_vector_t;
wire [7:0] out_vector_t;
viterbi_decoder viterbi_1(.clock(clock_t), .reset(reset_t), .in_vector(in_vector_t), .out_vector(out_vector_t));
initial begin
clock_t = 0;
reset_t = 0;
end
always #10000 clock_t = ~clock_t;
always#(posedge clock_t)
begin
//case 0
in_vector_t <= 00110101; // <= 1; reset_t <= 0;
#5 $display("Result_t = %b", out_vector_t);
//case 1
in_vector_t <= 00001111; //clock_t <= 1; reset_t <= 0;
#5 $display("Result_t = %b", out_vector_t);
//case 2
in_vector_t <= 00010101; //clock_t <= 1; reset_t <= 0;
#5 $display("Result_t = %b", out_vector_t);
//case 3
in_vector_t <= 00101100; //clock_t <= 1; reset_t <= 0;
#5 $display("Result_t = %b", out_vector_t);
//case 4
in_vector_t <= 00000000; //clock_t <= 1; reset_t <= 0;
#5 $display("Result_t = %b", out_vector_t);
end
endmodule
First, your test bench needs improvements. The clock is very slow and the dut will only see in_vector_t <= 00000000; one the next of any clock edge. I suggest you change your in_vector_t in relation to the clock edge. Also since you have a free running clock, you'll need to end the simulation with a $finish. Example:
always #5 clock_t = ~clock_t;
initial begin
$monitor("Result_t = %b", out_vector_t);
#(posedge clock_t) in_vector_t <= 8'b00110101; //case 0
#(posedge clock_t) in_vector_t <= 8'b00001111; //case 1
#(posedge clock_t) in_vector_t <= 8'b00010101; //case 2
#(posedge clock_t) in_vector_t <= 8'b00101100; //case 3
#(posedge clock_t) in_vector_t <= 8'b00000000; //case 4
#(posedge clock_t);
#5 $finish; // end simulation
end
In your design, there are may place where you set/compare two bit values to 10 or 11. These values are in decimal ten and eleven. You need to specify the width and base type, I.E. 2'b10 or 2'b11. The same is true for your test bench; 00001111 is decimal one thousand one hundred and eleven, 8'b00001111 is decimal fifteen.
You are using non-blocking (<=) inside a clocked always block. This is correct. The problem is your code appears to be depended on recently updated values. With non-blocking assignment, the register does not get new value until the end of the time step. Anything sampling/comparing the value will see the old value until then. In this case you need to split the block into two always blocks: one synchronous using non-blocking (<=) and one combinational using blocking (=). Not knowing your full intended logic I'll just give you the template to get started:
always #* begin : comb_logic__calc_next
// defaults (constants or flops)
next_example1 = 8'h00; // constant
next_example2 = example2;// flop
/* algorithms for here
.... made-up example * /
for (index = 0; index<8; index=index+1) begin
if (input_bus[index]==1'b1) next_example1[index] = 1'b1;
else next_example2[index] = ~next_example2[index];
if (next_example1[index]==example[7-index]) begin
next_example2 = {next_example2[6:0],next_example2[7]};
end
end
end
always #(posedge clock) begin : synchronous_logic__assign_flops
if (reset) begin
// constants only
example1 <= 8'h00;
example2 <= 8'h00;
end
else begin
// assign flops to next value
example1 <= next_example1;
example2 <= next_example2;
end
end
Beyond that you will need to run simulation with a waveform dumping.
Related
I am getting this error when synthesizing my code, but I don't know what it means. It reads:
Error- net "Count[0] or a directly connected net is driven by more
than one source and not all drivers are three state.
It says the same errors for vectors count[0] - count[4] as well as for my load and k values. The code is my representation of an SPI Master. The SPI master has an instantiation of a shift register that is used to push out information.
module SPIMaster(output reg SCLK, CS, MOSI,
input EN, CLK, MISO,
input [7:0] m_data);
wire master_out;
reg [4:0] count;
wire [7:0] data_buff;
wire SCLK1;
reg master_in, c_sw, k, state, load;
shiftReg register_out (master_out, data_buff, load, (~SCLK), master_in, m_data);
assign SCLK1 = (~c_sw) | CLK;
always#(posedge CLK) begin
if(state) begin
if (k == 1) begin
state <= 0;
c_sw <= 0;
CS <= 1;
count <= 0;
k <= 0;
load <= 0;
end
else begin
state <= 1;
c_sw <= 1;
CS <= 0;
end
end
else begin
if (EN == 1) begin
state <= 1;
c_sw <= 1;
CS <= 0;
count <= 0;
k <= 0;
load <= 1;
end
else begin
state <= 0;
c_sw <= 0;
CS <= 1;
count <= 0;
k <= 0;
load <= 0;
end
end
end
always#(posedge SCLK1) begin
if (CS == 0) master_in <= MISO;
if (count == 7) begin
load <= 0;
end
else if (count == 15)begin
load <= 0;
end
else begin
load <= 1;
end
end
always#(negedge SCLK1) begin
if (count == 23) k <= 1;
else k <= 0;
if (CS == 0) begin
MOSI <= master_out;
count <= count + 1;
end
end
endmodule
Your code does not adhere to good synthesis coding practices because you assign to count from 2 different always blocks and those 2 blocks are triggered by different clock signals. You should make all assignments to count from the same always block.
The same is true of load and k.
I want to make a parameterized FIR filter in verilog on xilinix. This is my code:
module FIRFilter(xInput, clock, reset, filterCoeff, yOutput);
parameter inputBits = 8, lengthOfFilter = 4, coeffBitLength = 8, lengthOfCoeff = lengthOfFilter + 1, outputBitWdth = 2 * inputBits;
input [(coeffBitLength * lengthOfCoeff) - 1 : 0] filterCoeff;
input clock, reset;
input [inputBits - 1 : 0] xInput;
reg [outputBitWdth - 1 : 0] addWires [lengthOfFilter - 1 : 0];
output reg [outputBitWdth - 1 : 0] yOutput;
reg [inputBits - 1 : 0] registers [lengthOfFilter - 1 : 0];
integer i, j;
always # (posedge clock, posedge reset)
begin
if(reset)
begin
for(i = 0; i < lengthOfFilter; i = i + 1)
begin
registers[i] <= 0;
end
end
else
begin
registers[0] <= xInput;
for(i = 1; i < lengthOfFilter; i = i + 1)
begin
registers[i] <= registers[i - 1];
end
end
end
always # (posedge clock)
begin
addWires[0] = filterCoeff[(lengthOfFilter * coeffBitLength) - 1 : (lengthOfFilter - 1) * coeffBitLength] * xInput;
for(j = 1; j < lengthOfFilter; j = j + 1)
begin
addWires[j] = (filterCoeff[((j + 1) * coeffBitLength) - 1 : j * coeffBitLength] * registers[j - 1]) + addWires[j - 1];
end
yOutput = (filterCoeff[coeffBitLength - 1 : 0] * registers[lengthOfFilter - 1]) + addWires[lengthOfFilter - 1];
end
endmodule
But I keep getting this error
ERROR:HDLCompilers:109 - "FIRFilter.v" line 33 Most significant bit operand in part-select of vector wire 'filterCoeff' is illegal
ERROR:HDLCompilers:110 - "FIRFilter.v" line 33 Least significant bit operand in part-select of vector wire 'filterCoeff' is illegal
ERROR:HDLCompilers:45 - "FIRFilter.v" line 33 Illegal right hand side of blocking assignment
I searched online for the solution but haven't got any satisfactory answer.
Can someone help me with the this?
Verilog does not allow part selects signal[msb:lsb] where msb and lsb are not constants. You can use another construct called an indexed part select where you specify a constant width, but a variable offset signal[offset+:width]
addWires[0] = filterCoeff[(lengthOfFilter * coeffBitLength) +:coeffBitLength] * xInput;
The following code is compiled and is working in parallel, Please help me to make these code work sequentially, i.e after stage1 counter should reset itself and starts from 0 for the stage2. The following codes has Module1- stage1 and module2-stage2. This is the process flow in which one stage occur after completion of another. For example when stage 1 is done then counter reset itself and then stage 2 starts with count zero.Here stage 1 module has counter that counts till 18 and stage 2 counter counts 8.
module stage1(
input Clk, //50 Hz clock
input x0,
input reset,
output reg y0,y1,y2,y3,y5,y7,y10,y15,
output reg stage1_done
);
reg [15:0] counter = 0;
parameter F = 50;
always# (posedge Clk or posedge reset)
if(reset) begin
counter <= 0;
{y0,y1,y2,y3,y5,y7,y10,y15} <= 8'b00000000;
stage1_done <= 0;
end else begin
if(x0 == 1) begin
if(counter == 18*F)
stage1_done <= 1;
else begin
counter <= counter + 1;
stage1_done <= 0;
end
if(counter >= 1*F && counter < 10*F)
y0 <= 1;
else
y0 <= 0;
if(counter >= 1*F && counter < 17*F)
y1 <= 1;
else
y1 <= 0;
if(counter >= 1*F && counter < 9*F)
y2 <= 1;
else
y2 <= 0;
if(counter >= 11*F && counter < 16*F)
y3 <= 1;
else
y3 <= 0;
if(counter >= 1*F && counter < 18*F)
y5 <= 1;
else
y5 <= 0;
if(counter >= 1*F && counter < 5*F)
y7 <= 1;
else
y7 <= 0;
if(counter >= 1*F && counter < 5*F)
y10 <= 1;
else
y10 <= 0;
if((counter >= 2*F && counter < 9*F) || (counter >= 13*F && counter < 17*F))
y15 <= 1;
else
y15 <= 0;
end
end
endmodule
//Module for stage 2;
module stage2(
input x0,
input Clk, //50 Hz clock
input reset,
output reg y1,y3,y5,
output reg stage2_done
);
reg [15:0] counter = 0;
parameter F = 50;
always# (posedge Clk or posedge reset)
if(reset) begin
counter <= 0;
{y1,y3,y5} <= 3'b000;
stage2_done <= 0;
end
else begin if(x0 == 1) begin
if(counter == 8*F)
stage2_done <= 1;
else begin
counter <= counter + 1;
stage2_done <= 0;
end
if(counter >= 1*F && counter < 8*F)
y1 <= 1;
else
y1 <= 0;
if(counter >= 1*F && counter < 8*F)
y3 <= 1;
else
y3 <= 0;
if(counter >= 1*F && counter < 8*F)
y5 <= 1;
else
y5 <= 0;
end
end
endmodule
If you want a counter from stage2 module to start counting after counter from stage1 finishes, then you have to "inform" it that the other one finished counting. In your case you can use stage1_done signal and feed it to stage2 module. Use this signal as a condition for counter to start counting initially. Also, shouldn't you reset the counter from stage1 back to 0 when you assert stage1_done?
Think of it as a state machine. with 2 or 3 states, i.e. reset, stage1, stage2. You need to think over the conditions which would move from one stage to another. You provided one condition: stage1 counter overflow has to go from stage1 to stage2. There are definitely few question: what happens to stage1 while stage2 is running, what what happens when stage 2 is finished. What happens during reset?
So, I suggest that you create yest another module to implement the state machine logic:
module control(clk, ...);
enum { reset, stage1, stage2} state, next_state;
always_ff #( posedge clk)
case (state)
reset:
if (!resetSig) next_state <= stage1;
else if (resetSig) next_state <= reset;
stage1:
if (stage1Done) next)state <= stage2;
...
endcase
assign state = next_state;
Now in every stage you just use state as an enable condition.
module stage1(clk, state, stageDone, ...)
always_ff
if (state == reset)
do reset
else if (state == stage1)
do stage1
assign stageDone = counter == max_value;
and so on. Yes, you will need to pass extra ports for the state machine controls, but you will make your code much more manageable and readable and confirm to industry practices.
I'm using Verilog-2001 with Vivado 2015.4. There is my code:
parameter SHIFT = 16;
wire integrators_reset;
reg [INTEGRATOR_WIDTH - 1 : 0] sum_mem [SHIFT - 1 : 0];
reg [SHIFT - 1 : 0] full_mem;
wire [SHIFT - 1 : 0] equal;
genvar i;
generate
for(i = 0; i < SHIFT; i = i + 1) begin
always #(negedge equal[i]) begin
if(integrators_reset) begin
sum_mem[i] <= 0;
full_mem[i] <= 0;
end
else begin
if(sum_mem[i] == INTEGRATOR_MAX)
full_mem[i] <= 1;
else
sum_mem[i] <= sum_mem[i] + 1;
end
end
end
endgenerate
There is the error:
ERROR: [DRC 23-20] Rule violation (MDRV-1) Multiple Driver Nets- Net sum_mem[0][0] has multiple drivers
If i'm not using "generate" all is fine. For example:
always #(negedge equal[0]) begin
if(integrators_reset) begin
sum_mem[0] <= 0;
full_mem[0] <= 0;
end
else begin
if(sum_mem[0] == INTEGRATOR_MAX)
full_mem[0] <= 1;
else
sum_mem[0] <= sum_mem[0] + 1;
end
end
And there is not errors during implementation.
This seems like a tool limitation. You should be able to assign different fixed elements of an unpacked array from different always blocks. One workaround would be to move the declaration of sum_mem into the generate block.
for(I = 0; I < SHIFT; i = i + 1) begin : block_name
reg [INTEGRATOR_WIDTH - 1 : 0] sum_mem;
always #(negedge equal[I]) begin
if(integrators_reset) begin
sum_mem <= 0;
full_mem[i] <= 0;
end
else begin
if(sum_mem[i] == INTEGRATOR_MAX)
full_mem[i] <= 1;
else
sum_mem <= sum_mem + 1;
end
end
end
Now you have block_name[0].sum_mem, block_name[1].sum_mem, but you can not access block_name with a variable index.
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