Memory code errors in Verilog - verilog

I write Verilog program to simulate memory transfer to Temp , but i got a lot of errors, help please.
wire [64:0] temp,mem [0:256];
wire [15:0] w0, w1, w2, w3;
wire [7:0] block_nr;
integer i ;
for ( i=0; i <3; i = i + 1) begin
temp = mem [i];
data_mem [i] = {block_nr, w0,w1, w2, w3 };
block_nr = block_nr +1;
end

5There are many errors in your code. Here are some:
a) Instead of this:
wire [64:0] temp,mem [0:256];
perhaps you mean this?
wire [64:0] mem [0:256]; // this might be a reg, too, one cannot tell from your code snippet
reg [64:0] temp;
i) I don't think you meant temp to be a 65x257 array as well as mem? And did you mean "64"? Or "63"? Or (see below) "71"? And did you mean "256"? Or "255"?
ii) You cannot assign to a wire from inside a procedural block.
b) This needs to be a reg, too, because (again) you cannot assign to a wire from inside a procedural block.
reg [7:0] block_nr;
c) This code needs to go inside a procedural block, either initial or always. Which depends on your design intent - I cannot tell this from your snippet of code. Let's assume initial:
initial begin
for ( i=0; i <3; i = i + 1) begin
temp = mem [i];
data_mem [i] = {block_nr, w0,w1, w2, w3 }; // what is "data_mem"? Did you mean "mem"?
// if you did mean "mem", did you notice that "{block_nr, w0,w1, w2, w3 }" is 72 bits wide?
block_nr = block_nr +1;
end
end
If this is intended to be synthesised, the you cannot use initial. If you do intend to synthesise this, you are a long way from a working solution.
I must emphasise, however, that these are merely suggestions. It is not possible to completely correct errors in code whose design intent is not known.

Related

Why is this counter assignment wrong?

I am learning Verilog using the HDLBits website, and I solved this problem (circuit counts the number of '1's in an input vector), but I want to understand why my previous tries were wrong.
correct answer
module top_module(
input [254:0] in,
output [7:0] out );
int i ;
reg [7:0] counter;
always #(*) begin
counter =0;
for (i=0;i<255;i++)begin
counter = (in[i]==1)? counter+1:counter;
end
out = counter ;
end
endmodule
1st wrong answer
module top_module(
input [254:0] in,
output [7:0] out );
int i ;
reg [7:0] counter;
always #(*) begin
counter =0;
for (i=0;i<255;i++)begin
counter = (in[i]==1)? counter+1:counter;
end
end
out = counter ;
endmodule
2nd wrong answer
module top_module(
input [254:0] in,
output [7:0] out );
int i ;
always #(*) begin
out=0;
for (i=0;i<255;i++)begin
out = (in[i]==1)? out+1:out;
end
end
endmodule
All 3 code samples have syntax errors. If the HDLBits website did not report errors, try the EDA Playground website simulators.
In your "correct" answer you need to change
output [7:0] out );
to:
output reg [7:0] out );
When you make an assignment to a signal inside an always block (a procedural assignment), you need to declare the signal as a reg.
In your "1st wrong answer", change:
out = counter ;
to:
assign out = counter ;
Continuous assignments (outside of always blocks) require the assign keyword.
In your "2nd wrong answer", use reg for out.

In Verilog, counting and outputting the number of 1's in an 8bit input?

