Verilog asynch mem in Xilinx - verilog

I am trying to create a memory shift operation in verilog and was wondering the best way to do it. An example code is:
reg [MSB:0] a [0:NO_OF_LOCATIONS];
// after some processing
for(i =0; i <= NO_OF_LOCATIONS; i= i+1)
a[i] = a[i+1]
If I use a ROM in Xilinx it can only do synchronize writes and I need to do all the shifts within one clock cycle. If I do use a memory as above I am not sure if on board implementation will result in metastability or don't care propagation.
Also what would be the best way to do it instead of a for loop?

I am assuming this is part of a clocked synchronous block, i.e. something like the following (it would not make much sense otherwise and you wrote "I need to do all the shifts within one clock cycle", which implies that this is part of a synchronous design):
reg [MSB:0] a [0:NO_OF_LOCATIONS];
always #(posedge clk)
if (...) begin
for(i =0; i < NO_OF_LOCATIONS; i= i+1)
a[i] <= a[i+1];
a[NO_OF_LOCATIONS] <= ...;
end
// also use a[] somewhere
assign a0 = a[0];
Btw: a[] has NO_OF_LOCATIONS+1 locations in it. I'm not sure if this is intended but I just left it that way. Usually the range of a[] would be written as [0:NO_OF_LOCATIONS-1] for NO_OF_LOCATIONS memory locations.
Notice that I have changed the assignment = to <=. When assigning something in a clocked always-block and the thing you assign to is read anywhere outside that always-block then you must assign non-blocking (i.e. with <=) in order to avoid race conditions in simulation that can lead to simulation-synthesis mismatches.
Also notice that I have factored out the assignment to a[NO_OF_LOCATIONS], as it would have got its value from a[NO_OF_LOCATIONS+1], which is out-of-bounds and thus would always be undef. Without that change the synthesis tool would be right to assume that all elements of a[] are constant undef and would simply replace all reads on that array with constant 'bx.
This is perfectly fine code. I'm not sure why you brought up metastability but as long as the ... expressions are synchronous to clk there is no metastability in this circuit. But it does not really model a memory. Well, it does, but one with NO_OF_LOCATIONS write ports and NO_OF_LOCATIONS read ports (only counting the read ports inferred by that for-loop). Even if you had such a memory: it would be very inefficient to use it like that because the expensive thing about a memory port is its capability to address any memory location, but all the ports in this example have a constant memory address (i is constant after unrolling the for-loop). So this huge number of read and write ports will force the synthesis tool to implement that memory as a pile of individual registers. However, if your target architecture has dedicated shift register resources (such as many fpgas do), then this might be transformed to a shift register.
For large values of NO_OF_LOCATIONS you might consider implementing a fifo using cursor(s) into the memory instead of shifting the content of the entire memory from one element to the next. This would only infer one write port and no read port from inside the for-loop. For example:
reg [MSB:0] a [0:NO_OF_LOCATIONS];
parameter CURSOR_WIDTH = $clog2(NO_OF_LOCATIONS+1);
reg [CURSOR_WIDTH-1:0] cursor = 0;
always #(posedge clk)
if (...) begin
a[cursor] <= ...;
cursor <= cursor == NO_OF_LOCATIONS ? 0 : cursor+1;
end
assign a0 = a[cursor];

Related

Verilog module generates impossible data when running on FPGA

