Upsample with Verilog - verilog

I need to upsample(2x) my data using Verilog. I think to use three ports for input and one port for output. Input ports are filterin, reset and clock. Output port is filterout. Also I need dynamic input size. How can I realize this with Verilog.
Edit1:
My input and output datas are 16 bit long. I just need a Verilog code to do this:
If Input: 1 2 3,
Then Output: 1 0 2 0 3 0.
If Input: 1 2 3 4 5,
Then Output: 1 0 2 0 3 0 4 0 5 0.
Edit2:
I created a verilog file to solve this but it didn't solve my problem.
US1.v file
`timescale 1ns / 1ps
module US1 (filterin,clk,filterinus);
input [15:0] filterin;
input clk;
output reg [15:0] filterinus;
integer i=0;
always # (posedge clk) begin
if (i==0) begin
filterinus <= filterin;
end
else begin
filterinus <= 0;
end
i=~i;
end
endmodule
I tested this code with the following Test bench:
Test.v file
`timescale 1ps/1ps
module Test;
reg [15:0] filterin;
reg clk;
wire [15:0] filterinus;
US1 uut (
.filterin(filterin),
.clk(clk),
.filterinus(filterinus)
);
initial begin
clk = 1;
filterin = 1;
#2 filterin = 2;
#2 filterin = 3;
#2 filterin = 4;
#2 filterin = 5;
#30 $finish;
end
always #1 clk = ~clk;
endmodule
As is seen, my input is: 1 2 3 4 5.
My output is: 1 0 3 0 5 0 5 0 5 0...
I need to see: 1 0 2 0 3 0 4 0 5 0 0 0 0 0...

A few comments on your code, assuming this is for synthesis.
Don't initialize the variable 'i' in a declaration. This is not always synthesizable.
Don't use an integer type for a single toggle bit. This makes your code less clear and makes the tools work harder.
Never mix blocking and non-blocking assignments in the same always block.
Given your description, I'm not sure what operation you're trying to implement here. You said upsampling but this isn't a typical approach such as linear or cubic interpolation methods.

Problem solved. I changed filterin input period from my testbench like this:
filterin = 1;
#4 filterin = 2;
#4 filterin = 3;
#4 filterin = 4;
#4 filterin = 5;
#4 filterin = 0;
And I got my output: 1 0 2 0 3 0 4 0 5 0 0 0...

Related

If statement is not executing properly while trying to create double dabble to convert binary to BCD

