Address generation logic

S

Syed Huq

Guest
Hi guys,

I'm trying to implement trigger logic to keep storing trigger events which include pre-trigger data in a BRAM block.

The following logic is what I'm trying to implement. I'm not sure how viable it is or if I'm missing something in there, but I have a few doubts on how I'm going to implement certain things:

-The BRAM is 8-bits wide and 4096 bits deep. Each 8-bit data location is a sample.

Each trigger event is 64 address locations so I'm trying to create small ring buffers within the BRAM. One issue would be as to how I would generate the addresses for the 64 addresses. Would I use a mod-6 up counter ? Basically, whenever a trigger event occurs, I want 32 pre-trigger samples and 32 post-trigger samples in the 64 data locations. So whenever a trigger occurs, I start a 5-bit down counter for the 32 post-trigger data locations. Once this is filled, I'd move on to the next block of address locations.

So I'm kind of splitting my 4096 address locations into blocks of 64 address locations. Once the first trigger event is completed, I'd move on to the second block of addresses. But I'm having trouble trying to understand how I would accomplish this.

Now my second ring buffer would be from location 64 - 127, so would I have to use a separate counter from 64-127 ? Ideally, I'd want to use the same up-counter. Can someone give me a hint on how I would accomplish this efficiently ? Am I missing something here ?

-Syed
 
On 10/26/2014 5:10 AM, Syed Huq wrote:
Hi guys,

I'm trying to implement trigger logic to keep storing trigger events which include pre-trigger data in a BRAM block.

The following logic is what I'm trying to implement. I'm not sure how viable it is or if I'm missing something in there, but I have a few doubts on how I'm going to implement certain things:

-The BRAM is 8-bits wide and 4096 bits deep. Each 8-bit data location is a sample.

Each trigger event is 64 address locations so I'm trying to create small ring buffers within the BRAM. One issue would be as to how I would generate the addresses for the 64 addresses. Would I use a mod-6 up counter ? Basically, whenever a trigger event occurs, I want 32 pre-trigger samples and 32 post-trigger samples in the 64 data locations. So whenever a trigger occurs, I start a 5-bit down counter for the 32 post-trigger data locations. Once this is filled, I'd move on to the next block of address locations.

So I'm kind of splitting my 4096 address locations into blocks of 64 address locations. Once the first trigger event is completed, I'd move on to the second block of addresses. But I'm having trouble trying to understand how I would accomplish this.

Now my second ring buffer would be from location 64 - 127, so would I have to use a separate counter from 64-127 ? Ideally, I'd want to use the same up-counter. Can someone give me a hint on how I would accomplish this efficiently ? Am I missing something here ?

You only need one 6 bit counter to control the storage of data within a
ring buffer. But you will need an 8 bit counter to generate the upper
address bits for the 256 buffers to indicate which one you are using at
the moment.

However, once you have filled the buffer you will need to store the 6
bit starting address within the buffer so the data can be read out
starting from the first sample. You can either do that by using one of
the locations in the buffer (making it a 63 word buffer), by using four
of the 64 word buffers reducing the number of buffers 252 or by using a
separate 256 word memory.

--

Rick
 
rickman wrote:
On 10/26/2014 5:10 AM, Syed Huq wrote:
Hi guys,

I'm trying to implement trigger logic to keep storing trigger events
which include pre-trigger data in a BRAM block.

The following logic is what I'm trying to implement. I'm not sure how
viable it is or if I'm missing something in there, but I have a few
doubts on how I'm going to implement certain things:

-The BRAM is 8-bits wide and 4096 bits deep. Each 8-bit data location
is a sample.

Each trigger event is 64 address locations so I'm trying to create
small ring buffers within the BRAM. One issue would be as to how I
would generate the addresses for the 64 addresses. Would I use a mod-6
up counter ? Basically, whenever a trigger event occurs, I want 32
pre-trigger samples and 32 post-trigger samples in the 64 data
locations. So whenever a trigger occurs, I start a 5-bit down counter
for the 32 post-trigger data locations. Once this is filled, I'd move
on to the next block of address locations.

So I'm kind of splitting my 4096 address locations into blocks of 64
address locations. Once the first trigger event is completed, I'd move
on to the second block of addresses. But I'm having trouble trying to
understand how I would accomplish this.

