Can anybody explain what is the difference between these two?
In any other higher level languages construct 2 (without delay) would have given correct assignments.
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 `timescale 1ns / 1ps `include "C:/Users/GANESAN/NoC_RG_3_copy/NoC_RG_3_copy.srcs/sources_1/new/fifo_buf.v" `include "C:/Users/GANESAN/NoC_RG_include/NoC_RG_include.srcs/sources_1/new/NoC_RG_include.vh" //`include "C:/Users/GANESAN/NoC_RG_mux_2_copy/NoC_RG_mux_2_copy.srcs/sources_1/new/NoC_RG_mux_2.sv" module NoC_RG_mux_2(clk,mux_in_data,mux_sel,mux_out_data,rst,rd_enm,wr_enm,buf_fullm,buf_emptym,buf_inm,buf_outm,fifo_counterm,mux_data); input clk; input wire [`DATA_SIZE-1:0] mux_in_data [5]; input wire [2:0] mux_sel ; output reg [`DATA_SIZE-1:0] mux_out_data; reg [`DATA_SIZE-1:0] muxdata[5]; input wire rst; input wire [7:0] buf_inm [0:3][0:3]; input wire rd_enm [0:3][0:3], wr_enm[0:3][0:3]; output reg buf_fullm [0:3] [0:3]; output reg buf_emptym [0:3] [0:3]; output reg [7:0] buf_outm [0:3][0:3]; output reg [3:0] fifo_counterm [0:3][0:3] ; input wire [7:0]mux_data; genvar i,j,k; generate for (i=0;i<=`rowsize-1;i=i+1) begin for (j=0;j<=`colsize-1;j=j+1) begin fifo_buf f1(.clk(clk),.rst(rst),.rd_en(rd_enm[i][j]),.wr_en(wr_enm[i][j]),.buf_full(buf_fullm[i][j]),.buf_empty(buf_emptym[i][j]),.buf_in(buf_inm[i][j]),.buf_out(buf_outm[i][j]),.fifo_counter(fifo_counterm[i][j])); end end endgenerate //mux coding starts always @(mux_sel) mux_out_data=mux_in_data[mux_sel]; //mux coding ends endmodule
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// `include "C:/Users/GANESAN/NoC_RG_include/NoC_RG_include.srcs/sources_1/new/NoC_RG_include.vh" `include "C:/Users/GANESAN/NoC_RG_3_copy/NoC_RG_3_copy.srcs/sources_1/new/fifo_buf.v" module tb_NoC_RG_mux_2(); reg [`DATA_SIZE-1:0] mux_in_data [5]; reg [2:0] mux_sel; wire [`DATA_SIZE-1:0] mux_out_data; //parameter rowsize=4; //parameter colsize=4; reg clk,rst; reg [7:0] buf_inm [0:3][0:3]; reg rd_enm [0:3][0:3], wr_enm[0:3][0:3]; wire buf_fullm [0:3] [0:3]; wire buf_emptym [0:3] [0:3]; wire [7:0] buf_outm [0:3][0:3]; wire [3:0] fifo_counterm [0:3][0:3]; reg [3:0] i,j; reg [7:0] temp_data; reg [7:0] mux_data; //Mux code ends here NoC_RG_mux_2 f2 (.clk(clk),.mux_in_data(mux_in_data),.mux_sel(mux_sel),.mux_out_data(mux_out_data),.rst(rst),.rd_enm(rd_enm),.wr_enm(wr_enm),.buf_fullm(buf_fullm),.buf_emptym(buf_emptym),.buf_inm(buf_inm),.buf_outm(buf_outm),.fifo_counterm(fifo_counterm),.mux_data(mux_data)); initial begin $display("%m"); rst=1'b1; clk=1'b0; #4 rst =1'b0; temp_data<=0; mux_data<=0; //mux_out_data<=0; for (i=0;i<=3;i=i+1) begin for (j=0;j<=3;j=j+1) begin rd_enm[i][j]=0; wr_enm[i][j]=0; end end //buf_out_mux=0; //$display("fifo_buf_mux f2 rd_enm %d %d=%d",i,j,f2.rd_enm[2][1]); //$display("My instance name is: %m"); push(2,1,120); push(3,2,90); pop(2,1,temp_data); push(0,2,63); /*pop(2,1,temp_data); pop(3,2,temp_data); pop(3,2,temp_data); pop(3,2,temp_data); push(3,2,61); push(3,2,75); push(3,2,80); push(3,2,90); push(3,2,100); pop(3,2,temp_data); pop(3,2,temp_data); pop(3,2,temp_data); pop(3,2,temp_data); pop(3,2,temp_data);*/ end always #5 clk <= ~clk; task pop; input [3:0] row,col; output [7:0] temp_data; //output [7:0] mux_data; begin if (!buf_emptym[row][col]) begin rd_enm[row][col]=1'b1; @(posedge clk) #2 rd_enm[row][col]=1'b0; temp_data=buf_outm[row][col]; #1 mux_data=temp_data; $monitor("Buf_emptym= %d",buf_emptym[row][col]); $monitor ("Popped location [row] [col] %d %d value= %d",row,col,temp_data); $monitor ("mux_data= %d",mux_data); end else $monitor("buffer %d %d is empty ",row,col); end endtask task push; input [3:0] row,col; input [7:0] temp_data; begin if (!buf_fullm[row][col]) begin wr_enm[row][col]=1; buf_inm[row][col] =temp_data; #1 mux_data=buf_inm[row][col]; $monitor ("Pushed location [row] [col] %d %d value= %d",row,col,buf_inm[row][col]); $monitor("mux_data= %d",mux_data); @(posedge clk)#2 wr_enm[row][col]= 0; end else $monitor("buffer %d %d is full",row,col); end endtask //Mux code starts here always @ (mux_data) begin $monitor ("mux_data= %d",mux_data); end genvar a; generate for ( a=0; a<5; a++) begin assign mux_in_data[a]=mux_data; end endgenerate initial begin clk=0; mux_sel=1; #5 mux_sel=4; #10 mux_sel=1; end always @ (mux_sel) $monitor ("mux_sel= %d mux_out_data= %d",mux_sel,mux_out_data); endmodule
Your point 1 & 2 don't make any sense. They are both blocking assignments.pop task:
------
rd_enm[row][col]=1'b1;
@(posedge clk) #2 rd_enm[row][col]=1'b0;
temp_data=buf_outm[row][col];
#1 mux_data=temp_data;
-------
Two racing cases can happen in your task:
1/ if you remove "#2", temp_data could get the old value of buf_outm[row][col].
2/ if you remove and #1, mux_data could get the old value of temp_data.
For simulation, you can add the delay to eleminate the racing condition.
We are not sure which event happen first in computer machine if there is many things ( blocking assignments = ) were required at the same time.
What happen if you remove those delays case by case ?
A waveform is better to understand how your problem was.
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 //`timescale 1ns / 1ps module fifo_buf #(parameter buf_size=4,data_size=8,ptr_size=2) (clk,rst,rd_en,wr_en,buf_full,buf_empty,buf_in,buf_out,fifo_counter); input rd_en,wr_en; input rst,clk; input [data_size-1:0] buf_in; output reg [data_size-1:0] buf_out; output reg buf_full,buf_empty; reg [data_size-1:0] buf_mem[buf_size-1:0]; reg[ptr_size-1:0] rd_ptr,wr_ptr; output reg [buf_size:0] fifo_counter; always @ (fifo_counter) begin if (fifo_counter==buf_size) buf_full <= 1; else buf_full<=0; if (fifo_counter==0) buf_empty <=1; else buf_empty<=0; end always @(posedge clk or posedge rst) begin if (rst) fifo_counter <= 0; else begin if (!buf_full&& wr_en && !buf_empty && rd_en) fifo_counter <= fifo_counter; else if (!buf_full&& wr_en) fifo_counter <= fifo_counter+1; else if (!buf_empty && rd_en) fifo_counter <= fifo_counter-1; else fifo_counter <= fifo_counter; end end always @(posedge clk or posedge rst) begin if (rst) begin wr_ptr <= 0; rd_ptr<=0; end else begin if (!buf_full&& wr_en) #1 wr_ptr <= wr_ptr+1; else wr_ptr <= wr_ptr; if (!buf_empty && rd_en) #1 rd_ptr <= rd_ptr+1; else rd_ptr <= rd_ptr; end end always @(posedge clk) begin if (!buf_full&& wr_en) buf_mem[wr_ptr] <= buf_in; else buf_mem[wr_ptr] <= buf_mem[wr_ptr]; end always @(posedge clk or posedge rst) begin if (rst) buf_out <= 0; else begin if (!buf_empty && rd_en) buf_out <= buf_mem[rd_ptr]; else buf_out <= buf_out; end end endmodule
What screen shots?I have verified simulation after removing the delays as noted. NoC_RG_mux_delay pertains to Tcl console after removing delay #1. NoC_RG_mux_2 pertains to Tcl console after removing #2.
Sometimes mux_data gets prior value some times value ahead as can be noted from the screen shot.
you didn't supply the .vh file I'll just guess the values for the `defines (BTW this is really a bad practice to rely on `defines)Ganesan_R said:I have also enclosed the complete code as required by ads-ee. Pl. go thro' and advise.
Type out all words, I really hate the abbreviations used by non-english speakers it makes a post difficult to read (pl. I guess stands for please :-x)Ganesan_R said:Ads-ee may pl. advise how I could have better coded test bench. The delay in fifo_counter source code (not test bench) may pl. be ignored as they do not affect simulation results. (I have added it for my later extensions as landmarks)
Use less pins. If this is a module that is supposed to be used in a bigger design, then don't allow the tools to insert I/O when running it through synthesis/implementation.Ganesan_R said:I have one more issue: The code overshoots the device IO pin utilisation. What modifications I can do in the source codes not to exceed device IO utilisation.
A simulation testbench can include both non-synthesizble and synthesizable code. You don't synthesized testbenches you simulate with testbenches. You can write a synthesizable testbench (e.g. Xilinx MIG can produce a synthesizable testbench to allow you to run both a simulation and build the IP into a device to run a memory test).Ganesan_R said:You have mentioned for test bench you can add delay.
How test benches are realized (synthesized) in real world? Is it only software testing of hardware fpga board?
`timescale 1ns / 1ps
`ifndef _NoC_include_vh_
`define _NoC_include_vh_
`define rowsize 4
`define colsize 4
`define DATA_SIZE 8 //Put here required data size
`define BUF_SIZE 4
`define buf_size 4
//define log2 function here
function integer log2;
input integer value;
begin
value=value-1;
for (log2=0;value>0;log2=log2+1)
value=value>>1;
end
endfunction
What does this have to do with your testbench? Your testbench is supposed to emulate the top level code where your code is instantiated.I tried following your advice in synchronizing with clock pulse but the coding with synchronization could not be completed by me as some signals being input are set in main code and some signals being output are set in the main code.
Ganesan_R said:I am unable to carry intermediate signals from test bench to main program as intermediate signals are set in test benches for example rd_enm [j] in the test bench as I have to loop again in the main program even if I carry it.
To test a design the steps are usually:Ganesan_R said:So far the bonded IOB pin numbers are 584 as against 200 that is available. Yes the design is part of an entire NoC design. I do not know if IOB pin numbers exceed the Zynq demo board will I be able to practically burn and test the entire program?
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 `timescale 1ns / 1ps module fifo_buf #(parameter buf_size=4,data_size=8,ptr_size=2) (clk,rst,rd_en,wr_en,buf_full,buf_empty,buf_in,buf_out,fifo_counter); input rd_en,wr_en; input rst,clk; input [data_size-1:0] buf_in; output reg [data_size-1:0] buf_out; output reg buf_full,buf_empty; reg [data_size-1:0] buf_mem[buf_size-1:0]; reg[ptr_size-1:0] rd_ptr,wr_ptr; output reg [buf_size-1:0] fifo_counter; always @(fifo_counter) begin if (fifo_counter == 0) buf_empty=1; else buf_empty=0; if (fifo_counter == buf_size) buf_full=1; else buf_full=0; end always @(posedge clk or posedge rst) begin if (rst) fifo_counter <= 0; else if (!buf_full && wr_en) fifo_counter <= fifo_counter + 1; else if (!buf_empty && rd_en) fifo_counter <= fifo_counter - 1; else if ((!buf_empty && rd_en) && (!buf_full && wr_en)) fifo_counter <= fifo_counter; else fifo_counter<=fifo_counter; end always @(posedge clk or posedge rst) begin if (rst) buf_out <= 0; else begin if (!buf_empty && rd_en) buf_out<=buf_mem[rd_ptr]; else buf_out<=buf_out; end end always @(posedge clk) begin if (!buf_full && wr_en) buf_mem[wr_ptr]<=buf_in; else buf_mem[wr_ptr]<=buf_mem[wr_ptr]; end always @(posedge clk or posedge rst) begin if (rst) begin wr_ptr<=0; rd_ptr<=0; end else begin if (!buf_empty && rd_en) rd_ptr<=rd_ptr+1; else rd_ptr<=rd_ptr; if (!buf_full && wr_en) wr_ptr<=wr_ptr+1; else wr_ptr<=wr_ptr; end end endmodule
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 module tb_NoC_RG(); reg clk,rst,rd_en,wr_en; reg [7:0] buf_in; wire [7:0] buf_out; wire [3:0] fifo_counter; reg [7:0] temp_data,temp_data_out; reg counter_full,counter_empty; fifo_buf fb1 (.clk(clk),.rst(rst),.rd_en(rd_en),.wr_en(wr_en),.buf_full(buf_full),.buf_empty(buf_empty),.buf_in(buf_in),.buf_out(buf_out),.fifo_counter(fifo_counter)); initial begin clk=0; rst=1; rd_en=0; wr_en=0; //temp_data=0; //buf_in=0; #3 rst=0; //buf_empty=0; //buf_full=0; @ (posedge clk) push(127); @ (posedge clk) push(64); @ (posedge clk) pop(temp_data); @ (posedge clk) push(32); @ (posedge clk) push(110); @ (posedge clk) push(55); @ (posedge clk) push(210); @ (posedge clk) pop(temp_data); @ (posedge clk) pop(temp_data); @ (posedge clk) pop(temp_data); @ (posedge clk) pop(temp_data); @ (posedge clk) pop(temp_data); @ (posedge clk) push(77); @ (posedge clk) push(88); @ (posedge clk) pop(temp_data); end /*push(127); push(64); pop(temp_data); push(32); push(110); push(55); push(210); pop(temp_data); pop(temp_data); pop(temp_data); pop(temp_data); pop(temp_data); push(77); push(88); pop(temp_data); end*/ always #5 clk<=~clk; task pop; output [7:0] temp_data; begin if (!buf_empty) begin temp_data = buf_out; temp_data_out = temp_data; rd_en=1'b1; /*@(posedge clk)*/ #2 rd_en=0; $display("fifo_counter= %d Popped data= %d",fifo_counter,buf_out); $display("temp_data_out= %d",temp_data_out); end else $display("buffer empty"); end endtask task push; input [7:0] temp_data; begin if (!buf_full) begin buf_in = temp_data; temp_data_out = buf_in; $display("fifo_counter=%dPushed data= %d",fifo_counter,buf_in); $display("temp_data_out=%d",temp_data_out); wr_en =1'b1; /*@(posedge clk)*/#2 wr_en = 0; end else $display ("buffer full"); end endtask endmodule
Code dot - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 fifo_counter= 0Pushed data= 127 temp_data_out=127 fifo_counter= 1Pushed data= 64 temp_data_out= 64 fifo_counter= 1 Popped data= 127 temp_data_out= 0 fifo_counter= 1Pushed data= 32 temp_data_out= 32 fifo_counter= 2Pushed data= 110 temp_data_out=110 fifo_counter= 3Pushed data= 55 temp_data_out= 55 buffer full fifo_counter= 3 Popped data= 64 temp_data_out= 127 fifo_counter= 2 Popped data= 32 temp_data_out= 64 fifo_counter= 1 Popped data= 110 temp_data_out= 32 fifo_counter= 0 Popped data= 55 temp_data_out= 110 buffer empty fifo_counter= 0Pushed data= 77 temp_data_out= 77 fifo_counter= 1Pushed data= 88 temp_data_out= 88 fifo_counter= 1 Popped data= 77 temp_data_out= 55
Never said to synchronize every push pop only the first (reread post #8), as you added a @(posedge clk) on every push/pop you've just delayed everything by another clock cycle as there is already a @(posedge clk) inside the tasks. If you wanted to transfer on every clock cycle you needed to only have the single @(posedge clk) to synchronize the beginning first push/pop to the clock edge then all the reset of them would be synchronous to the clock edges by default due to the @(psoedge clk) inside the task.Dear Sir,
As per your suggestion I completely reworked the entire code and test bench to synchronize with clock.
The relevant source code is as follows:
module tb_NoC_RG()
reg clk,rst,rd_en,wr_en;
reg [7:0] buf_in;
wire [7:0] buf_out;
wire [3:0] fifo_counter;
reg [7:0] temp_data,temp_data_out;
reg counter_full,counter_empty;
fifo_buf fb1 (.clk(clk),.rst(rst),.rd_en(rd_en),.wr_en(wr_en),.buf_full(buf_full),.buf_empty(buf_empty),.buf_in(buf_in),.buf_out(buf_out),.fifo_counter(fifo_counter));
initial
begin
clk=0;
rst=1;
rd_en=0;
wr_en=0;
//temp_data=0;
//buf_in=0;
#3 rst=0;
//buf_empty=0;
//buf_full=0;
@ (posedge clk) push(127);
/*@ (posedge clk)*/ push(64);
/*@ (posedge clk)*/ pop(temp_data);
/*@ (posedge clk)*/ push(32);
/*@ (posedge clk)*/ push(110);
/*@ (posedge clk)*/ push(55);
/*@ (posedge clk)*/ push(210);
/*@ (posedge clk)*/ pop(temp_data);
/*@ (posedge clk)*/ pop(temp_data);
/*@ (posedge clk)*/ pop(temp_data);
/*@ (posedge clk)*/ pop(temp_data);
/*@ (posedge clk)*/pop(temp_data);
/*@ (posedge clk)*/ push(77);
/*@ (posedge clk)*/push(88);
/*@ (posedge clk)*/ pop(temp_data);
end
/*push(127);
push(64);
pop(temp_data);
push(32);
push(110);
push(55);
push(210);
pop(temp_data);
pop(temp_data);
pop(temp_data);
pop(temp_data);
pop(temp_data);
push(77);
push(88);
pop(temp_data);
end*/
always
#5 clk<=~clk;
task pop;
output [7:0] temp_data;
begin
@(posedge clk)
begin
if (!buf_empty)
begin
temp_data = buf_out;
temp_data_out = temp_data;
rd_en=1'b1;
/*@(posedge clk)*/ #2 rd_en=0;
$display("fifo_counter= %d Popped data= %d",fifo_counter,buf_out);
$display("temp_data_out= %d",temp_data_out);
end
else
$display("buffer empty");
end
end
endtask
task push;
input [7:0] temp_data;
begin
@(posedge clk)
begin
if (!buf_full)
begin
buf_in = temp_data;
temp_data_out = buf_in;
$display("fifo_counter=%dPushed data= %d",fifo_counter,buf_in);
$display("temp_data_out=%d",temp_data_out);
wr_en =1'b1;
/*@(posedge clk)*/#2 wr_en = 0;
end
else
$display ("buffer full");
end
end
endtask
endmodule
temp_data = buf_out;
temp_data_out = temp_data;
rd_en=1'b1;
While temp_data value is populated, it takes some time for it to get assigned (register delay) with new value. Immediate assignment of temp_data_out populates only old value of temp_data to temp_data_out. Adding some delay to temp_data_out gives correct results.
I want confirmation of my analysis from forum members on my understanding.
Thanks.
Yours sincerely,
R. Ganesan.
That is what I was alluding to in my previous post. I never apply data to a UUT using a task directly I always delay the outputs of the task by a #1 so they don't fall on the clock edge as what you are seeing could happen depending on the delta delays of your code. In fact I usually add in what I expect the external delays will actually be as a parameter constant. Though once you do this you will notice the same issue I saw with the delayed handling of the full and empty flags (you over/underflow the FIFO).ads-ee said:If you change the code to correctly delay the testbench inputs to the FIFO UUT code then the simulation fails due to the handling of the full and empty flags. As they would actually be delayed in real hardware.
task
...
task_output = something;
...
endtask
always @* uut_input = task_output;
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?