I’m developing a boolean data logger on a ZYNQ 7000 SoC. The logger takes a boolean input from GPIO and logs the input’s value and the time it takes to flip.
I use a 32-bit register as a log entry, the MSB bit is the boolean value. The 30:0 bits is an unsigned integer which records the time between last 2 flips. The logger should work like the following picture.
Here's my implementation of the logger in Verilog. To read the logged data from the processor, I use an AXI slave interface generated by vivado and inline my logger in the AXI module.
module BoolLogger_AXI #(
parameter BufferDepth = 512
)(
input wire data_in, // boolean input
input wire S_AXI_ACLK, // clock
input wire S_AXI_ARESETN, // reset_n
// other AXI signals
);
wire slv_reg_wren; // write enable of AXI interface
reg[31:0] buff[0:BufferDepth-1];
reg[15:0] idx;
reg[31:0] count;
reg last_data;
always #(posedge S_AXI_ACLK) begin
if((!S_AXI_ARESETN) || slv_reg_wren) begin
idx <= 0;
count <= 1;
last_data <= data_in;
end else begin
if(last_data!=data_in) begin // add an entry only when input flips
last_data <= data_in;
if(idx < BufferDepth) begin // stop logging if buffer is full
buff[idx] <= count | (data_in << 31);
idx <= idx + 1;
end
count <= 1;
end else begin
count <= count + 1;
end
end
end
//other AXI stuff
endmodule
In the AXI module, the 512*32bit logged data is mapped to addresses from 0x43c20000 to 0x43c20800.
In the Verilog code, the logger adds a new entry only when the boolean input flips. In simulation, the module works as expected. But in the FPGA, sometimes the logged data is not valid. There are successive 2 data and their MSB bit is the same, which means the entry is added even when the boolean input stays the same.
The invalid data appear from time to time. I've tried reading from the address programmatically (*(u32*)(0x43c20000+4*idx)), and there are still invalid data. I watch idx in a ILA module and idx is 512, which means the logging finishes when I read the data.
The FPGA clock is 10 MHz. The input signal is 10 Hz. So the typical period is 10e6/10/2=0x7A120, which most of the data is close to, except the invalid data.
I think if the Verilog code is implemented well, there should be no such invalid data. What may be the problem? Is this an issue about timing?
The code
First off, are you absolutely sure you are not issuing an accidental write on the AXI bus, resetting the registers?
If so, have you tried inserting a so-called double-flop on data_in (two flip-flops, delaying the signal two clock ticks)? I suppose that your data_in is not synchronous to the FPGA clock, which will lead to metastability and you having bad days if not accounted for. Have a look here for information by NANDLAND.
Citing the linked source:
If you have ever tried to sample some input to your FPGA, such as a button press, or if you have had to cross clock domains, you have had to deal with Metastability. A metastable state is one in which the output of a Flip-Flop inside of your FPGA is unknown, or non-deterministic. When a metastable condition occurs, there is no way to tell if the output of your Flip-Flop is going to be a 1 or a 0. A metastable condition occurs when setup or hold times are violated.
Metastability is bad. It can cause your FPGA to exhibit very strange behavior.
In that source there is also a link to a white paper from Altera about the topic of metastability, linked here for reference.
Citing from that paper:
When a metastable signal does not resolve in the allotted time, a logic failure can result if the destination logic observes inconsistent logic states, that is, different destination registers capture different values for the metastable signal.
and
To minimize the failures due to metastability in asynchronous signal transfers, circuit designers typically use a sequence of registers (a synchronization register chain or synchronizer) in the destination clock domain to resynchronize the signal to the new clock domain. These registers allow additional time for a potentially metastable signal to resolve to a known value before the signal is used in the rest of the design.
Basically having the asynchronous signal routed to two flip-flops might for example lead to one FF reading a 1 and one FF reading a 0. This in turn could lead to the data point being saved, but the counter not being reset to 0 (hence doubling the measured time) and the bit being saved as 0.
Finally, it seems to me, that you are using the Vivado-generated example AXI core. Dan Gisselquist simply calls it "broken". This might not be the problem here, but you might want to have a look at his posts and his AXI core design.

Fast array inner access in verilog

I have some lines of code below:
wire [WIDTH_PIXEL-1:0] x_vector [0:36];
wire [6-1:0] x_sample [0:511]; // 0 <= x_sample <= 36
reg [WIDTH_PIXEL-1:0] rx_512 [0:511];
genvar p;
generate
for(p=0;p<=511;p=p+1) begin: PPP
always#(posedge clk) begin
if(x_sample[p] == counter2) begin
rx_512[p] <= x_vector[x_sample[p]];
end
end
I want to save 512 x_vector elements whose address is the value of x_sample[p]. The problem is when I synthesize on Quartus, the total LC-combinationals over 50000. I know the problem lies on the line
rx_512[p] <= x_vector[x_sample[p]];
So is there any way for improving the access memory? Thank you.
Keep in mind that Verilog is meant as a hardware emulation language.
This makes that you have to learn to write two different types of code:
Code that gets converted to hardware
Test bench code
For the former there are a lot more restrictions. As you correctly noticed you get 512 comparators each comparing 6 bits plus each conditionally selecting one of 37 PIXELWIDTH values and assigning it to one of 512 PIXELWIDTH destinations. My guess is easily a million gates.
You have to use a divide an conquer approach. As Qiu says make the code sequential: One operation per clock cycle. It will take more clock cycles but a lot less logic. Unfortunately you might find out that you do not have enough time to e.g. process a whole image in that (frame?) time. Then choose to do two or four operations per cycle.
You have to continuously weigh speed versus number of gates & power. Maybe you find out that you can't do the operations at all with the chosen hardware. (Nobody said writing Verilog was easy!)
I don't know if it helps but you can make the compiler/optimizer's life a bit easier if you use:
rx_512[p] <= x_vector[counter2];

