Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

inserting stuck at..faults to memory

579 views
Skip to first unread message

Daniel Prego

unread,
Nov 19, 2013, 12:12:42 PM11/19/13
to
Hi to all
I have a 2D array:reg [WordSize-1:0] ram[0:rows-1][0:cells-1];

now i need to inject faults to this memory module
for example: i need ram[3][4][1] to be stuck permanently at zero
that mean rows 3 column 4 , second lsb to be 0
constantly, even if a write operation is on

how can i do it? i wrote some code but its not very sophisticated, and not usable if i need to inject, lets say, 20 faults like this

so, how can i inject a permanent fault into a specific bit inside an array?

GaborSzakacs

unread,
Nov 19, 2013, 2:10:04 PM11/19/13
to
If you're doing this for simulation, I would think that the "force"
command should do what you want. This might depend on the simulator
you use, though. It's not really part of Verilog. The question is
whether the simulator's force command supports targets that are a
subset of a multidimensional array...

--
Gabor

GaborSzakacs

unread,
Nov 19, 2013, 2:23:16 PM11/19/13
to
Sorry about that, I was thinking of the command line "force" rather
than the Verilog "force." If you want to add the force to the
test bench, then it would be a Verilog command (clearly not
synthesizable).

something like:

initial begin
#1000 force ram[3] [4] [1] = 1'b0;
end

--
Gabor

Daniel

unread,
Nov 19, 2013, 2:51:53 PM11/19/13
to
thanks, i need to write a code that identify the errors
for that i need to module a rem and inject errors, so i dont think i need to synthesize this for now. a few questions :
1) if i am not mistaken, force cannot be applied to a specific bit inside a vector?
not sure

2)also, regarding your suggestion, if i put the force at the initial block. what happens when i try to write to that cell later on? or the #(insert time longer than all simulation) takes care of that?

3) if youre example works (going to try it now), is there a nice way i can load or generate several injections like this' instead of 25 lines with different addresses?

Daniel

unread,
Nov 19, 2013, 2:56:52 PM11/19/13
to
well, can i use an initial inside my memory module? or only inside the testbanch?
if only inside the TB, its a bit problematic. as the RAM configuration sits as a register inside the memory module and cannot be seen from the TB
TB access: addresses,data,clk,en. thats it

GaborSzakacs

unread,
Nov 19, 2013, 4:06:08 PM11/19/13
to
Daniel wrote:
[snip]

>
> well, can i use an initial inside my memory module? or only inside the testbanch?
> if only inside the TB, its a bit problematic. as the RAM configuration sits as a register inside the memory module and cannot be seen from the TB
> TB access: addresses,data,clk,en. thats it

Inside your synthesizable code you can place simulation-only
code if you use the synthesis translate_on/off pragmas:

// synthesis translate_off
initial begin
#1000 force ram[3] [4] [1] = 1'b0;
end
// synthesis translate_on

Some synthesizers will not complain even if you don't use the pragmas,
or you'll just get a warning that the force statement was ignored for
synthesis.

If you want to do this from the test bench, then you need to use the
hierarchical naming like:

// synthesis translate_off
initial begin
#1000 force uut.ram_instance.ram[3] [4] [1] = 1'b0;
end
// synthesis translate_on

Where in this case your synthesizable code is instantiated as "uut"
in the testbench and the RAM was one level down in a module instantiated
as "ram_instance."

Note that placing code for simulation inside your synthesizable code
will not work for post-synthesis timing simulation. That's because
the code is not translated during synthesis and thus doesn't end up
in the post synthesis simulation timing model. Also hierarchical
access from the test bench to the RAM bit gets tricky for post synthesis
translation because the name or path may change depending on synthesis
settings.

If you find that this works for individual bits (have you tried it yet?)
then I suppose you could make a memory-like structure in your test
bench that loads a list of bit locations and values from a file and
then use a loop to apply a force command for each entry in the file.

--
Gabor

Daniel

unread,
Nov 20, 2013, 12:24:57 PM11/20/13
to
i tried this in my memory module and ran a simulation. didnt get any error on compile, but also cant see that the bit was really stuck as i wanted it to be

Daniel

unread,
Nov 20, 2013, 1:47:34 PM11/20/13
to
Inserted it in the TB file and it worked great
so, if i want to make this "nice looking" or code writing apropriate, if i want to inject 20 faults like this? how can i do it beside writing 20+ lines of :

GaborSzakacs

unread,
Nov 20, 2013, 2:02:18 PM11/20/13
to
This may be simulator dependent. I tried it in Xilinx ISIM, and it
refused to force any part of an array or vector giving this error:

Bit-select or part-select is not allowed in a force statement for
non-net ram

where "ram" was the name of the array as in your example.

However I was able to effect a similar behavior with this code:

always @ (ram[2][2]) ram[2][2][2] = 0; // 0 after any attempt to change

This is of course permanently stuck, not just after some particular
time, however it could use an if statement to limit the "force" to
a particular time period.

--
Gabor

Daniel

unread,
Nov 20, 2013, 3:26:18 PM11/20/13
to
thanks Gabor!
as i mentioned, it worked ok for me through the TB
now i want to do this using a file
so, i thought of doing it using 3 different text files, one for rows one for column and one for bit select