What I am trying to do in my mind is take 8 1-bit inputs and count the 1's. Then represent those 1's.
01010111 should output 0101 (There are five 1's from input)
module 8to4 (in,out,hold,clk,reset);
input [7:0] in; //1 bit inputs
reg [7:0] hold; //possible use for case statement
output [3:0] out; //Shows the count of bits
always #(clk)
begin
out = in[0] + in[1] + in[2] + in[3] + in[4] + in[5] + in[6] + in[7]; //Adds the inputs from testbench and outputs it
end
endmodule
Questions:
Is that the proper way to have 8 1-bit inputs? Or do I need to declare each variable as one bit ex: input A,B,C,D,E,F,G,H;
If my above code is close to being correct, is that the proper way to get out to display the count of 1's? Would I need a case statement?
I'm really new to verilog, so I don't even want to think about a test bench yet.
The way you wrote it is probably the better way of writing it because it makes it easier to parameterize the number of bits. But technically, you have one 8-bit input.
module 8to4 #(parameter WIDTH=8) (input [WIDTH-1:0] in,
output reg [3:0] out,hold,
input clk,reset);
reg [WIDTH-1:0] temp;
integer ii;
always #(clk)
begin
temp = 0;
for(ii=0; ii<WIDTH; i = i + 1)
temp = temp + in[ii];
out <= temp;
end
endmodule
Logically the code is proper.
However you can improve it like the following.
Make out as a reg, because you are using it in a procedural assignment.
Usage of reset. Ideally any code should have reset state, which is missing in your code.
Declare the direction (input/output) for hold, clk & reset port, which is currently not specified.
As dave mentioned, you can use parameters for your code.

Data memory unit