Now my second ring buffer would be from location 64 - 127, so would I
have to use a separate counter from 64-127 ? Ideally, I'd want to use
the same up-counter. Can someone give me a hint on how I would
accomplish this efficiently ? Am I missing something here ?

You only need one 6 bit counter to control the storage of data within a
ring buffer. But you will need an 8 bit counter to generate the upper
address bits for the 256 buffers to indicate which one you are using at
the moment.

However, once you have filled the buffer you will need to store the 6
bit starting address within the buffer so the data can be read out
starting from the first sample. You can either do that by using one of
the locations in the buffer (making it a 63 word buffer), by using four
of the 64 word buffers reducing the number of buffers 252 or by using a
separate 256 word memory.

One other thing to consider is whether your trigger events could
conceivably come close enough together (within 64 clock cycles)
to prevent the next buffer from storing the full 32-word pre-
store for that trigger event. You'd actually have the data in
the prior ring buffer, but you'd need to have a way of knowing
that the events happened too close, e.g. by storing the time
difference in clocks between the current and previous trigger.
And of course if the trigger events could occur within 32 clocks
of eachother you'd also need to flag that more than one trigger
event is in the same buffer.

The first case would be easier to deal with if you actually
ping-pong between two physical RAMs. Then you can be pre-storing
the data for the next buffer while still capturing the post-store
for the current buffer.

--
Gabor
 
The trigger will be latched to 1 until the entire 64 clk cycles are completed and only then I'll be sending the reset trigger from the FPGA to the Trigger boards so that shouldn't be a worry I believe.

I'm trying to simulate a simple 3-bit up counter as an address generator and a 2-bit down counter for when the trigger event occurs, but I seem to be doing something silly here which is causing only 3 addresses to be used when the down-counter starts when I want 4 addresses to be stored after the trigger. :

//=== 8-bit wide loadable up-counter ============================`timescale 1 ns / 1 ps

module fw_up_counter_3 (tc, count, d, ld, en, clk, rst);

output tc;
output [2:0] count;
input [2:0] d;
input ld, en, clk, rst;
reg [2:0] l_count;
wire tc;

assign tc = &count[2:0];
assign count = l_count ;

always @(posedge clk)
begin
if(rst)
l_count <= 3'b0;
else if(ld)
l_count <= d;
else if (en & ~ld)
l_count <= l_count + 1;
else
l_count <= l_count;
end
endmodule

//====2-bit wide loadable down-counter====================module fw_dn_counter_1(tc, count, en, ld, clk, rst);
output tc;
output [1:0] count;
input en, clk, rst, ld;
reg [1:0] l_count;
reg [1:0] d = 2'b11;
wire tc;

assign tc = ~|count[1:0];
assign count = l_count;

