Why is my register not updating in the testbench? - verilog

I have a register that I increment by a different value base on the different inputs, When I run a test bench to check it, the value does not increment. Not sure why. Attached is my code and the TB, as well as a screen shot of the simulation:
`timescale 1ns / 1ps
module TEMP_P1(
input clk,
input reset,
input inquarter,
input indime,
input innickle,
input inbev1,
input inbev2,
input inbev3,
output reg [3:0] outquarter,
output reg [3:0] outdime,
output reg [3:0] outnickle,
output reg [1:0] outbev1,
output reg [1:0] outbev2,
output reg [1:0] outbev3
);
reg [31:0] total;
reg [3:0] quarter_count;
reg [3:0] dime_count;
reg [3:0] nickle_count;
always#(clk)begin
if(reset)begin
total = 0;
quarter_count = 0;
dime_count = 0;
nickle_count = 0;
end else begin
if (inquarter) begin
quarter_count = quarter_count + 1;
total = total + 25;
end
if (indime) begin
dime_count = dime_count + 1;
total = total + 10;
end
if (innickle) begin
nickle_count = nickle_count + 1;
total = total + 5;
end
if ((inbev1 === 1) && ( total >= 100)) begin
outbev1 = 1;
total = total - 100;
end
if ((inbev2 == 1) && ( total >= 120)) begin
outbev2 = 1;
total = total - 120;
end
if ((inbev3 == 1) && ( total >= 115)) begin
outbev3 = 1;
total = total - 115;
end
if (total >= 25) begin
outquarter = 1;
outdime = 0;
outnickle = 0;
total = total - 25;
end
if ((total >= 10) && (total < 25)) begin
outquarter = 0;
outdime = 1;
outnickle = 0;
total = total - 10;
end
if ((total >= 5) && (total < 10)) begin
outquarter = 0;
outdime = 0;
outnickle = 1;
total = total - 5;
end
end
end
endmodule
`timescale 1ns / 1ps
module TEMP_P1_TB(
);
reg clk;
reg reset;
reg inquarter;
reg indime;
reg innickle;
reg inbev1;
reg inbev2;
reg inbev3;
wire [3:0] outquarter;
wire [3:0] outdime;
wire [3:0] outnickle;
wire [1:0] outbev1;
wire [1:0] outbev2;
wire [1:0] outbev3;
TEMP_P1 UUT(.clk(clk), .reset(reset), .inquarter(inquarter), .indime(indime), .innickle(innickle), .inbev1(inbev1), .inbev2(inbev2), .inbev3(inbev3),
.outquarter(outquarter), .outdime(outdime), .outnickle(outnickle), .outbev1(outbev1), .outbev2(outbev2), .outbev3(outbev3));
initial begin
clk = 0;
reset = 0;
inquarter = 0;
indime = 0;
innickle = 0;
inbev1 = 0;
inbev2 = 0;
inbev3 = 0;
#10;
reset = 1;
#1
reset = 0;
#1
inquarter = 1;
#1;
inquarter = 0;
#1;
inquarter = 1;
#1;
inquarter = 0;
#1;
inquarter = 1;
#1;
inquarter = 0;
#1;
inquarter = 1;
#1;
inquarter = 0;
#1;
inquarter = 1;
#1;
inquarter = 0;
#1;
inbev1 = 1;
#1;
inbev1 = 0;
#1;
end
always begin
#1 clk = ~clk;
end
endmodule
I have tried changing blocking v. nonblocking assignments.