I am trying to build a binary to BCD converter using the double dabble algorithm. I wrote the code for the same, and when I simulated the entire thing, it was observed that my if statement is not getting executed properly.
`timescale 1ns / 1ps
module test_6( input [13:0] bin ,
output reg [3:0] ones, // ones value of the input number
output reg [3:0] tens, // tens value of the input number
output reg [3:0] hundreds, // hundreds value of the input nnumber
output reg [3:0] thousands // thousands value of the input number
);
integer i;
reg [15:0] scratch; // 16 bit register
reg [29:0] combined; // 30 bit concatenated register bin and scratch
always #(bin) begin
scratch = 0;
combined = {scratch[15:0], bin[13:0]}; // concatenating scratch and bin into combined
for (i=0; i<14; i=i+1) begin
combined = combined<<1; // left shift by 1
if (combined[17:14] > 4) begin
combined[17:14] = combined[17:14] + 4'b0011; //check if >4, if yes add 3
end
if (combined[21:18] > 4) begin
combined[21:18] = combined[21:18] + 4'b0011; //check if >4, if yes add 3
end
if (combined[25:22] > 4) begin
combined[25:22] = combined[25:22] + 4'b0011; //check if >4, if yes add 3
end
if (combined[29:26] > 4) begin
combined[29:26] = combined[29:26] + 4'b0011; //check if >4, if yes add 3
end
end
thousands = combined[29:26];
hundreds = combined[25:22];
tens = combined[21:18];
ones = combined[17:14];
$display(ones);
$display(tens);
$display(hundreds);
$display(thousands);
end
endmodule
The testbench is given below.
module test_6_tb;
// Inputs
reg [13:0] bin;
// Outputs
wire [3:0] ones;
wire [3:0] tens;
wire [3:0] hundreds;
wire [3:0] thousands;
// Instantiate the Unit Under Test (UUT)
test_6 uut (
.bin(bin),
.ones(ones),
.tens(tens),
.hundreds(hundreds),
.thousands(thousands)
);
initial begin
// Initialize Inputs
bin = 14'd1157;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
end
endmodule
The output on the simulation window was as shown:
The output I am expecting is:
Thousands should have the value 1, hundreds should have the value 1, tens should have the value 5, ones should have the value 7.
The mistake in your code is that you did not follow the double dabble algorithm. From Wikipedia:
The algorithm then iterates n times. On each iteration, any BCD digit
which is at least 5 (0101 in binary) is incremented by 3 (0011); then
the entire scratch space is left-shifted one bit.
You performed the left shift before the add-by-3, but it should be done after.
for (i=0; i<14; i=i+1) begin
if (combined[17:14] > 4) begin
combined[17:14] = combined[17:14] + 4'b0011; //check if >4, if yes add 3
end
if (combined[21:18] > 4) begin
combined[21:18] = combined[21:18] + 4'b0011; //check if >4, if yes add 3
end
if (combined[25:22] > 4) begin
combined[25:22] = combined[25:22] + 4'b0011; //check if >4, if yes add 3
end
if (combined[29:26] > 4) begin
combined[29:26] = combined[29:26] + 4'b0011; //check if >4, if yes add 3
end
combined = combined<<1; // left shift by 1
end
Now I get the expected output: 1157.
After I posted my other answer, I was curious as to how the algorithm worked. So, I decided to try to follow the description as you did.
I searched on EE.SE and found this answer. It contains a link to Wikipedia, which has the following code. I had to fix a typo in the code, but this works:
// parametric Verilog implementation of the double dabble binary to BCD converter
// for the complete project, see
// https://github.com/AmeerAbdelhadi/Binary-to-BCD-Converter
module bin2bcd
#( parameter W = 14) // input width
( input [W-1 :0] bin , // binary
output reg [W+(W-4)/3:0] bcd ); // bcd {...,thousands,hundreds,tens,ones}
integer i,j;
always #(bin) begin
for(i = 0; i <= W+(W-4)/3; i = i+1) bcd[i] = 0; // initialize with zeros
bcd[W-1:0] = bin; // initialize with input vector
for(i = 0; i <= W-4; i = i+1) // iterate on structure depth
for(j = 0; j <= i/3; j = j+1) // iterate on structure width
if (bcd[W-i+4*j -: 4] > 4) // if > 4
bcd[W-i+4*j -: 4] = bcd[W-i+4*j -: 4] + 4'd3; // add 3
end
endmodule
module tb;
reg [13:0] bin;
reg [17:0] bcd;
wire [3:0] ones = bcd[ 3: 0];
wire [3:0] tens = bcd[ 7: 4];
wire [3:0] hundreds = bcd[11: 8];
wire [3:0] thousands = bcd[15:12];
bin2bcd dut (bin, bcd);
initial begin
$monitor(thousands,,hundreds,,tens,,ones);
#5 bin = 14'd1157;
#5 bin = 14'd0045;
#5 bin = 14'd9876;
end
endmodule
Prints:
x x x x
1 1 5 7
0 0 4 5
9 8 7 6
The algorithm is thoroughly explained in the article and in the header comments of the Verilog code in github.

Scheduling semantic of a task in Verilog

The execution of this code under iverilog simulator
module top();
reg clk;
reg[31:0] counter;
reg[19:0] in;
reg[31:0] out;
reg[19:0] xxx;
reg[19:0] yyy;
always #5 clk = ~clk;
initial begin
clk <= 0;
counter <= 0;
out <= 0;
end
always #(posedge(clk)) begin
decode_inst(counter);
$strobe("pre-counter is %0t",counter);
counter = counter + 1;
out <= counter;
$strobe("time is %0t",$time);
$strobe("counter is %0t",counter);
$strobe("out is %0t",out);
decode_inst(counter);
if (counter == 2) $finish();
end
task decode_inst(input xxx);
begin
$strobe("task_time is %0t",$time);
$strobe("task_counter is %0t",xxx);
end
endtask
endmodule
produces the following output:
task_time is 5
task_counter is 1
pre-counter is 1
time is 5
counter is 1
out is 1
task_time is 5
task_counter is 1
task_time is 15
task_counter is 0
pre-counter is 2
time is 15
counter is 2
out is 2
task_time is 15
task_counter is 0
Even studing the semantic of Verilog scheduling,
I'm not able to explain to myself the result.
In particular, how it is possible
task_counter = 0 when task_time = 15 and
task_counter = 1 when task_time = 5.
My question: is this output compliant with Verilog scheduling semantic?
The behavior described in the post is compliant with Verilog and its scheduling semantics.
The unexpected behavior (task_counter = 0 at the end) is caused by an error in the task argument.
The argument type is omitted; the default type is one-bit wide.
One bit can't represent the integer 2.
To correct this, change the task argument type to a vector as below:
task decode_inst(input [31:0] xxx);
begin
$strobe("task_time is %0t",$time);
$strobe("task_counter is %0d",xxx);
end
endtask
Also added some time after the clock to let the printing occur before the simulation ends. Without this the test is stopping and printing at the same time which can be confusing and lead to figuring out who wins the race.
Add #1 delay:
if (counter == 2) #1 $finish();
Produces the result in two simulators on EDA Playground:
# pre-counter is 1
# time is 5
# counter is 1
# out is 1
# task_time is 5
# task_counter is 1
# pre-counter is 2
# time is 15
# counter is 2
# out is 2
# task_time is 15
# task_counter is 2

Task does not pass the output right

I have been trying to design a task for my testbench to make my life easier. The task seems to be doing fine when I check the internal signals using $display. However, when I hook the task up in my initial block, the simulation output shown on the waveform is NOT the same as the display result. Thank you in advance
===========Code===========
`timescale 1ns/1ps
/*----------Macros----------*/
`define FullCycle 20
`define HalfCycle 10
`define CLK_Cycle(CycleNum) (`FullCycle*CycleNum)
module syncronization_tb();
/*----------DUT I/O----------*/
logic reset_n, clk4m, ppm_data, output_valid_flag;
logic [7: 0] data_out_DUT;
logic flag;
/*----------TX I/O----------*/
logic bit_stream, clk50m;
logic [1: 0] ppm_out;
/*----------RX I/O----------*/
logic clk50mREC;
logic data_out;
assign ppm_data = data_out;
Syncronization DUT
(
reset_n,
clk4m_out,
ppm_data,
data_out_DUT,
output_valid_flag
);
PPM_top TX
(
reset_n,
clk50m,
bit_stream,
ppm_out
);
CLK_Recovery RX
(
clk50mREC,
reset_n,
ppm_out[1],
data_out,
clk4m_out
);
logic [7:0] data;
logic Taskflag;
integer index;
initial forever #`HalfCycle clk50m = ~ clk50m;
initial #17 forever #`HalfCycle clk50mREC = ~clk50mREC;
initial begin
{reset_n, clk50m, bit_stream, clk50mREC} = 0;
#`CLK_Cycle(5);
{reset_n} = 1;
data = 8'haa;
generateBITstream(.data(data), .bit_stream_out(bit_stream),.index(index));
// data = 8'he3;
// generateBITstream(data, bit_stream);
//data = 8'h5b;
//generateBITstream(data, bit_stream);
#`CLK_Cycle(800);
$stop;
end
task automatic generateBITstream;
parameter integer width = 8;
input [width - 1: 0] data;
output logic bit_stream_out;
output integer index;
begin
for(index = 0; index < width; index = index + 1 ) begin
#(posedge TX.clk1m) bit_stream_out = data[index];
$display("%d and time is %t with %b",index, $time, bit_stream_out);
#`CLK_Cycle(10);
end
end
endtask
endmodule
===========Console Display [Correct Result]===========
run -all
# 0 and time is 1870000ps with 0
# 1 and time is 2870000ps with 1
# 2 and time is 3870000ps with 0
# 3 and time is 4870000ps with 1
# 4 and time is 5870000ps with 0
# 5 and time is 6870000ps with 1
# 6 and time is 7870000ps with 0
# 7 and time is 8870000ps with 1
# Break in Module syncronization_tb at G:/Work/PPM/src/Syncronization RTL Simulation/src/syncronization_tb.sv line 74
===========Waveform [Wrong Result]===========
[]
===========A minimal reproducible example===========
`timescale 1ns/1ps
/*----------Macros----------*/
`define FullCycle 20
`define HalfCycle 10
`define CLK_Cycle(CycleNum) (`FullCycle*CycleNum)
module syncronization_tb();
logic [7:0] data;
logic bit_stream, clk50m;
integer index;
initial forever #`HalfCycle clk50m =~ clk50m;
initial begin
clk50m = 0; #`CLK_Cycle(10);
data = 8'haa;
generateBITstream(.data(data), .bit_stream_out(bit_stream),.index(index));
#`CLK_Cycle(800);
$stop;
end
task automatic generateBITstream;
parameter integer width = 8;
input [width - 1: 0] data;
output logic bit_stream_out;
output integer index;
begin
for(index = 0; index < width; index = index + 1 ) begin
#(posedge clk50m) bit_stream_out = data[index];
$display("%d and time is %t with %b",index, $time, bit_stream_out);
#`CLK_Cycle(10);
end
end
endtask
endmodule
===========Console Display [Correct Result]===========
# 0 and time is 210000 with 0
# 1 and time is 410000 with 1
# 2 and time is 610000 with 0
# 3 and time is 810000 with 1
# 4 and time is 1010000 with 0
# 5 and time is 1210000 with 1
# 6 and time is 1410000 with 0
# 7 and time is 1610000 with 1
# Break in Module syncronization_tb at G:/Work/PPM/src/Syncronization RTL Simulation/src/syncronization_tb.sv line 22
The problem is that the signal connected to the task output port (bit_stream) only gets updated in the testbench once the task completes (after the for loop). It does not get updated every time the $display is called in the for loop.
One way to fix this is to get rid of the task output port, and directly update the bit_stream signal inside the task:
task automatic generateBITstream;
parameter integer width = 8;
input [width - 1: 0] data;
output integer index;
begin
for(index = 0; index < width; index = index + 1 ) begin
#(posedge TX.clk1m) bit_stream = data[index];
$display("%d and time is %t with %b",index, $time, bit_stream);
#`CLK_Cycle(10);
end
end
endtask
Then call the task as:
generateBITstream(.data(data), .index(index));

verilog counter not starting from 0

I'm using this counter as a mux select pins and I need it to start from 0, but in simulation in the first cycle it is starting from 1 and at the next cycle it starts from 0.
module upcounter(clk,reset,out);
input clk,reset;
output reg [2 : 0]out = 3'b000;
always #(posedge clk or posedge reset)
begin
if(reset)
out <= 3'b000;
else
out <= out + 3'b001;
end
endmodule
This is my testbench codes:
module counter_tst;
reg clk;
wire [2 : 0] out;
reg rst;
upcounter u0(clk,rst,out);
initial
clk = 1'b1;
always
#1 clk = ~clk;
initial
begin
rst=0;
end
endmodule
As #Serge says the test bench is important to explain what you are seeing.
Your testbench only ever sets rst to 0, so we can safely ignore the code that is conditioned on reset entirely. No positive edges or values of 1 to worry about.
At time 0 your testbench forces clk to 1. This is treated as a positive edge, as such immediately after that out is incremented to 1. Since you don't have a <= #n delay when you increment out it appears to take effect immediately. With this sort of thing, I find including simulation delays helps debugging.
Consider this version of the code and testbench. I've slowed down the clock ticking by a factor of 10, and inserted a #1 delay in the out value incrementing. I've also removed all the orphaned rst/reset code to focus on the effect you are seeing:
// code.v
module upcounter(clk,out);
input clk;
output reg [2 : 0] out = 3'b000;
always #(posedge clk)
out <= #1 out + 3'b001;
endmodule
module counter_tst;
reg clk;
wire [2 : 0] out;
upcounter u0(clk,out);
initial
begin
clk = 1'b1;
$monitor("time = %0d", $time, " clk = %b out = %d", clk, out);
$dumpvars();
#1000 $finish();
end
always
#10 clk = ~clk;
endmodule
Compile and run it as follows:
$ iverilog code.v
$ ./a.out
VCD info: dumpfile dump.vcd opened for output.
time = 0 clk = 1 out = 0
time = 1 clk = 1 out = 1
time = 10 clk = 0 out = 1
time = 20 clk = 1 out = 1
time = 21 clk = 1 out = 2
time = 30 clk = 0 out = 2
time = 40 clk = 1 out = 2
time = 41 clk = 1 out = 3
< etc >
You should now be able to see that the first increment to out is happening because of the observed posedge clk.

Lattice iCE40-HX8K Board - UART

I have the following verilog code for my Lattice iCE40-HX8K Board:
uart.v:
module uart(input clk, output TXD);
reg [3:0] count;
reg [9:0] data;
reg z;
initial begin
data[9:0] = 10'b1000000000; // Startbit = 1, Stopbit = 0
z = 0;
end
always#(posedge clk)
begin
if(count == 1250) //9600x per Second (1250) = Baudrate
begin
count <= 0;
TXD = data[z];
z = z + 1;
if(z == 10)
begin
z = 0;
end
else
begin
end
end
else
begin
count <= count + 1;
end
end
endmodule
For receiving the UART-Data I use gtkterm under Ubuntu 14.04.
I have set the baudrate in gtkterm to 9600.
If I now program my FPGA with the code I receive once per programming a
hex "00" (irrespective of the 8 usage-bits).
Can anybody give me a hint what is wrong?
Thank you for your support.
There are at least two obvious problems with your design:
Your count is only 4 bits wide, thus it cannot count to 1250. It must be at least 11 bits wide to be able to count to 1250.
Also your z is only 1 bit wide, so it can only hold the values 0 and 1. It must be at least 4 bits wide to be able to count to 10.
You should also read up on blocking vs. non-blocking assignments. The way you use blocking assignments in sequential logic can lead to race conditions in the verilog simulation model.
You should always write testbenches for your HDL code and simulate it before trying to run it in hardware. A testbench for your design would be as easy as:
module uart_testbench;
reg clk = 1;
always #5 clk = ~clk;
uart uut (
.clk(clk)
);
initial begin
$dumpfile("uart.vcd");
$dumpvars(0, uut);
repeat (1000000) #(posedge clk);
$finish;
end
endmodule

Resources