i am trying to figure out how to do it using %fgets and a for loop.
thought about dong it like this:
initial
begin
for (i=0; i<10; i+1) begin // not sure how to move through the lines in text file
row=%fgets( not sure of opcode here)
column=%fgets( not sure of opcode here)
bit_select==%fgets( not sure of opcode here)
#1000 force memory.ram[row][column][bit_select] = 1'b0;
end
end

GaborSzakacs

unread,
Nov 20, 2013, 4:42:30 PM11/20/13
to
Daniel wrote:
>
> thanks Gabor!
> as i mentioned, it worked ok for me through the TB
> now i want to do this using a file
> so, i thought of doing it using 3 different text files, one for rows one for column and one for bit select
>
> i am trying to figure out how to do it using %fgets and a for loop.
> thought about dong it like this:
> initial
> begin
> for (i=0; i<10; i+1) begin // not sure how to move through the lines in text file
> row=%fgets( not sure of opcode here)
> column=%fgets( not sure of opcode here)
> bit_select==%fgets( not sure of opcode here)
> #1000 force memory.ram[row][column][bit_select] = 1'b0;
> end
> end

This works for me (I know $readmemh, $readmemb better than the streaming
file operators, so I used arrays for the row, column, etc.)


reg [7:0] ram[0:3][0:7];
reg [7:0] rows [0:9];
reg [7:0] cols [0:9];
reg [7:0] bits [0:9];
reg vals [0:9];

integer k;
initial begin
$readmemh ("row.txt",rows);
$readmemh ("col.txt",cols);
$readmemh ("bit.txt",bits);
$readmemb ("val.txt",vals);
for (k = 0;k < 10;k = k + 1)
begin
$display ("Want to force ram [%d] [%d] [%d] to %d", rows[k],
cols[k], bits[k], vals[k]);
// force ram[rows[k]][cols[k]][bits[k]] = vals[k]; // Doesn't work in
ISIM
end
end


Text File contents (each column in a separate file)

row.txt col.txt bit.txt val.txt

00 01 00 0
02 01 01 1
03 02 02 1
01 02 03 0
00 05 04 1
03 07 05 0
02 04 06 1
02 06 07 1
01 00 00 0
03 03 01 1

Simulation printout:

Want to force ram [ 0] [ 1] [ 0] to 0
Want to force ram [ 2] [ 1] [ 1] to 1
Want to force ram [ 3] [ 2] [ 2] to 1
Want to force ram [ 1] [ 2] [ 3] to 0
Want to force ram [ 0] [ 5] [ 4] to 1
Want to force ram [ 3] [ 7] [ 5] to 0
Want to force ram [ 2] [ 4] [ 6] to 1
Want to force ram [ 2] [ 6] [ 7] to 1
Want to force ram [ 1] [ 0] [ 0] to 0
Want to force ram [ 3] [ 3] [ 1] to 1

Daniel

unread,
Nov 21, 2013, 12:11:05 PM11/21/13
to
thanks a lot!, ill give it now a try and see

Daniel

unread,
Nov 21, 2013, 1:28:09 PM11/21/13
to
On Wednesday, November 20, 2013 11:42:30 PM UTC+2, gabor wrote:
ok 2 issues:
1) i get an error regarding the selection of the specific bit: "bit select or part bit select must be constant" , if i write : force ram[rows[k]][cols[k]][3] = vals[k]; i.e the bit is constant and not read from an array, i get through the compilation, any way around that?

2) i wrote #1000 force ram[rows[k]][cols[k]][bits[k]] = vals[k];
this command is inside a for loop. how is #1000 effected when in a for loop?

GaborSzakacs

unread,
Nov 21, 2013, 2:58:04 PM11/21/13
to
Daniel wrote:
>
> ok 2 issues:
> 1) i get an error regarding the selection of the specific bit: "bit select or part bit select must be constant" , if i write : force ram[rows[k]][cols[k]][3] = vals[k]; i.e the bit is constant and not read from an array, i get through the compilation, any way around that?
>
> 2) i wrote #1000 force ram[rows[k]][cols[k]][bits[k]] = vals[k];
> this command is inside a for loop. how is #1000 effected when in a for loop?

