HDL problem: find the first bit equal to zero, and set it to one - Page 1
Forum section: electronics / general

author: legacy
author_rank: Super Contributor
timestamp: July 04, 2017, 04:45:19 pm
content: so, you have a vector of 1024 bit (it might be 4x bigger), they are initially all zero, and sometimes, inside a process, you need to find the lower bit set to zero, and once found you need to set it to one.It's like find the first bit equal to zero, and set it to one so it will be skipped on future searches.it's 1024 bit, how could you implement it in a decent way?As a giant circuit made on the cascade of "IF" vector(x) branches ?edit:OT but interesting: some ISA supportsffs, even if their implementation is 32bit/64bit. Here I need the circuit for a different purpose. Happy to know that also MIPS comes with something similar.Code:MIPSclzCount Leading Zeros in Word32, 64clzinput sizeMIPScloCount Leading Ones in Word32, 64cloinput size

author: filssavi
author_rank: Frequent Contributor
timestamp: July 04, 2017, 05:14:55 pm
content: You need to provide more informations if you want more precise answers.That said assuming that by hdl you mean hardware description language, and thus FPGA there is more than One way to skin this Digital cat if resource usage is a problem you can do this by setting up a pipeline that fetches data from a dual porta ram, lsb to msb, compares It and makes necessary changes and if necessary writes them backIf speed Is the focus i'd divide and conquer, so split the Vector in smaller chunks, do as above on the chunks once you are Shure you found the lowest 0 bit in the lowest chunks stop the process

author: legacy
author_rank: Super Contributor
timestamp: July 04, 2017, 05:30:57 pm
content: Usually I prefer vhdl. I am planning a design for a small fpga.Code:procedure find_first_set(v : in bit_vector;found : out boolean;first_set_index: out natural)isbeginfor index in v'rangeloopif v(index)thenfound := true;first_set_index := index;return;end if;end loopfound := false;end procedure;Something like this works on the paper as well as on simulators, I have some doubt about the implementation.I have to use it in a clocked processCode:process(clk)beginif rising_edge(clk) thenfind_first_set(...end if;end process;Where clk needs to be around 100MHz (it's 33Mhz x3, using a PLL) on a Spartan3E-250 device.

author: legacy
author_rank: Super Contributor
timestamp: July 04, 2017, 05:47:15 pm
content: I can relax a constraint: "find_first_set" can use a first clock's edge, and bit_set can stay on a second one.