One major problem with your code is that you have Verilog simulation race conditions.
To model registers, you need to use these coding styles:
Signal changes triggered off only one edge of the clock (positive, for example):
#(posedge clk)
Nonblocking assignments: <=
This style must be used in both the design and testbench.
For the design, refer to these simple code examples.
In the testbench, you should replace all of the # delays, except for the clk signal, with #(posedge clk). This assures that the inputs will be synchronous to the clock. clk should use a blocking assignment; so there is no need to change your code there.
Also, the testbench code can be easier to understand if you use loops. I use repeat loops. Here are all the changes to both the design and testbench:
`timescale 1ns / 1ps
module TEMP_P1(
input clk,
input reset,
input inquarter,
input indime,
input innickle,
input inbev1,
input inbev2,
input inbev3,
output reg [3:0] outquarter,
output reg [3:0] outdime,
output reg [3:0] outnickle,
output reg [1:0] outbev1,
output reg [1:0] outbev2,
output reg [1:0] outbev3
);
reg [31:0] total;
reg [3:0] quarter_count;
reg [3:0] dime_count;
reg [3:0] nickle_count;
always #(posedge clk) begin
if (reset) begin
total <= 0;
quarter_count <= 0;
dime_count <= 0;
nickle_count <= 0;
end else begin
if (inquarter) begin
quarter_count <= quarter_count + 1;
total <= total + 25;
end
if (indime) begin
dime_count <= dime_count + 1;
total <= total + 10;
end
if (innickle) begin
nickle_count <= nickle_count + 1;
total <= total + 5;
end
if ((inbev1 === 1) && ( total >= 100)) begin
outbev1 <= 1;
total <= total - 100;
end
if ((inbev2 == 1) && ( total >= 120)) begin
outbev2 <= 1;
total <= total - 120;
end
if ((inbev3 == 1) && ( total >= 115)) begin
outbev3 <= 1;
total <= total - 115;
end
if (total >= 25) begin
outquarter <= 1;
outdime <= 0;
outnickle <= 0;
total <= total - 25;
end
if ((total >= 10) && (total < 25)) begin
outquarter <= 0;
outdime <= 1;
outnickle <= 0;
total <= total - 10;
end
if ((total >= 5) && (total < 10)) begin
outquarter <= 0;
outdime <= 0;
outnickle <= 1;
total <= total - 5;
end
end
end
endmodule
`timescale 1ns / 1ps
module TEMP_P1_TB;
reg clk;
reg reset;
reg inquarter;
reg indime;
reg innickle;
reg inbev1;
reg inbev2;
reg inbev3;
wire [3:0] outquarter;
wire [3:0] outdime;
wire [3:0] outnickle;
wire [1:0] outbev1;
wire [1:0] outbev2;
wire [1:0] outbev3;
TEMP_P1 UUT(.clk(clk), .reset(reset), .inquarter(inquarter), .indime(indime), .innickle(innickle), .inbev1(inbev1), .inbev2(inbev2), .inbev3(inbev3),
.outquarter(outquarter), .outdime(outdime), .outnickle(outnickle), .outbev1(outbev1), .outbev2(outbev2), .outbev3(outbev3));
initial begin
clk <= 0;
reset <= 0;
inquarter <= 0;
indime <= 0;
innickle <= 0;
inbev1 <= 0;
inbev2 <= 0;
inbev3 <= 0;
repeat (5) #(posedge clk);
reset <= 1;
repeat (1) #(posedge clk);
reset <= 0;
repeat (5) begin
repeat (1) #(posedge clk);
inquarter <= 1;
repeat (1) #(posedge clk);
inquarter <= 0;
end
repeat (1) #(posedge clk);
inbev1 <= 1;
repeat (1) #(posedge clk);
inbev1 <= 0;
repeat (10) #(posedge clk);
$finish;
end
always begin
#1 clk = ~clk;
end
endmodule
The above code fixes the timing problems (race conditions).
However, you also have problems with your logic since the total gets cleared after each quarter input, as you can see in the waves below:
If that is not your intended behavior, I recommend you spend more time looking at your internal waveforms. If you still have problems, you can ask a new question.