1) At some point, it would make sense to just add the 20 lines of code
instead of making a research project out of doing it in a loop. One
suggestion if you wanted to automate this is to write a simple C program
that takes formatted values from a file, and outputs them in the form
required for the force statements, writing the output to another file.
Or you could use a Perl script to convert the number list to force
statements. Then the testbench could just `include the generated file.

2) Each #1000 will add another 1,000 time units as written. If you
wanted the bits to be permanently stuck from time zero, then just leave
the #1000 out. If you wanted to model bits becoming stuck after some
time period, then you can adjust this as necessary. If you want each
force statement to take effect at a particular absolute time, rather
than an interval since the previous force statement, you should probably
put each one in its own initial statement like:

initial #1000 force ram[<x>][<y>][<z>] = <n>;

where <x> <y> etc. are filled in by the external C program or Perl
script.

--
Gabor

Daniel

unread,
Nov 21, 2013, 3:25:25 PM11/21/13
to
:) i do have a file with 20 lines, but in the future i will have to inject other kinds of errors, and this way is so much cleaner

i tried diffrent ways, i cant seem to shake this error off, you think there is no way to do a bit select in this kind of force? any manipulation...?

by the way, thanks for all the help and explanations!

GaborSzakacs

unread,
Nov 21, 2013, 3:50:28 PM11/21/13
to
Daniel wrote:
>
> :) i do have a file with 20 lines, but in the future i will have to inject other kinds of errors, and this way is so much cleaner
>
> i tried diffrent ways, i cant seem to shake this error off, you think there is no way to do a bit select in this kind of force? any manipulation...?
>
> by the way, thanks for all the help and explanations!

The simulator I use won't do a force on a part select at all, so you're
already doing more than I can. Since your force statement can only
handle constants in the part selects, then I don't see how you could
easily read them from a file other than the `include method I mentioned.

I guess the question is how you want these to be applied. If you don't
need the faults to happen after a delay (i.e. bits are stuck permanently
from time 0), then you could use the other method I mentioned, perhaps
with a generate loop to add an always block per fault like:

generate
genvar k;
for (k = 0;k < 10;k = k + 1) begin: Fault
always @(ram[rows[k]][cols[k]][bits[k]])
ram[rows[k]][cols[k]][bits[k]] = vals[k];
end
endgenerate

Or if you need to apply the stuck bits only under some condition,
you could have a vector with a bit for each fault like:

reg [9:0] apply_fault;

generate
genvar k;
for (k = 0;k < 10;k = k + 1) begin: Fault
always @(ram[rows[k]][cols[k]][bits[k]])
if (apply_fault[k]) ram[rows[k]][cols[k]][bits[k]] = vals[k];
end
endgenerate

--
Gabor

GaborSzakacs

unread,
Nov 21, 2013, 6:03:02 PM11/21/13
to
A quick response to my own post here...

The above code works for me. However there is a small difference in
simulation between the always blocks and the force statements. In
the case of force, any attempt to write the forced bit will not
happen. In the case of the always blocks, the writes happen and
then the bit gets immediately (zero simulation time) set to the
overriding value by the always block. So you'll see zero-width
glitches on the signal on a waveform. Also any code that uses
the bit as a trigger (like these always blocks) will get triggered
on that same edge, and you could have race conditions. However
this would be very unusual for a bit in a memory array. Any
well behaved code that doesn't try to use the memory bit at
the exact time it is being written should never see the write
happen on the "forced" bits.

--
Gabor

Daniel

unread,
Nov 22, 2013, 8:50:42 AM11/22/13
to
ok, for now i decided to go with a force command inside an initial block which is inside my memory module.
I read Initial should only be on a testbanch, but since my memory module is not ment to be synthesized, i thought this should be ok.

i prefer the force instead of a writing at zero time aproach

GaborSzakacs

unread,
Nov 22, 2013, 2:17:24 PM11/22/13
to
Daniel wrote:
>
> ok, for now i decided to go with a force command inside an initial block which is inside my memory module.
> I read Initial should only be on a testbanch, but since my memory module is not ment to be synthesized, i thought this should be ok.

initial blocks can be used in synthesizable code, but the support
varies from synthesizer to synthesizer. For Xilinx's XST for
example, it is perfectly OK to use an initial block to initialize
a ROM like:

reg [7:0] my_rom [0:1023];

initial begin
$readmemh ("my_rom_data.txt", my_rom);
end

XST also allows initial blocks for simple regs, and also
can handle initial values in the declaration like:

reg foo = 0;

reg bar;

initial begin
bar = 1;
end

There are some restrictions. For one, the initial block must be in the
same module as the reg declaration. And the fact that you can do this
is due to the underlying hardware that gets initialized by the device
bitstream during configuration.

>
> i prefer the force instead of a writing at zero time aproach
>


As I said, the force is a cleaner approach. On the other hand
it won't do what you originally wanted as far as reading in
the bit locations from a file. So for now you see this as
a trade-off. There may be other ways to deal with this, and
I was hoping one of the SystemVerilog gurus would chime in on
this thread. I'm still using Verilog 2001, because that's all my
tools support.

--
Gabor

Mark Curry

unread,
Nov 22, 2013, 5:24:42 PM11/22/13
to
In article <l6oal8$76b$1...@dont-email.me>,
Not having followed the entire thread - is the main problem
the variable part select in the force?

You can get around that by sticking the force inside a generate,
and the having the qualification for the force outside the force
itself. i.e. changing the variable in the part select to a genvar instead.

something like:

genvar row, column; // Maybe "bit" too?
generate
for( all rows...)
begin : gen_rows
for( all columns )
begin : gen_columns
initial
if( some_qual[ row ][ column ] ) // Maybe add timing controls too...
force mem[ row ][ column ][ bit ] = 1;
end
end
endgenerate

This might barf in the simulator though if the array size get's big. It's
effectively a large number of initial blocks. Don't know at what sizes
the simulator would start to barf...

--Mark





0 new messages