author: NorthGuy
author_rank: Super Contributor
timestamp: July 04, 2017, 06:06:18 pm
content: Quote from: filssavi on July 04, 2017, 05:14:55 pmDivide is certainly the way to go. If you split the vector in half and do the analysis for each half separately you'll get:found1, first_set_index1 - for the LS halffound2, first_set_index2 - for the MS half.Now:Code:if found1 = '1' thenfound <= '1';first_set_index(first_set_index'left) <= '0';first_set_index(first_set_index'left-1 downto 0) <= first_set_index1;elsefound <= found2;first_set_index(first_set_index'left) <= '1';first_set_index(first_set_index'left-1 downto 0) <= first_set_index2;end ifAnd so you continue dividing until you get to the array of size 1 which is trivial.This will give you 10 logic levels which is Ok for 100 MHz. It'll be quite big though.

author: marshallh
author_rank: Unknown
timestamp: July 04, 2017, 07:09:51 pm
content: If you need single cycle it will require a lot of combinational logic. Otherwise you can just usea counter and shift by 1 bit every clock, until you find hte bit, modify, it and shift everything back until the counter resets.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 04, 2017, 07:52:30 pm
content: Isn't what you are describing a long shift register, initially set to all zero, and then ones shifted in from one end (or you can look at it as the lowest zero bit being set)Or am I missing something?

author: legacy
author_rank: Super Contributor
timestamp: July 04, 2017, 07:53:51 pm
content: Quote from: marshallh on July 04, 2017, 07:09:51 pmconstraint: find and set has be within two clock edges.

author: legacy
author_rank: Super Contributor
timestamp: July 04, 2017, 07:56:58 pm
content: Quote from: hamster_nz on July 04, 2017, 07:52:30 pmWell, it looks more like a giant priority encoder than a shift register.And I cannot shift one bit per clock edge

author: legacy
author_rank: Super Contributor
timestamp: July 04, 2017, 07:58:24 pm
content: Quote from: marshallh on July 04, 2017, 07:09:51 pmexactly the feeling I had

author: NorthGuy
author_rank: Super Contributor
timestamp: July 04, 2017, 08:01:13 pm
content: Quote from: hamster_nz on July 04, 2017, 07:52:30 pmAs I understand, there's a 1024-bit register. You scan it from one end. When (if) you find '1', you replace it with '0' and stop.

author: legacy
author_rank: Super Contributor
timestamp: July 04, 2017, 08:33:53 pm
content: Quote from: NorthGuy on July 04, 2017, 06:06:18 pmThanks, good ideaPerhaps I'd better switch to a bigger fpga, like S3-500. I have to check the whole project utilization, currently it's just a proof, I mean the project is composed by different modules, a lot of them haven't yet been analyzed, therefore I don't know the current logic utilization, but now I know the "find the first" module will consume a lot of logic.

author: legacy
author_rank: Super Contributor
timestamp: July 04, 2017, 08:50:33 pm
content: Quote from: NorthGuy on July 04, 2017, 08:01:13 pmyes, but you cannot "scan"Scanning implies that you check one bit per rising clock edge: it can't be applied to my problem, since I need to find the first bit equal to zero in a vector of 1024-bit ...within one clock rising edge. As constraint the search mustn't take more than one clock, and the bit-set to 1 mustn't take more than one clock, in other words the whole mustn't take more than two clock rising edges.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 04, 2017, 08:55:10 pm
content: Quote from: NorthGuy on July 04, 2017, 08:01:13 pmso, you have a vector of 1024 bit (it might be 4x bigger), they are initially all zero,0000... ...0000and sometimes, inside a process, you need to find the lower bit set to zero, and once found you need to set it to one.After each sometimes:0000... ...00010000... ...00110000... ...01110000... ...1111...0001... ...11110011... ...11110111... ...11111111... ...1111Looks like a shift register to me.Either that or we are not being told the whole story

author: NorthGuy
author_rank: Super Contributor
timestamp: July 04, 2017, 09:06:40 pm
content: Quote from: hamster_nz on July 04, 2017, 08:55:10 pmI assumed the register is modified by other means too, so the regular shift pattern will eventually dissipate.

author: legacy
author_rank: Super Contributor
timestamp: July 04, 2017, 09:21:13 pm
content: Quote from: hamster_nz on July 04, 2017, 08:55:10 pmummm, yupForgot to say that sometimes another process needs to reset the bit in the vector to zero, and since you can't assume any predefined scheme it's like it was a random process which re-sets bit to zero randomly, therefore the shift-register-scheme is broken.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 04, 2017, 10:35:58 pm
content: Smallest/slowest answer is something likeSet up a chain from high to low, checking for when the first zero is seen.all_zeros(1023) <= NOT vector(n);for n in 0 to 1022 loop;all_zeros(n) <= all_zeros(n+1) AND NOT vector(n);end loop;...and then leave the tools to optimize it for the underlying architecture (they will most likely do a poor job)During the update just set the bitif rising_edge(clk) and something = '1' thenvector(0) <= '1';for n in 1 to 1023 loopvector(n) <= vector(n) OR (all_zeros(n) AND vector(n-1));end loop;end;There is no way getting around it, that the new state for bit one depends on the state of all other bits in the vector. Somehow the state from the 1023 other bits must fan in to allow it to be updated.If you need to do that in one cycle the best you can do is celling(log(1024)/log(LUT width)) levels of LUTs......unless you also maintain a vector of "this block of n bits is all zeros" alongside the main one, allowing you to move some of the work a cycle earlier.

author: Flip-Flop
author_rank: Newbie
timestamp: July 05, 2017, 06:09:11 pm
content: Try something like this:Code:Process(clk)Variable a, b, c : unsigned(1024 downto 0);BeginIf rising_edge(clk) thena := unsigned('0' & vector);b := a + 1;c := not a and b; -- contains a one at the position of the first zerovector_out <= vector xor c(1023 downto 0); -- Toggle first zeroEnd if;End process;

author: kmike
author_rank: Regular Contributor
timestamp: July 06, 2017, 12:26:11 pm
content: You clould shift the register to the right with 0s and to the left with 1s.edit:Like this: (may contain errors)shift_reg <= shift_reg(REGSIZE-1 downto 0) & '1'shift_reg <= '0' & shift_reg(REGSIZE downto 1)Br,mike

author: Gribo
author_rank: Frequent Contributor
timestamp: July 06, 2017, 03:13:25 pm
content: Is that 1024 bit vector a status register for lots of other processes?

author: Kalvin
author_rank: Super Contributor
timestamp: July 06, 2017, 03:40:41 pm
content: You might be able to reduce the complexity by creating for example 32 identical macroblocks with 32 bits each. Each block will output 1 if any of its input bits are zero, and the bit position of the zero value bit (5 bits). With some simple decoding you should be able to do the tricks you want to perform with decent propagation delay.

author: legacy
author_rank: Super Contributor
timestamp: July 06, 2017, 04:31:48 pm
content: @Kalvingood trick, I think I will follow your idea

author: legacy
author_rank: Super Contributor
timestamp: July 06, 2017, 04:56:59 pm
content: Quote from: Gribo on July 06, 2017, 03:13:25 pmyes it's a status register, but only two processes are involved with it.

author: Gribo
author_rank: Frequent Contributor
timestamp: July 06, 2017, 06:01:36 pm
content: So, let me understand it, one process is filling the vector with bits at an unknown rate, the other is emptying it, again, at an unknown rate?

author: JacobPilsen
author_rank: Regular Contributor
timestamp: July 06, 2017, 07:35:55 pm
content: It sounds (very similar) like "Flash ADC" to me.Don't you know how "highest 1 of 1024" to "binary number" is implemented:

author: legacy
author_rank: Super Contributor
timestamp: July 06, 2017, 08:42:28 pm
content: Quote from: Gribo on July 06, 2017, 06:01:36 pmExactly.

author: brucehoult
author_rank: Super Contributor
timestamp: July 06, 2017, 10:34:16 pm
content: Quote from: hamster_nz on July 04, 2017, 10:35:58 pmThat's just purely to find out whether there is at least one 0 or not. Basically implementing AND gates with all the LUTs. But you won't know where any zero is, let alone the first one.I've never owned or used an FPGA (though I plan to soon) but I had a crack at solving this, designing LUT contents directly as I don't know VHDL or Verilog.Code:git clone https://github.com/brucehoult/fpga_ffz.gitcd fpga_ffzmakeIt will generate a bunch of LUTs as C code, then simulate them through a million random test cases.Examine e.g. luts.hI get 1247 LUTs, of which 224 are 6 input LUTs used as 4:1 muxes. The other 1023 only require four inputs, with groups of three LUTs sharing the same four inputs. If you can use your 6-input LUTs as two 5-input LUTs (as I know Xilinx can) or even into four 4-input LUTs (anyone?) then the number of LUTs can be reduced to 906 or 565.In theory you could cover 1024 inputs with 4 layers of 6-input LUTs, but presumably you want the output of the location of the first zero in binary, not some wacky form. It's only 5 layers with 4-input LUTs.The output of whether there is a zero of not is available in 5 LUT delays and the location of the first zero in 6 LUT delays.Here's the start and end of luts.h. I have no idea how people really do this, so I just made something up on the spotOf course since the simulation is serial not parallel, there is a constraint that all the input wires to a LUT must have smaller indexes than the output of the LUT. The original input bits are in wires 0 .. 1023.Code:#define AllSet4 0x8000800080008000#define FFZ4_0 0x22a222a2a2a222a2#define FFZ4_1 0x8888088808880888#define Mux4to1 0xfedcba9876543210// make_ffz_layers 4 0// make_ffz_layers 3 0// make_ffz_layers 2 0// make_ffz_layers 1 0// make_ffz_layers 0 0{1024, AllSet4, 0, 1, 2, 3, 0, 0},{1025, FFZ4_1, 0, 1, 2, 3, 0, 0},{1026, FFZ4_0, 0, 1, 2, 3, 0, 0},// make_ffz_layers 0 4{1027, AllSet4, 4, 5, 6, 7, 0, 0},{1028, FFZ4_1, 4, 5, 6, 7, 0, 0},{1029, FFZ4_0, 4, 5, 6, 7, 0, 0},// make_ffz_layers 0 8{1030, AllSet4, 8, 9, 10, 11, 0, 0},{1031, FFZ4_1, 8, 9, 10, 11, 0, 0},{1032, FFZ4_0, 8, 9, 10, 11, 0, 0},// make_ffz_layers 0 12{1033, AllSet4, 12, 13, 14, 15, 0, 0},{1034, FFZ4_1, 12, 13, 14, 15, 0, 0},{1035, FFZ4_0, 12, 13, 14, 15, 0, 0},{1036, AllSet4, 1024, 1027, 1030, 1033, 0, 0},{1037, FFZ4_1, 1024, 1027, 1030, 1033, 0, 0},{1038, FFZ4_0, 1024, 1027, 1030, 1033, 0, 0},{1039, Mux4to1, 1038, 1037, 1025, 1028, 1031, 1034},{1040, Mux4to1, 1038, 1037, 1026, 1029, 1032, 1035},// make_ffz_layers 1 16// make_ffz_layers 0 16{1041, AllSet4, 16, 17, 18, 19, 0, 0},{1042, FFZ4_1, 16, 17, 18, 19, 0, 0},{1043, FFZ4_0, 16, 17, 18, 19, 0, 0},// make_ffz_layers 0 20{1044, AllSet4, 20, 21, 22, 23, 0, 0},{1045, FFZ4_1, 20, 21, 22, 23, 0, 0},{1046, FFZ4_0, 20, 21, 22, 23, 0, 0},// make_ffz_layers 0 24{1047, AllSet4, 24, 25, 26, 27, 0, 0},{1048, FFZ4_1, 24, 25, 26, 27, 0, 0},{1049, FFZ4_0, 24, 25, 26, 27, 0, 0},// make_ffz_layers 0 28{1050, AllSet4, 28, 29, 30, 31, 0, 0},{1051, FFZ4_1, 28, 29, 30, 31, 0, 0},{1052, FFZ4_0, 28, 29, 30, 31, 0, 0},{1053, AllSet4, 1041, 1044, 1047, 1050, 0, 0},{1054, FFZ4_1, 1041, 1044, 1047, 1050, 0, 0},{1055, FFZ4_0, 1041, 1044, 1047, 1050, 0, 0},{1056, Mux4to1, 1055, 1054, 1042, 1045, 1048, 1051},{1057, Mux4to1, 1055, 1054, 1043, 1046, 1049, 1052},::// make_ffz_layers 1 1008// make_ffz_layers 0 1008{2227, AllSet4, 1008, 1009, 1010, 1011, 0, 0},{2228, FFZ4_1, 1008, 1009, 1010, 1011, 0, 0},{2229, FFZ4_0, 1008, 1009, 1010, 1011, 0, 0},// make_ffz_layers 0 1012{2230, AllSet4, 1012, 1013, 1014, 1015, 0, 0},{2231, FFZ4_1, 1012, 1013, 1014, 1015, 0, 0},{2232, FFZ4_0, 1012, 1013, 1014, 1015, 0, 0},// make_ffz_layers 0 1016{2233, AllSet4, 1016, 1017, 1018, 1019, 0, 0},{2234, FFZ4_1, 1016, 1017, 1018, 1019, 0, 0},{2235, FFZ4_0, 1016, 1017, 1018, 1019, 0, 0},// make_ffz_layers 0 1020{2236, AllSet4, 1020, 1021, 1022, 1023, 0, 0},{2237, FFZ4_1, 1020, 1021, 1022, 1023, 0, 0},{2238, FFZ4_0, 1020, 1021, 1022, 1023, 0, 0},{2239, AllSet4, 2227, 2230, 2233, 2236, 0, 0},{2240, FFZ4_1, 2227, 2230, 2233, 2236, 0, 0},{2241, FFZ4_0, 2227, 2230, 2233, 2236, 0, 0},{2242, Mux4to1, 2241, 2240, 2228, 2231, 2234, 2237},{2243, Mux4to1, 2241, 2240, 2229, 2232, 2235, 2238},{2244, AllSet4, 2188, 2205, 2222, 2239, 0, 0},{2245, FFZ4_1, 2188, 2205, 2222, 2239, 0, 0},{2246, FFZ4_0, 2188, 2205, 2222, 2239, 0, 0},{2247, Mux4to1, 2246, 2245, 2189, 2206, 2223, 2240},{2248, Mux4to1, 2246, 2245, 2190, 2207, 2224, 2241},{2249, Mux4to1, 2246, 2245, 2191, 2208, 2225, 2242},{2250, Mux4to1, 2246, 2245, 2192, 2209, 2226, 2243},{2251, AllSet4, 2019, 2094, 2169, 2244, 0, 0},{2252, FFZ4_1, 2019, 2094, 2169, 2244, 0, 0},{2253, FFZ4_0, 2019, 2094, 2169, 2244, 0, 0},{2254, Mux4to1, 2253, 2252, 2020, 2095, 2170, 2245},{2255, Mux4to1, 2253, 2252, 2021, 2096, 2171, 2246},{2256, Mux4to1, 2253, 2252, 2022, 2097, 2172, 2247},{2257, Mux4to1, 2253, 2252, 2023, 2098, 2173, 2248},{2258, Mux4to1, 2253, 2252, 2024, 2099, 2174, 2249},{2259, Mux4to1, 2253, 2252, 2025, 2100, 2175, 2250},{2260, AllSet4, 1324, 1633, 1942, 2251, 0, 0},{2261, FFZ4_1, 1324, 1633, 1942, 2251, 0, 0},{2262, FFZ4_0, 1324, 1633, 1942, 2251, 0, 0},{2263, Mux4to1, 2262, 2261, 1325, 1634, 1943, 2252},{2264, Mux4to1, 2262, 2261, 1326, 1635, 1944, 2253},{2265, Mux4to1, 2262, 2261, 1327, 1636, 1945, 2254},{2266, Mux4to1, 2262, 2261, 1328, 1637, 1946, 2255},{2267, Mux4to1, 2262, 2261, 1329, 1638, 1947, 2256},{2268, Mux4to1, 2262, 2261, 1330, 1639, 1948, 2257},{2269, Mux4to1, 2262, 2261, 1331, 1640, 1949, 2258},{2270, Mux4to1, 2262, 2261, 1332, 1641, 1950, 2259},#define NUM_WIRES 2271#define NUM_INPUTS 1024#define NUM_LUTS 1247#define RES_NO_ZEROS 2260#define RES_POS_9 2261#define RES_POS_8 2262#define RES_POS_7 2263#define RES_POS_6 2264#define RES_POS_5 2265#define RES_POS_4 2266#define RES_POS_3 2267#define RES_POS_2 2268#define RES_POS_1 2269#define RES_POS_0 2270

author: NorthGuy
author_rank: Super Contributor
timestamp: July 07, 2017, 12:22:06 am
content: Quote from: brucehoult on July 06, 2017, 10:34:16 pmThe hierarchical process would yield 682 LUTs (assuming 6x1 or 5x2 Xilinx LUTs), 224 4:1 MUXes and 6 layers of combinatory logic.Layer 1You group all bits into 256 groups, each consists of consecutive 4-bit elements. For each group you calculate:1-bit layer1_found - '1' if if the group has a good bit. This takes 1 6x1 LUT - 4 original bits as inputs2-bit layer1_index - index of the first good bit (if any). This takes 1 5x2 LUT - same 4 inputs - 2 bits of outputsCombined all together, we've got 256 of each. 256 x 2 = 512 LUTs for the first layerLayer 2We now form groups, each of which consists of 4 consecutive layer-1 groups (64 groups total - each represents 4 groups from layer 1 or 16 original bits). For each group we calculate1-bit layer2_found - '1' if any of the 4 layer1_found is set. This take 1 6x1 LUT - 4 group1_found as inputs2-bit layer2_index - index of the first layer1_found which is set (if any). This takes 1 5x2 LUT - same 4 inputsLUTs on layer 2: 64 x 2 = 128 LUTsNote that layer2_index must be 4-bit, but it is only 2-bit. The existing 2 bits of the layer2_index should be used toselect the appropriate layer1_index (out of 4) and use the selected layer1_index as 2 LS bits of layer2_index.We cannot do it right now, but we can do it on the next layer.Layer 3We now form 16 4-element groups from the layer-2 group. Acting the same way as before we produce1-bit layer3_found - 1 LUT2-bit layer3_index - 1 LUTThis gives us 16 x 2 = 32 LUTsNow we continue with selecting indices. 2 bits of layer2_index are used as a MUX selector to select theappropriate layer1_index for each group of the 2-nd layer. Since layer1_index is 2-bit, we need 2 MUXes.These can be implemented as LUTs. Xilinx also has built-in 4:1 MUXes which can be used instead. Assumewe use MUXes.64 x 2 = 128 MUXesLayer 4Same thing. Create layer4_found and layer4_index4 x 2 = 8 LUTsAlso, as in the previous layer, we use layer3_index to select appropriate layer2_index values. layer2_index isnow 4-bit, so we need 4 MUXes for each group.16 x 4 = 64 MUXesLayer 5We now get only one group and produce layer5_found and layer5_index = 2 LUTsAlso, use layer4_index to select the appropriate layer3_index (which is now 6-bit long)4 x 6 = 24 MUXesLayer 6We still need to use layer5_index to select the correct layer4_index = 8 MUXes (one for each bit of layer4_index)Total count is:512 + 128 + 32 + 8 + 2 = 682 LUTs128 + 64 + 24 + 8 = 224 MUXesHowever, producing the signal which uses 10-bit layer5_index to select new value for each of 1024 bits will take 2 LUTs for each = 2048 LUTs, but I guess there might be a better way to do the modification.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 07, 2017, 04:34:53 am
content: Based @Flip-Flop's idea from earlier in this thread.... it actually works very well!Code:initial 0000000000000000000001000000000000000000000000000000000000000000SetNext 0000000000000000000011000000000000000000000000000000000000000000SetNext 0000000000000000000111000000000000000000000000000000000000000000Extra 0000000000001000000111000000000000000000000000000000000000000000SetNext 0000000000011000000111000000000000000000000000000000000000000000SetNext 0000000000111000000111000000000000000000000000000000000000000000It uses the carry chain to get information between bits, so should be relatively fast - much faster than LUTsHere is the C code used to test the idea - NOTE - The bits in vector are in the wrong order (e.g the leftmost bit above is bit 0, the rightmost is bit 63).Code:unsigned long long vector = 0;void setNext(void) {unsigned long long t;unsigned long long mask;t = ~vector; // Flip the 0s and 1s,t++; // Cause a carry to ripple up through the carry chainmask = t & vector; // Detect where the carry stoppedvector |= mask >> 1; // pull bit back and set the next bit}There are a few boundary conditions that need to be checked carefully (when all zeros, or when the last bit is set). You could maybe use this as a basis for a shorter block, and chain them (much like a carry-lookahead adder). But using the carry chain in between bits is the way to go!Here is the entire test code:Code:#include <stdio.h>unsigned long long vector = 0;void print_vector(char *desc) {printf("%-10.10s",desc);unsigned long long mask = 1;while(mask) {putchar( (mask&vector) ? '1' : '0');mask <<= 1;}printf("\n");}void setNext(void) {unsigned long long t;unsigned long long mask;t = ~vector;t++;mask = t & vector;vector |= mask >> 1;}int main(int c, char *v[]){/* Set the initial value */vector = 0x200000;print_vector("initial");setNext();print_vector("SetNext");setNext();print_vector("SetNext");/* Note this is bit 48 in the vector */vector |= 0x1000;print_vector("Extra ");setNext();print_vector("SetNext");setNext();print_vector("SetNext");}

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: July 07, 2017, 07:29:43 am
content: Quote from: legacy on July 06, 2017, 04:56:59 pmA 4096 bit status register? What is its purpose?

author: brucehoult
author_rank: Super Contributor
timestamp: July 07, 2017, 12:05:47 pm
content: Quote from: NorthGuy on July 07, 2017, 12:22:06 am... and you go on to excellently describe precisely the same solution as I posted working code for in the message you replied to :-) With the same results I quoted there: 906 LUTs total (224 as 4:1 MUXes), if both 6x1 and 5x2 are available.I guess that means I wasn't too far off for a first crack at FPGA design :-) :-) :-) :-)