accessing elements of an multiply instantiated module

I am trying to write a behavioral code in verilog describing a RAM that has 256 locations, each of size 64-bits. so, I created a module RAM_cell that has output data_out and input data_in,both of width 64 bits. then, I created another module called RAM within which, I declared,
RAM_cell mem [255:0] (data_out,data_in,rd);
the RAM reads from 8-bit Maddr when rd=1 or writes to Maddrwhen rd=0.Now
in the module RAM, which has Mdata_out as output, for read operation, I wrote,
always #(posedge clk)
initial
begin
if (rd == 1'b1)
Mdata_in = mem[Maddr].data_out;
end
that didn't work. the compiler threw error that the indexing variable is not a constant.
Why didn't it work? what are the other ways (Other than using case statement using 256 control signals..!!).
Thank you. Any help will be highly appreciated.
PS: I can upload all necessary data (like exact code,compiler output,etc..) on demand.
This is similar to the generate..endgenerate. the compiler allocates the number of instances you required. The array index will become a part of the name.
So it will create 256 uniquely named instances like m[0], m[1], ... where '[]' will be just a part of the generated name. You cannot index into it. There is no such name as 'mem[Maddr]'
So, instead you should index your data_out.
I do not recommend using this construct at all due to confusing syntax around it. Instead use a generate block and a for loop to instantiate it. In this case you would have a complete control over what you pass to it:
generate
for(geni = 0; geni < 256; geni++) begin: loop
RAM_cell mem (data_out[geni],data_in[geni],rd);
end
endgenerate
always #* begin
...
Mdata_in = data_out[Maddr];
...
end
If you insist on XMR (non synthesizable) to access internal signals in the 'mem', you can put your always block inside the 'for' loop and use 'mem.sig'

How to initialize contents of inferred Block RAM (BRAM) in Verilog

I am having trouble initializing the contents of an inferred ram in Verilog. The code for the ram is as below:
module ram(
input clock, // System clock
input we, // When high RAM sets data in input lines to given address
input [13:0] data_in, // Data lines to write to memory
input [10:0] addr_in, // Address lines for saving data to memory
input [10:0] addr_out, // Address for reading from ram
output reg data_out // Data out
);
reg [13:0] ram[2047:0];
// Initialize RAM from file
// WHAT SHOULD GO HERE?
always #(posedge clock) begin
// Save data to RAM
if (we) begin
ram[addr_in] <= data_in;
end
// Place data from RAM
data_out <= ram[addr_out];
end
endmodule
I have run into the command $readmemh. However, documentation for it seems sparse. How should I format the file that contains the data? Also, how can I pass the file as argument when instantiating this module so that I can have different instances of this module load from different files?
I want the initialized content to be available for both simulation and actual implementation. So that the FPGA already boots with this content in RAM.
I am using Vivado 2015.4 to program a Kintex xc7k70 FPGA.
You are correct that you should use $readmemh inside an initial block. In order to make it so different instances of the module can have different initialization files, you should use a parameter like so:
parameter MEM_INIT_FILE = "";
...
initial begin
if (MEM_INIT_FILE != "") begin
$readmemh(MEM_INIT_FILE, ram);
end
end
The format is described in Section 21.4 of the IEEE1800-2012 specification; typically the file is just a bunch of lines containing hex numbers of the correct bit-length, like so:
0001
1234
3FFF
1B34
...
Note that there is no "0x" prefix and each line represents an adjacent address (or any separating whitespace). In the example above, $readmemh would put 14'h0001 into ram[0], 14'h1234 into ram[1], 14'h3FFF into ram[2] and so on. You can also include comments in the hex file using // or /* */. Finally, you can use the # symbol to designate an address for the following numbers to be located at, like so:
#0002
0101
0A0A
...
In the above file, ram[0] and ram[1] would be uninitialized and ram[2] would get 14'h0101. Those are all the major constructs of the hex file format, though you can also use _, x and z as you would in other Verilog numbers and theres a few more rules you can read in the section sited above.
Apart from #Unn's excellent ans, I want to add that, If you just want to initialize your memory with either all bits to 1'b1 or 1'b0, then you can just put following code,
integer j;
initial
for(j = 0; j < DEPTH; j = j+1)
ram[j] = {WIDTH{MEM_INIT_VAL}};
For your case, WIDTH=14, and MEM_INIT_VAL may be 1'b1 or 1'b0.
Since your question cited the #xilinx and #vivado tags, I wanted to suggest that you can also use the xpm_memory family of primitives to instantiate a parameterized memory. The advantages of this approach:
Exports exactly the hardware capabilities of the memory resources on the FPGA (ie, makes you think clearly about limitations such as memory ports).
Guarantees correct identical behavior in simulation and benchtop for memory primitives.
You can allow Vivado to choose the most efficient memory implementation (BRAM, UltraRAM, distributed RAM, flops) at synthesis time, according to your design constraints.
Easy to fine tune (enable or disable internal pipeline stages, etc.).
With that said, purely inferred memories are often easier to code. But, it's still worth getting familiar with the Xilinx-provided memory primitives so that you'll have a clearer idea of what Vivado can easily synthesize, and what it can't.
For more information, see UG573, the Vivado Memory Resources User Guide:
https://www.xilinx.com/support/documentation/user_guides/ug573-ultrascale-memory-resources.pdf
integer j;
initial
for(j = 0; j < DEPTH; j = j+1)
ram[j] = j;
This might be easy in case of debug, where the value of a location is its location number.
Also, I would suggest you to not initialize the RAMs. It will help you in catching bugs, if any, in simulation as the data driven will be 'x if RAM is un-intialized and can be caught easily.

Reconstructing variable sized packets in verilog

I am trying to reconstruct a packet that was sent via UART RS232 connections, but am not sure how to reconstruct the packet in its entirety such that the packet can be taken apart and stuff can be done using it.
The issue is that when I receive 1 byte at a time, I store that byte into a register 8 bits wide, and when I receive the next byte, I want to be able to shift the first byte by 8 bits, then add the new byte to the end. This becomes an issue as the register is now too small (8 bits vs 16 bits to hold the next byte). In addition, I cannot see a way to change the size of the register during runtime to grow and shrink depending on the size of the packet, as all registers must be static, and I also must know the exact size of the packet in order to process it.
There is the possibility of setting up an insanely large register to hold the packet, and counting how many valid bytes were copied into the register, but I am sure there is a better way to do this that I am not seeing.
All this is done using Xilinx ISE.
Verilog is static to mimic physical design. You will need to know the maximum number of bytes that can be supported. To know the size of the input, simply incompetent a counter as the data bytes shift. The only way to have a dynamic size is if this is for non-synthesizable behavior modeling then you can use C code to link into your design (PLI/VPI/DPI) or SystemVerilog Queues (IEEE Std 1800-2012 section 7.10). Read-up about SystemVerilog if you are interested.
The follow is a Verilog example of a large shift register:
parameter SIZE = 2**10;
reg [SIZE*8-1:0] store;
always #(posedge clk or negedge rst_n) begin
if ( !rst_n ) begin
counter <= 0;
store <= {(SIZE*8){1'b0}};
end
else if ( push_in ) begin
counter <= first_byte ? 0 : (counter+1);
store <= {store[SIZE*8-1-8:0], data_in[7:0]};
end
end
With an "insanely large register" you may need to break up the store into chunks so the simulator can handle it; some simulators cannot handle reg [2**32-1:0] store;. Sudo code example:
// ...
storeN <= {store3[SIZE*8-1-8:0], storeM[7:0]};
// ...
store1 <= {store1[SIZE*8-1-8:0], store0[7:0]};
store0 <= {store0[SIZE*8-1-8:0], data_in[7:0]};
// ...

Resources