I started Verilog a few weeks ago and now I'm implementing MIPS pipelining on an FPGA board and I'm on the MEM part of the pipelining stage. I'm trying to code the Data memory unit (in picture -> Data memory Unit).
I don't understand the use of memread. I understand that if memwrite is 1, the contents of the current address is passed to read data.
So far, this is my code:
module data_memory (
input wire [31:0] addr, // Memory Address
input wire [31:0] write_data, // Memory Address Contents
input wire memwrite, memread,
output reg [31:0] read_data // Output of Memory Address Contents
);
reg [31:0] MEMO[0:255]; // 256 words of 32-bit memory
integer i;
initial begin
read_data <= 0;
for (i = 0; i < 256; i = i + 1)
MEMO[i] = i;
end
always # (addr) begin
//**I don't understand the use of memread**//
if (memwrite == 1'b1)
MEMO[addr] <= write_data;
end
end
assign read_data = MEMO[addr];
endmodule
Do I need another if statement for the memread? Any help is greatly appreciated. Thanks
In the design you have coded above, you dont use memread, instead choosing to combinationally read from the memory via the last line of your module. And without more details on how exactly the memory in your diagram is suppose to function, its difficult to say the exact usage of memread. Typical memories only have a memwrite and assume that if an address is supplied and memwrite is deasserted, the access is a read. In this case, I can only assuming memread should be asserted to read from the memory. Also, I would suggest a few edits to your code to make it work better and follow a better synchronous design style (this will incorporate memread so you can see how it can be used):
module data_memory (
input wire [31:0] addr, // Memory Address
input wire [31:0] write_data, // Memory Address Contents
input wire memwrite, memread,
input wire clk, // All synchronous elements, including memories, should have a clock signal
output reg [31:0] read_data // Output of Memory Address Contents
);
reg [31:0] MEMO[0:255]; // 256 words of 32-bit memory
integer i;
initial begin
read_data <= 0;
for (i = 0; i < 256; i = i + 1) begin
MEMO[i] = i;
end
end
// Using #(addr) will lead to unexpected behavior as memories are synchronous elements like registers
always #(posedge clk) begin
if (memwrite == 1'b1) begin
MEMO[addr] <= write_data;
end
// Use memread to indicate a valid address is on the line and read the memory into a register at that address when memread is asserted
if (memread == 1'b1) begin
read_data <= MEMO[addr];
end
end
endmodule
Important to note also the need for a clock in your design. Most block diagrams at that level will omit the clock as it is assumed but all synchronous elements (memories and registers) will be synchronized to a common clock (or multiple clocks in some cases).
#Unn gives excellent answer, moreover I just want add that, if you not use read_enable, Then it may unsynchronised data read operation, It is also preferred to flop the output read_data on read_clk.
Here with see below templent for reference.
parameter RAM_WIDTH = <ram_width>;
parameter RAM_ADDR_BITS = <ram_addr_bits>;
(* RAM_STYLE="{AUTO | BLOCK | BLOCK_POWER1 | BLOCK_POWER2}" *)
reg [RAM_WIDTH-1:0] <ram_name> [(2**RAM_ADDR_BITS)-1:0];
reg [RAM_WIDTH-1:0] <output_dataB>;
<reg_or_wire> [RAM_ADDR_BITS-1:0] <addressA>, <addressB>;
<reg_or_wire> [RAM_WIDTH-1:0] <input_dataA>;
// The forllowing code is only necessary if you wish to initialize the RAM
// contents via an external file (use $readmemb for binary data)
initial
$readmemh("<data_file_name>", <ram_name>, <begin_address>, <end_address>);
always #(posedge <clockA>)
if (<enableA>)
if (<write_enableA>)
<ram_name>[<addressA>] <= <input_dataA>;
always #(posedge <clockB>)
if (<enableB>)
<output_dataB> <= <ram_name>[<addressB>];

Declaring Variable in Verilog with Indexing that doesn't start at zero

I am using this wire declaration in Verilog:
wire [23:15] myvar;
My code works and I have seen this coding style before, but I am not sure what is actually happening, I can only guess that a wire that is 9 bits wide is getting declared. Is that what is happening? I wanted to read more on this online, but i didn't know what this is called, so apologies for the simplistic question.
Verilog is a Hardware Descriptive Language(HDL). Whatever you write/declare, ultimately turns out to be a form of hardware.
Lets have a look at the image below:
Here, declaring wire [23:15] myvar; or wire [8:0] myvar; declares the same bunch of wires, nine bits wide. Its just the indexing part that differs. No matter you call it as a[0] (when a is wire [8:0] a) or a[15] (when a is wire [23:15] a). The coding part is different according to the ease for programmer, while synthesis part remains the same.
Also, note that in former case, myvar[15] is the least significant bit while latter has myvar[0] as the LSB. We can swap the declarations part, which shall swap the MSB-LSB too.
reg [7:0] reg1; // 8-bit vector with MSB=7 LSB=0
reg [0:7] reg2; // 8-bit vector with MSB=0 LSB=7
// ...
// ...
reg1 = 8'hF0; // reg1[7] = 1 and reg1[0] = 0 ultimately, reg1 = F0
reg2 = 8'hF0; // reg2[7] = 0 and reg2[0] = 1 ultimately, reg2 = F0
Lets take an example:
wire [23:15] myvar;
reg [23:15] reg2;
reg [31:0] reg3;
initial begin
$monitor("myvar = %0h myvar2 = %0h reg3 = %0h",myvar,myvar2,reg3);
reg3 = 32'h5ABC_FEDC;
// This will correctly assign values to reg2, since it is [23:15]
for(int i=16;i<20;i++)
begin
reg2[i] = myvar[i];
$display("1: reg2[%0d] = %0h myvar[%0d] = %0h",i,reg2[i],i,myvar[i]);
end
// While, this will not assign correctly,
// since reg2 does not have [5:0] indexes,neither does myvar
for(int i=0;i<5;i++)
begin
reg2[i] = myvar[i];
$display("2: reg2[%0d] = %0h myvar[%0d] = %0h",i,reg2[i],i,myvar[i]);
end
end
Another alternative is that your reg is [8:0] while wire is [23:0]. Here is all that matters, but just in the coding part. Note that in the first snippet below, values are assigned to reg1[4:0] and in the second snippet, it is in the range reg1[20:15].
reg [8:0] reg1;
wire [23:15] myvar;
// Correct, since LSB of myvar is at index position 15
for(int i=0;i<5;i++)
begin
reg1[i] = myvar[i+15];
$display("3 : reg1[%0d] = %0h myvar[%0d] = %0h",i,reg1[i],i,myvar[i+15]);
end
reg [31:0] reg1;
wire [23:15] myvar;
// reg1[19:15] is assigned here
for(int i=15;i<20;i++)
begin
reg1[i] = myvar[i];
$display("4 : reg1[%0d] = %0h myvar[%0d] = %0h",i,reg1[i],i,myvar[i]);
end
So, in the end, just some slicing differs while driving from the wire, no effect on the actual hardware. More information can be obtained from Verilog Syntax Details link.
You are correct that you are declaring a 9-bit wire. Many designs have different ideas about what the LSB and MSB values should be, which direction the index numbering should go in. It really doesn't matter what use for index values until you start referencing individual bit or slices.

Testbench of floating point adder in verilog

I want to write floating point double precision adder. in the test-bench of that, I have some problems.
*adder is a module which gets two 64bits number and give sum of them.
this is my test bench:
module testadder;
reg [63:0] a;
reg [63:0] b;
wire [63:0] sum;
reg[10:0] expa,expb,expsum;
reg signa,signb,signsum,one;
reg[51:0] fa,fb,fsum;
real ta,tb,fa2,fb2,sumcheck,fsum2,resultmodulesum;
integer i;
reg [10:0]h23;
adder nameofinstance(sum,a,b);
initial begin
for(i=0;i<1000;i=i+1)
begin
h23=1023;
one=1'b1;
a = {$random(),$random()};
b = {$random(),$random()};
#10;
expa=a[62:52]-h23;
expb=b[62:52]-h23;
fa=a[51:0];
fb=b[51:0];
signa=a[63];
signb=b[63];
fa2 = ( $bitstoreal(fa)/(2**52) )+ one ;
ta=(-1)**(signa)*fa2*(2**expa);
fb2 = ( $bitstoreal(fb)/(2**52) ) + one;
tb=(-1)**(signb)*fb2*(2**expb);
sumcheck=ta+tb;
fsum=sum[51:0];
signsum=sum[63];
fsum2 = ( $bitstoreal(fsum)/(2**52) ) +one;
expsum=$bitstoreal(sum[62:52])-1023;
resultmodulesum=(-1)**(signsum)*fsum2*(2**expsum);
if(sumcheck!=resultmodulesum)
$display("wrong");
end
end
endmodule
module adder(sum,a, b);
input [63:0] a;
input [63:0] b;
reg [63:0] fa,fb;
always #(a or b) begin
fa={1'b1,a[51:0],12'b0};
fb={1'b1,b[51:0],12'b0};
end
endmodule
when i add ( $bitstoreal(fa)/(2**52) ) with one , fa2 get 1 ! but when i don't add it , fa2 get real value of (fa/2^52).
so I change my code to something like that to avoid adding with one, but another problem appears!
my change for making ta,tb and resultmodulesum:
(example for fa)
fa2 = ( $bitstoreal(fa)/(2**52) ) ;
ta=(-1)**(signa)*(fa2*(2**expa)+(2**expa));
2.then i understand that ta always get to (-1)**(signa)*(2**expa);
it means that fa2*(2**expa) is 0 ! but i don't know why and what can I do to make it correct.
I think that even if I didn't change my fa2 and fa2 (with one added in it) give correct output, my ta might has a problem.
3.I have another problem in my module that it is really strange!
little part of adder code module comes after test-bench code.
it is that when i debug my code, 63th bit of fb is 0! any idea?
This is not a full answer but more than can be expressed in the comments.
For the model of the floating point double I would have expected to see something along the lines of:
reg [63:0] a;
reg [63:0] b;
//Built in real for verification of code
real result;
real a_real;
real b_real;
initial begin
a = {$random(),$random()};
b = {$random(),$random()};
#1ps;
a_real = $bitstoreal(a);
b_real = $bitstoreal(b);
result = a_real + b_real;
$display("a %64b", a);
$display("b %64b", b);
$display("a_real %f", a_real);
$display("b_real %g", b_real);
$display("result %f", result);
#1ps;
$finish;
end
For splitting the randomised doubles up in to parts I would have expected to see some thing like:
wire a_sign; // 1 bit
wire [10:0] a_exponent;//11 bit
wire [51:0] a_fraction;//52 bit
assign a_sign = a[63] ;
assign a_exponent = a[62:52];
assign a_fraction = a[51:0] ;
wire b_sign; // 1 bit
wire [10:0] b_exponent;//11 bit
wire [51:0] b_fraction;//52 bit
assign b_sign = b[63] ;
assign b_exponent = b[62:52];
assign b_fraction = b[51:0] ;

Resources