author: legacy
author_rank: Super Contributor
timestamp: July 07, 2017, 12:10:36 pm
content: Quote from: brucehoult on July 07, 2017, 12:05:47 pmLOL

author: NorthGuy
author_rank: Super Contributor
timestamp: July 07, 2017, 12:55:48 pm
content: Quote from: hamster_nz on July 07, 2017, 04:34:53 amI don't think so. Carry chain is consecutive and hence very slow. For example, propagation through a CARRY4 element in Xilinx-7 series takes roughly 0.5 ns. So, to go through 1024 elements will take about 128 ns. This is about 30 times slower than the brucehoult's solution.

author: NorthGuy
author_rank: Super Contributor
timestamp: July 07, 2017, 01:25:48 pm
content: Quote from: brucehoult on July 07, 2017, 12:05:47 pmAmazing. After posting this, I looked at your post again and the numbers looked suspiciously similar. This was very surprising, but I'm not familiar with fpga_ffz, so I didn't go through your code.

author: nctnico
author_rank: Super Contributor
timestamp: July 08, 2017, 09:19:09 am
content: Quote from: legacy on July 06, 2017, 08:42:28 pmIsn't there some way to avoid having to check all the bits every time by using a different way to get the same functionality? I'm not talking about optimisation but creating an entirely different approach to the problem you are trying to solve which avoids needing to check & set bits at all.

author: legacy
author_rank: Super Contributor
timestamp: July 08, 2017, 01:58:02 pm
content: Quote from: nctnico on July 08, 2017, 09:19:09 amSince I need to write a few notes to make to remember what I am doing, I am going to write a laTek paragraph under the title "getting stuck in a rut" since alternatives to 'get & set' actually exist, but ... they all block other functionalities.Get&Set works, but it's hard to be implemented (and might consume area). I have to thank people for the helpOh, in the theory, relaxing other circuits and removing other functionalities, I could simply end in replacing the 'get&set' with a simple 32 bit counter which increments and decrement on demand

author: Gribo
author_rank: Frequent Contributor
timestamp: July 08, 2017, 02:52:33 pm
content: You practically have a 4096 bit deep, 1 bit wide, dual port FIFO.