In the UUT, add the keyword posedge to # statement, like this:
always#(posedge clk)begin
In the testbench, assert reset at the beginning, release it a couple of clocks later, don't assert it again. It was asserted for 1/2 of a clock some time after the test was started. Best practice is to assert it at the unless there is a good reason not to do so.
initial begin
reset = 1;
#5 reset = 0;
Use non-blocking assignments everywhere in the UUT # statement for the clocked process like this (I did not fix them all, you should). Non-blocking assignments in a synchronous process is the correct way model registers:
always#(posedge clk)begin
if(reset)begin
total <= 0;
quarter_count <= 0;
dime_count <= 0;
nickle_count <= 0;
end else begin
if (inquarter) begin
quarter_count <= quarter_count + 1;
total <= total + 25;
In the testbench, hold the inputs (example inquarter) for at least 1 clock cycle so that they are able to be sampled at a logic 1, at the clock edge. inquarter is 1/2 a clock cycle wide. The clk period is #2, so if you change an input every #1, that is making a skinny pulse that would be easy for the DUT to miss. I did not fix these in the testbench you should. Register quarter_count is catching the input at 1 almost by accident in my simulation.
Make these changes and the registers start behaving as registers.
The waves looks like this for me on edaplayground:
Another issue is that you have an always block in the testbench
always begin
#1 clk = ~clk;
however there is no $finish or $stop anywhere in your code. The simulation will run forever until you click some sort of kill/stop in the simulation GUI, or kill the process from the command line. The solution to this is to add a
$finish;
at the end of the testbench main initial block. Now the simulation will compile, elaborate, run, and stop relatively quickly. My eda playground simulation run of your post takes about 15 seconds total.

Related

UART Transmit and receive data does not start (Vivado)