always@(posedge clk)
begin
if (rst)
l_count <= 2'b11;
else if (ld)
l_count <= d;
else if(en & ~ld & ~tc)
l_count <= l_count - 1;
else if (l_count == 2'b00)
l_count <= 2'b00;
else
l_count <= l_count;
end
endmodule


---------

module trig_test(clk, tc1, tc2, en1, en2, count1, count2, rst, ld, trig, trig_loc);
input clk, rst, en1, en2, ld;
output [2:0] count1;
output [1:0] count2;
output tc1, tc2;
input trig;
output reg [2:0]trig_loc;

fw_up_counter_3 counter1(.tc(tc1), .count(count1), .d(3'b000), .ld(ld), .en(~tc2), .clk(clk), .rst(rst));

fw_dn_counter_1 counter2(.tc(tc2), .count(count2), .en(trig) , .ld(ld), .clk(clk), .rst(rst));

always@(posedge trig)
begin
trig_loc <= count1;
end

endmodule

Waveform: http://imgur.com/TCPVzRR



On Monday, 27 October 2014 08:33:11 UTC-5, gabor wrote:
rickman wrote:
On 10/26/2014 5:10 AM, Syed Huq wrote:
Hi guys,

I'm trying to implement trigger logic to keep storing trigger events
which include pre-trigger data in a BRAM block.

The following logic is what I'm trying to implement. I'm not sure how
viable it is or if I'm missing something in there, but I have a few
doubts on how I'm going to implement certain things:

-The BRAM is 8-bits wide and 4096 bits deep. Each 8-bit data location
is a sample.

Each trigger event is 64 address locations so I'm trying to create
small ring buffers within the BRAM. One issue would be as to how I
would generate the addresses for the 64 addresses. Would I use a mod-6
up counter ? Basically, whenever a trigger event occurs, I want 32
pre-trigger samples and 32 post-trigger samples in the 64 data
locations. So whenever a trigger occurs, I start a 5-bit down counter
for the 32 post-trigger data locations. Once this is filled, I'd move
on to the next block of address locations.

So I'm kind of splitting my 4096 address locations into blocks of 64
address locations. Once the first trigger event is completed, I'd move
on to the second block of addresses. But I'm having trouble trying to
understand how I would accomplish this.

Now my second ring buffer would be from location 64 - 127, so would I
have to use a separate counter from 64-127 ? Ideally, I'd want to use
the same up-counter. Can someone give me a hint on how I would
accomplish this efficiently ? Am I missing something here ?

You only need one 6 bit counter to control the storage of data within a
ring buffer. But you will need an 8 bit counter to generate the upper
address bits for the 256 buffers to indicate which one you are using at
the moment.

However, once you have filled the buffer you will need to store the 6
bit starting address within the buffer so the data can be read out
starting from the first sample. You can either do that by using one of
the locations in the buffer (making it a 63 word buffer), by using four
of the 64 word buffers reducing the number of buffers 252 or by using a
separate 256 word memory.


One other thing to consider is whether your trigger events could
conceivably come close enough together (within 64 clock cycles)
to prevent the next buffer from storing the full 32-word pre-
store for that trigger event. You'd actually have the data in
the prior ring buffer, but you'd need to have a way of knowing
that the events happened too close, e.g. by storing the time
difference in clocks between the current and previous trigger.
And of course if the trigger events could occur within 32 clocks
of eachother you'd also need to flag that more than one trigger
event is in the same buffer.

The first case would be easier to deal with if you actually
ping-pong between two physical RAMs. Then you can be pre-storing
the data for the next buffer while still capturing the post-store
for the current buffer.

--
Gabor
 
Why can't you debug this in the simulator? It will show you all the
signals everywhere in your design. That should show you exactly where
the problem is.

This is not a problem, but it makes the code harder to read. In the 3
bit counter module you have this condition in the else clause of the if
(ld)
...
else if (en & ~ld)

It can be simplified to just

else if (en)

The & ~ld is implied by the else just as you don't include & ~rst in all
the following conditions.

You also don't need the default case of

else
l_count <= l_count;

That is implied by the else condition not being specified.

In your 2 bit counter the conditions are confused by the inclusion of
the extraneous inputs. Take out the extraneous stuff and code a bit
more simply. I'm not clear on what this counter is even supposed to do.

else if (ld)
l_count <= d;
else if(en & ~tc)
l_count <= l_count - 1;
end

I believe this code is equivalent to what you wrote.

Isn't (l_count == 2'b00) the same as ~tc?

I don't see a problem. Are you looking for four counts *after* the
trigger, or four counts including the trigger sample? If you want the
latter you need a starting count of 100. One of your states has to
indicate to stop storing data. So a four count needs a fifth state.

Hard to tell, you can make it work with four states depending on the
timing of the trigger relative to the rest of the circuit.

Rick


On 10/28/2014 1:53 AM, Syed Huq wrote:
The trigger will be latched to 1 until the entire 64 clk cycles are completed and only then I'll be sending the reset trigger from the FPGA to the Trigger boards so that shouldn't be a worry I believe.

I'm trying to simulate a simple 3-bit up counter as an address generator and a 2-bit down counter for when the trigger event occurs, but I seem to be doing something silly here which is causing only 3 addresses to be used when the down-counter starts when I want 4 addresses to be stored after the trigger. :

//=== 8-bit wide loadable up-counter =============================
`timescale 1 ns / 1 ps

module fw_up_counter_3 (tc, count, d, ld, en, clk, rst);

output tc;
output [2:0] count;
input [2:0] d;
input ld, en, clk, rst;
reg [2:0] l_count;
wire tc;

assign tc = &count[2:0];
assign count = l_count ;

always @(posedge clk)
begin
if(rst)
l_count <= 3'b0;
else if(ld)
l_count <= d;
else if (en & ~ld)
l_count <= l_count + 1;
else
l_count <= l_count;
end
endmodule

//====2-bit wide loadable down-counter=====================
module fw_dn_counter_1(tc, count, en, ld, clk, rst);
output tc;
output [1:0] count;
input en, clk, rst, ld;
reg [1:0] l_count;
reg [1:0] d = 2'b11;
wire tc;

assign tc = ~|count[1:0];
assign count = l_count;

always@(posedge clk)
begin
if (rst)
l_count <= 2'b11;
else if (ld)
l_count <= d;
else if(en & ~ld & ~tc)
l_count <= l_count - 1;
else if (l_count == 2'b00)
l_count <= 2'b00;
else
l_count <= l_count;
end
endmodule


---------

module trig_test(clk, tc1, tc2, en1, en2, count1, count2, rst, ld, trig, trig_loc);
input clk, rst, en1, en2, ld;
output [2:0] count1;
output [1:0] count2;
output tc1, tc2;
input trig;
output reg [2:0]trig_loc;

fw_up_counter_3 counter1(.tc(tc1), .count(count1), .d(3'b000), .ld(ld), .en(~tc2), .clk(clk), .rst(rst));

fw_dn_counter_1 counter2(.tc(tc2), .count(count2), .en(trig) , .ld(ld), .clk(clk), .rst(rst));

always@(posedge trig)
begin
trig_loc <= count1;
end

endmodule

Waveform: http://imgur.com/TCPVzRR



On Monday, 27 October 2014 08:33:11 UTC-5, gabor wrote:
rickman wrote:
On 10/26/2014 5:10 AM, Syed Huq wrote:
Hi guys,

I'm trying to implement trigger logic to keep storing trigger events
which include pre-trigger data in a BRAM block.

The following logic is what I'm trying to implement. I'm not sure how
viable it is or if I'm missing something in there, but I have a few
doubts on how I'm going to implement certain things:

-The BRAM is 8-bits wide and 4096 bits deep. Each 8-bit data location
is a sample.

Each trigger event is 64 address locations so I'm trying to create
small ring buffers within the BRAM. One issue would be as to how I
would generate the addresses for the 64 addresses. Would I use a mod-6
up counter ? Basically, whenever a trigger event occurs, I want 32
pre-trigger samples and 32 post-trigger samples in the 64 data
locations. So whenever a trigger occurs, I start a 5-bit down counter
for the 32 post-trigger data locations. Once this is filled, I'd move
on to the next block of address locations.

So I'm kind of splitting my 4096 address locations into blocks of 64
address locations. Once the first trigger event is completed, I'd move
on to the second block of addresses. But I'm having trouble trying to
understand how I would accomplish this.

Now my second ring buffer would be from location 64 - 127, so would I
have to use a separate counter from 64-127 ? Ideally, I'd want to use
the same up-counter. Can someone give me a hint on how I would
accomplish this efficiently ? Am I missing something here ?

You only need one 6 bit counter to control the storage of data within a
ring buffer. But you will need an 8 bit counter to generate the upper
address bits for the 256 buffers to indicate which one you are using at
the moment.

However, once you have filled the buffer you will need to store the 6
bit starting address within the buffer so the data can be read out
starting from the first sample. You can either do that by using one of
the locations in the buffer (making it a 63 word buffer), by using four
of the 64 word buffers reducing the number of buffers 252 or by using a
separate 256 word memory.


One other thing to consider is whether your trigger events could
conceivably come close enough together (within 64 clock cycles)
to prevent the next buffer from storing the full 32-word pre-
store for that trigger event. You'd actually have the data in
the prior ring buffer, but you'd need to have a way of knowing
that the events happened too close, e.g. by storing the time
difference in clocks between the current and previous trigger.
And of course if the trigger events could occur within 32 clocks
of eachother you'd also need to flag that more than one trigger
event is in the same buffer.

The first case would be easier to deal with if you actually
ping-pong between two physical RAMs. Then you can be pre-storing
the data for the next buffer while still capturing the post-store
for the current buffer.

--
Gabor

--

Rick
 

Welcome to EDABoard.com

Sponsor

Back
Top