I can't figure out why is it that when I set the clock frequency from 50MHz to 100MHz, by changing the clk period to 5 in the testbench, my output transmit and receive data stays at 0. Can anyone enlighten me on this? I need my clock frequency to be 100MHz. Your help will be much appreciated.
Testbench
`timescale 1ns / 1ps
module uart_tx_test();
parameter periodCLK_2 = 5;
parameter perioddump = 10;
parameter delay = 1;
parameter delay_in = 2;
reg CLK_TB = 0 ;
reg RSTN ;
reg [7:0] data = 0;
reg clk = 0;
reg enable = 0;
wire tx_busy;
wire rdy;
wire [7:0] rxdata;
wire loopback;
reg rdy_clr = 0;
uart test_uart(.din(data),
.wr_en(enable),
.clk_50m(clk),
.tx(loopback),
.tx_busy(tx_busy),
.rx(loopback),
.rdy(rdy),
.rdy_clr(rdy_clr),
.dout(rxdata));
initial begin
// $dumpfile("uart.vcd");
$dumpvars(0, uart_tx_test);
enable <= 1'b1;
#2 enable <= 1'b0;
end
always begin
#5 clk = ~clk; //I set period to 5; period was 1 previously.
end
always #(posedge rdy) begin
#2 rdy_clr <= 1;
#2 rdy_clr <= 0;
if (rxdata != data) begin
$display("FAIL: rx data %x does not match tx %x", rxdata, data);
$finish;
end else begin
if (rxdata == 8'hff) begin
$display("SUCCESS: all bytes verified");
$finish;
end
data <= data + 1'b1;
enable <= 1'b1;
#2 enable <= 1'b0;
end
end
endmodule
Design Sources
module uart(
input wire [7:0] din,
input wire wr_en,
input wire clk_50m,
output wire tx,
output wire tx_busy,
input wire rx,
input wire rdy_clr,
output wire rdy,
output wire [7:0] dout
);
wire rxclk_en, txclk_en;
baud_rate_gen uart_baud(
.clk_50m(clk_50m),
.rxclk_en(rxclk_en),
.txclk_en(txclk_en)
);
transmitter uart_tx(
.tx(tx),
.din(din),
.clk_50m(clk_50m),
.clken(txclk_en),
.wr_en(wr_en),
.tx_busy(tx_busy)
);
receiver uart_rx(
.rx(rx),
.data(dout),
.clk_50m(clk_50m),
.clken(rxclk_en),
.rdy(rdy),
.rdy_clr(rdy_clr)
);
endmodule
/*
* Hacky baud rate generator to divide a 50MHz clock into a 9600 baud
* rx/tx pair where the rx clcken oversamples by 16x.
*/
module baud_rate_gen(input wire clk_50m,
output wire rxclk_en,
output wire txclk_en);
parameter RX_ACC_MAX = 100000000 / (9600 * 16);
parameter TX_ACC_MAX = 100000000 / 9600;
parameter RX_ACC_WIDTH = $clog2(RX_ACC_MAX);
parameter TX_ACC_WIDTH = $clog2(TX_ACC_MAX);
reg [RX_ACC_WIDTH - 1:0] rx_acc = 0;
reg [TX_ACC_WIDTH - 1:0] tx_acc = 0;
assign rxclk_en = (rx_acc == 5'd0);
assign txclk_en = (tx_acc == 9'd0);
always #(posedge clk_50m) begin
if (rx_acc == RX_ACC_MAX[RX_ACC_WIDTH - 1:0])
rx_acc <= 0;
else
rx_acc <= rx_acc + 5'b1;
end
always #(posedge clk_50m) begin
if (tx_acc == TX_ACC_MAX[TX_ACC_WIDTH - 1:0])
tx_acc <= 0;
else
tx_acc <= tx_acc + 9'b1;
end
endmodule
module transmitter(
input wire [7:0] din,
input wire wr_en,
input wire clk_50m,
input wire clken,
output reg tx,
output wire tx_busy
);
initial begin
tx = 1'b1;
end
parameter STATE_IDLE = 2'b00;
parameter STATE_START = 2'b01;
parameter STATE_DATA = 2'b10;
parameter STATE_STOP = 2'b11;
reg [7:0] data = 8'h00;
reg [2:0] bitpos = 3'h0;
reg [1:0] state = STATE_IDLE;
always #(posedge clk_50m) begin
case (state)
STATE_IDLE: begin
if (wr_en) begin
state <= STATE_START;
data <= din;
bitpos <= 3'h0;
end
end
STATE_START: begin
if (clken) begin
tx <= 1'b0;
state <= STATE_DATA;
end
end
STATE_DATA: begin
if (clken) begin
if (bitpos == 3'h7)
state <= STATE_STOP;
else
bitpos <= bitpos + 3'h1;
tx <= data[bitpos];
end
end
STATE_STOP: begin
if (clken) begin
tx <= 1'b1;
state <= STATE_IDLE;
end
end
default: begin
tx <= 1'b1;
state <= STATE_IDLE;
end
endcase
end
assign tx_busy = (state != STATE_IDLE);
endmodule
module receiver(
input wire rx,
input wire rdy_clr,
input wire clk_50m,
input wire clken,
output reg rdy,
output reg [7:0] data
);
initial begin
rdy = 0;
data = 8'b0;
end
parameter RX_STATE_START = 2'b00;
parameter RX_STATE_DATA = 2'b01;
parameter RX_STATE_STOP = 2'b10;
reg [1:0] state = RX_STATE_START;
reg [3:0] sample = 0;
reg [3:0] bitpos = 0;
reg [7:0] scratch = 8'b0;
always #(posedge clk_50m) begin
if (rdy_clr)
rdy <= 0;
if (clken) begin
case (state)
RX_STATE_START: begin
/*
* Start counting from the first low sample, once we've
* sampled a full bit, start collecting data bits.
*/
if (!rx || sample != 0)
sample <= sample + 4'b1;
if (sample == 15) begin
state <= RX_STATE_DATA;
bitpos <= 0;
sample <= 0;
scratch <= 0;
end
end
RX_STATE_DATA: begin
sample <= sample + 4'b1;
if (sample == 4'h8) begin
scratch[bitpos[2:0]] <= rx;
bitpos <= bitpos + 4'b1;
end
if (bitpos == 8 && sample == 15)
state <= RX_STATE_STOP;
end
RX_STATE_STOP: begin
/*
* The baud clock may not be running at exactly the
* same rate as the transmitter. If we thing that
* we're at least half way into the stop bit, allow
* transition into handling the next start bit.
*/
if (sample == 15 || (sample >= 8 && !rx)) begin
state <= RX_STATE_START;
data <= scratch;
rdy <= 1'b1;
sample <= 0;
end else begin
sample <= sample + 4'b1;
end
end
default: begin
state <= RX_STATE_START;
end
endcase
end
end
endmodule
You need to scale all your other delays accordingly. Change all your #2 to #10, then you will see the SUCCESS: all bytes verified message.
With your original clock delay of #1, your other input signal pulses (enable and rdy_clr) were wide enough for your uart design module to sample properly. For example, on the 1st posedge of clk, your design properly sampled the enable input as 1, which started the TX state machine.
You increased the clock period by a factor of 5 when you changed the delay from #1 to #5. However, your enable pulse stayed the same width as before, which means that the design sampled enable as 0, not 1. So your TX state machine stayed in the IDLE state. By changing the enable delay from #2 to #10, you are able to properly sample enable as 1.
You can easily prove this to yourself by dumping a VCD file, and viewing the waveforms inside the design.
You could replace the numeric delays with a parameter to make it easier to change to different frequencies.
Note: You stated the clk delay was originally #1. This gives the clk signal a period of 2ns, which is 500MHz, not 50MHz.

Why doesn't the up/down counter count down?

I was doing the Logic Design assignment, and I found some problems I can't solve.
I need to design a 6-bit counter, and this counter needs to count with two functions, for up and down respectively.
I have done the up part and down part, but when I run the simulation, the counting down part doesn't work correctly.
The function for counting down: the next a = a - 2^n, where n = 0, 1, 2, 3... eg. a1 = 63, a2 = 63 - 1 = 62, a3 = 62 - 2 = 60, a4 = 56...
But the simulation with my program, it becomes 63, 62, 61(63 - 2), 59(63 - 4)...
By the way, this assignment has a reset feature.
However, my program won't keep counting after being reset.
It should back to zero and continue counting theoretically.
The following is my code:
`timescale 1ns/100ps
module lab2_1(
input clk,
input rst,
output reg [5:0] out
);
reg [5:0] cnt;
wire [5:0] cnt_next;
reg updown;
wire [5:0] out_next;
initial begin
out = 0;
cnt = 1;
updown = 1;
end
assign cnt_next = (out == 6'b111111) ? 0 : cnt + 1;
assign out_next = out - (2**cnt);
always #(*) begin
if(out == 6'b111111)begin
updown = 0;
end
if(out == 6'b000000)begin
updown = 1;
end
if(rst == 1) begin
out = 0;
updown = 1;
cnt = 0;
end
end
always #(posedge clk, posedge rst) begin
if(updown == 1)begin
if(out > cnt)begin
out <= out - cnt;
end
else
out <= out + cnt;
end
else begin
out <= out_next;
end
cnt <= cnt_next;
end
endmodule
The testbench just monitors the output and drives the inpupts.
`timescale 1ns/100ps
module lab2_1_t;
wire [5:0] out;
reg clk;
reg rst;
lab2_1 v(clk, rst, out);
initial begin
clk = 0;
rst = 0;
$monitor($time,":clk = %b, rst = %b, out = %d", clk, rst, out);
end
always #10 clk = ~clk;
always #10000 rst = ~rst;
endmodule
You should not make assignments to the same signal (such as cnt) from multiple blocks. You can assign to cnt from a single always block. I don't think you need both out and cnt.
Here is a simplified version which automatically switches between up and down:
module lab2_1(
input clk,
input rst,
output reg [5:0] cnt
);
reg updown;
always #(posedge clk, posedge rst) begin
if (rst) begin
updown <= 1;
end else if (cnt == 6'b111110) begin
updown <= 0;
end else if (cnt == 6'b000001) begin
updown <= 1;
end
end
always #(posedge clk, posedge rst) begin
if (rst) begin
cnt <= 0;
end else if (updown) begin
cnt <= cnt + 1;
end else begin
cnt <= cnt - 1;
end
end
endmodule
The code shows a more typical use of the reset signal in the sequential always block. See also for more examples.
Here is a modified testbench where the reset is asserted at time 0, then released after a couple clock cycles. At the end, it asserts reset again so you can see that the counter goes to 0.
module lab2_1_t;
wire [5:0] out;
reg clk;
reg rst;
lab2_1 v(clk, rst, out);
initial begin
$monitor($time,":clk = %b, rst = %b, out = %d", clk, rst, out);
clk = 0;
rst = 1;
#40 rst = 0;
#10000 rst = 1;
#1000 $finish;
end
always #10 clk = ~clk;
endmodule

verilog code of FIFO (first in first out) is not showing the proper result?

I wanted to design a FIFO having a certain depth and width. The Verilog code of the FIFO is written in Vivado 2017.4. The code is able to to read the input data, but it is only showing XX as the output. The design sources and test bench of the FIFO is given below. Help me to find the problem.
module fifo #(parameter WIDTH=8, parameter DEPTH=8) (
input wire [WIDTH-1:0] data_in,
output reg [WIDTH-1:0] data_out,
output reg data_valid,
input wire reset,
input wire clk
);
function integer clog2(input reg [32-1:0] value);
begin
value = value-1;
for (clog2=0; value>0; clog2=clog2+1)
value = value>>1;
end
endfunction
reg [WIDTH-1:0] data [DEPTH-1:0];
reg [clog2(DEPTH)-1:0] write_pointer;
reg [clog2(DEPTH)-1:0] read_pointer;
always #(posedge clk) begin
if (reset == 1'b0) begin
write_pointer <= 0;
read_pointer <= 1;
data_valid <= 0;
end else begin
if (write_pointer == DEPTH-1) write_pointer <= 0;
else write_pointer <= write_pointer + 1;
if (read_pointer == DEPTH-1) read_pointer <= 0;
else read_pointer <= read_pointer + 1;
data[write_pointer] <= data_in;
data_out <= data[read_pointer];
end
if (read_pointer == 0) data_valid <= 1'b1;
end
endmodule
test bench
`timescale 1ns / 1ps
module fifo_tb;
parameter WIDTH = 16;
parameter DEPTH = 8;
reg reset;
reg clk;
reg [(WIDTH-1):0] data_in;
wire [(WIDTH-1):0] data_out;
wire data_valid;
fifo #(WIDTH,DEPTH) U0(data_in,data_out,data_valid,reset,clk);
initial begin
clk = 0;
reset = 1;
#1 reset = 0;
#1 reset = 1;
end
// Create clock
always
#5 clk = ~clk;
reg signed [15:0] rom_memory [4096-1:0];
integer i=0;
initial
begin
$readmemh("C:\\Users\\input_7_zz.txt",rom_memory);
end
always#(posedge clk )
begin
if(~reset)
begin
data_in <= 0;
end
else
begin
data_in <= rom_memory[i];
i <= i+ 1;
end
end
endmodule
In your test bench code the clock is changed every 5 ticks:
// Create clock
always
#5 clk = ~clk;
The reset in RTL uses posedge of this clock:
always #(posedge clk) begin
if (reset == 1'b0) begin
write_pointer <= 0;
read_pointer <= 1;
data_valid <= 0;
So, the reset action could happen only if the posedge clk could be detected during the reset period. In other words you have a synchronous reset.
Nevertheless, in your test bench code your reset lasts only a single tick:
initial begin
clk = 0;
reset = 1;
#1 reset = 0;
#1 reset = 1; // << one tick after the reset was asserted.
end
Potentially you have 2 possible solutions.
1) keep the synchronous reset, but make sure that the posedge of the clk could be detected during the reset. So, make it bigger than a clock cycle (or at least half clock cycle if you are sure when it comes). Something like 5 should work in your case. Make it 10 or more to be sure for arbitrary starting points.
initial begin
clk = 0;
reset = 1;
#1 reset = 0;
#5 reset = 1; // << 5 tick after the reset was asserted.
The reset above will last from time 1 to time 6. The first posegde will happen at time 5. So, it should be sufficient in your case.
2) you can use an asynchronous reset in RTL which will look as the following:
always #(posedge clk or reset) begin
if (reset == 1'b0) begin
write_pointer <= 0;
read_pointer <= 1;
data_valid <= 0;
In the above case the always block will be executed whenever 'reset' changes. However you have to be careful about the timing of other assignment there. They could happen when you deassert reset with some offset from the posedge clk.

Error count for two different patterns in verilog

I have made 2 forms of data patterns and wants to compare them in the form of error count.....when the 2 patterns are not equal, the error count should be high....i made the code including test bench, but when i ran behavioral sumilation, the error count is only high at value 0 and not at value 1.....I expect it to be high at both 0 and 1....please help me out in this, since I am new with verilog
here is the code
`timescale 1ns / 1ps
module pattern(
clk,
start,
rst,enter code here
clear,
data_in1,
data_in2,
error
);
input [1:0] data_in1;
input [1:0] data_in2;
input clk;
input start;
input rst;
input clear;
output [1:0] error;
reg [1:0] comp_out;
reg [1:0] i = 0;
assign error = comp_out;
always#(posedge clk)
begin
comp_out = 0;
if(rst)
comp_out = 0;
else
begin
for(i = 0; i < 2; i = i + 1)
begin
if(data_in1[i] != data_in2[i])
comp_out <= comp_out + 1;
end
end
end
endmodule
here is the test bench for the above code
`timescale 1ns / 1ps
module tb_pattern();
// inputs
reg clk;
reg rst;
reg [1:0] data_in1;
reg [1:0] data_in2;
wire [1:0] error;
//outputs
//wire [15:0] count;
//instantiate the unit under test (UUT)
pattern uut (
// .count(count),
.clk(clk),
.start(start),
.rst(rst),
.clear(clear),
.data_in1(data_in1),
.data_in2(data_in2),
.error(error)
);
initial begin
clk = 1'b0;
rst = 1'b1;
repeat(4) #10 clk = ~clk;
rst = 1'b0;
forever #10 clk = ~clk; // generate a clock
end
initial begin
//initialize inputs
clk = 0;
//rst = 1;
data_in1 = 2'b00;
data_in2 = 2'b01;
#100
data_in1 = 2'b11;
data_in2 = 2'b00;
#100
$finish;
end
//force rest after delay
//#20 rst = 0;
//#25 rst = 1;
endmodule
When incrementing in a for loop you need to use blocking assignment (=), however when assigning flops you should use non-blocking assignment (<=). When you need to use a for loop to assign a flop, it is best to split the combinational and synchronous functionality into separate always blocks.
...
reg [1:0] comp_out, next_comb_out;
always #* begin : comb
next_comp_out = 0;
for (i = 0; i < 2; i = i + 1) begin
if (data_in1[i] != data_in2[i]) begin
next_comp_out = next_comp_out + 1;
end
end
end
always #(posedge clk) begin : dff
if (rst) begin
comb_out <= 1'b0;
end
else begin
comb_out <= next_comp_out;
end
end
...
begin
for(i = 0; i < 2; i = i + 1)
begin
if(data_in1[i] != data_in2[i])
comp_out <= comp_out + 1;
end
end
This for loop doesn't work the way you think it does. Because this is a non-blocking assignment, only the last iteration of the loop actually applies. So only the last bit is actually being compared here.
If both bits of your data mismatch, then the loop unrolls to something which looks like this:
comp_out <= comp_out + 1;
comp_out <= comp_out + 1;
Because this is non-blocking, the RHS of the equation are both evaluated at the same time, leaving you with:
comp_out <= 0 + 1;
comp_out <= 0 + 1;
So even though you tried to use this as a counter, only the last line takes effect, and you get a mismatch count of '1', no matter how many bits mismatch.
Try using a blocking statement (=) for comp_out assignment instead.

Reduce array to sum of elements

I am trying to reduce a vector to a sum of all it elements. Is there an easy way to do this in verilog?
Similar to the systemverilog .sum method.
Thanks
My combinational solution for this problem:
//example array
parameter cells = 8;
reg [7:0]array[cells-1:0] = {1,2,3,4,5,1,1,1};
//###############################################
genvar i;
wire [7:0] summation_steps [cells-2 : 0];//container for all sumation steps
generate
assign summation_steps[0] = array[0] + array[1];//for less cost starts witch first sum (not array[0])
for(i=0; i<cells-2; i=i+1) begin
assign summation_steps[i+1] = summation_steps[i] + array[i+2];
end
endgenerate
wire [7:0] result;
assign result = summation_steps[cells-2];
Verilog doesn't have any built-in array methods like SV. Therefore, a for-loop can be used to perform the desired functionality. Example:
parameter N = 64;
integer i;
reg [7:0] array [0:N-1]
reg [N+6:0] sum; // enough bits to handle overflow
always #*
begin
sum = {(N+7){1'b0}}; // all zero
for(i = 0; i < N; i=i+1)
sum = sum + array[i];
end
In critiquing the other answers delivered here, there are some comments to make.
The first important thing is to provide space for the sum to be accumulated. statements such as the following, in RTL, won't do that:
sum = sum + array[i]
because each of the unique nets created on the Right Hand Side (RHS) of the expression are all being assigned back to the same signal called "sum", leading to ambiguity in which of the unique nets is actually the driver (called a multiple driver hazard). To compound the problem, this statement also creates a combinational loop issue because sum is used combinationally to drive itself - not good. What would be good would be if something different could be used as the load and as the driver on each successive iteration of the loop....
Back to the argument though, in the above situation, the signal will be driven to an unknown value by most simulator tools (because: which driver should it pick? so assume none of them are right, or all of them are right - unknown!!). That is if it manages to get through the compiler at all (which is unlikely, and it doesn't at least in Cadence IEV).
The right way to do it would be to set up the following. Say you were summing bytes:
parameter NUM_BYTES = 4;
reg [7:0] array_of_bytes [NUM_BYTES-1:0];
reg [8+$clog2(NUM_BYTES):0] sum [NUM_BYTES-1:1];
always #* begin
for (int i=1; i<NUM_BYTES; i+=1) begin
if (i == 1) begin
sum[i] = array_of_bytes[i] + array_of_bytes[i-1];
end
else begin
sum[i] = sum[i-1] + array_of_bytes[i];
end
end
end
// The accumulated value is indexed at sum[NUM_BYTES-1]
Here is a module that works for arbitrarily sized arrays and does not require extra storage:
module arrsum(input clk,
input rst,
input go,
output reg [7:0] cnt,
input wire [7:0] buf_,
input wire [7:0] n,
output reg [7:0] sum);
always #(posedge clk, posedge rst) begin
if (rst) begin
cnt <= 0;
sum <= 0;
end else begin
if (cnt == 0) begin
if (go == 1) begin
cnt <= n;
sum <= 0;
end
end else begin
cnt <= cnt - 1;
sum <= sum + buf_;
end
end
end
endmodule
module arrsum_tb();
localparam N = 6;
reg clk = 0, rst = 0, go = 0;
wire [7:0] cnt;
reg [7:0] buf_, n;
wire [7:0] sum;
reg [7:0] arr[9:0];
integer i;
arrsum dut(clk, rst, go, cnt, buf_, n, sum);
initial begin
$display("time clk rst sum cnt");
$monitor("%4g %b %b %d %d",
$time, clk, rst, sum, cnt);
arr[0] = 5;
arr[1] = 6;
arr[2] = 7;
arr[3] = 10;
arr[4] = 2;
arr[5] = 2;
#5 clk = !clk;
#5 rst = 1;
#5 rst = 0;
#5 clk = !clk;
go = 1;
n = N;
#5 clk = !clk;
#5 clk = !clk;
for (i = 0; i < N; i++) begin
buf_ = arr[i];
#5 clk = !clk;
#5 clk = !clk;
go = 0;
end
#5 clk = !clk;
$finish;
end
endmodule
I designed it for 8-bit numbers but it can easily be adapted for other kinds of numbers too.

Resources