Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 8/16/32 bit widths for block RAM inference #32

Open
3 tasks
HackerFoo opened this issue Jun 9, 2019 · 7 comments
Open
3 tasks

Add 8/16/32 bit widths for block RAM inference #32

HackerFoo opened this issue Jun 9, 2019 · 7 comments

Comments

@HackerFoo
Copy link

HackerFoo commented Jun 9, 2019

Add inference for 8, 16, and 32 bit wide block RAM.

  • See commit below for changes needed brams.txt
  • Modify brams_map.v to correctly map {DO,DI} to {A1,B1}DATA
  • Add tests to symbiflow-arch-defs

https://github.com/HackerFoo/yosys/commit/13af5854ce244281da05fdf64e57054c6941e41d#diff-f6a92cf62e16c847b9dc035993276826L48

assign A1DATA = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] };
assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA;

@markus-zzz
Copy link

I started to have a look at this issue. Since I am a complete newbie to this project I am just going to state my understanding so far and then you will have to correct me if I am wrong.

As this concerns Xilinx 7 series block RAMs a useful read up on what BRAM primitives the device actually support would be the 7 Series FPGAs Memory Resources UG.

The rules file brams.txt is used by passes/memory/memory_bram.cc to find out what is available and contains rules for how to match.

Techmap maps to one of the modules available in bram_map.v and if this is something narrower than 18/36 bits then DI/DO need to be mapped in more clever ways. How exactly I do not understand yet but maybe that will become clear by reading the Xilinx Memory UG linked above.

Also I should run some examples and examine the IR.

@HackerFoo
Copy link
Author

HackerFoo commented Jul 1, 2019

@markus-zzz The Yosys manual might also be useful.

The mapping for 8/16/32-bit widths are easier than 9/18/36-bit widths, because you don't use the parity bits {DOP,DIP}.

The bram_shifter test is a little easier to use and understand than the other BRAM tests. You could replace the primitive BRAMs with an inferred block RAM module e.g.:

https://github.com/SymbiFlow/symbiflow-arch-defs/blob/31732ac2bd7ca5bf952b7e28f03f6e0df4048f01/xc7/tests/bram_test/bram_test_36.v#L1-L27

The shifter tests use the RAM as a double buffer with the switches as input and the LEDs as output, SW0 flips the buffers.

GitHub
FOSS architecture definitions of FPGA hardware useful for doing PnR device generation. - SymbiFlow/symbiflow-arch-defs

@markus-zzz
Copy link

@HackerFoo, Thanks! I had a look at the Yosys manual before and it contains a lot of useful background info.

I am still a bit confused though about what to do. In brams_map.v the TDP memories at least take parameters CFG_DBITS and CFG_ABITS that I assume you would need to do something like the following with (since the port sizes defined in brams_bb.v are of fixed size)

        generate
        if (CFG_DBITS == 36) begin
        assign A1DATA = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] };
        assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA;
        end else begin
        assign A1DATA = DO[CFG_DBITS-1:0];
        assign DI = {(32-CFG_DBITS)'h0, B1DATA};
        end
        endgenerate

I.e. we need to match the declared port sizes and for 32/16/8 this is trivial map-through.

If I do this wrong will I get any warnings or errors from the toolchain (yosys or nextpnr) or will I see problems first when I try to run it on HW? Is it possible to simulate this? (Maybe if I borrow the Xilinx primitives from a Vivado install?)

The board is the second problem, the only Xilinx 7 series device that I have is a ZedBoard and I am not sure that is supported right now.

@guyfleeman
Copy link

Can I help with this issue?

@guyfleeman
Copy link

I found the brams_init.py file since the structure seems to have been made a bit more flexible since the last movement on this thread. I also found the xc7_brams_map.v and xc7_xcu_brams.txt file. It looks like the entry now needs to be added there?

After reading the UG for 7 Series BRAM it's also not clear to me if setting the width to 9, 18, 36 (and then not using the parity bits) densely packs the memory. I'll keep reading and write some tests to check.

@HackerFoo
Copy link
Author

HackerFoo commented Aug 28, 2020

From what I remember, there are really only widths that are multiples of 9 bits in hardware (8 bits from DO + 1 bit from DOP), and one of those bits can be used for parity. In addition there are modes that handle 1, 2, and 4 bits, but cannot use the parity bit. So 2^n bit widths without parity just waste the 9th bit (DOP).

The structure of the hardware is interesting, in that a BRAM18 is made of mostly symmetric halves, where each has a port, and then two of those can be used together as a BRAM36.

This might give you an idea of how memory is arranged in the two BRAM18s that make up a BRAM36: https://github.com/SymbiFlow/symbiflow-arch-defs/blob/master/xc/common/primitives/bram/rambfifo36e1.pb_type.xml#L236-L387

GitHub
FOSS architecture definitions of FPGA hardware useful for doing PnR device generation. - SymbiFlow/symbiflow-arch-defs

@guyfleeman
Copy link

I read the UG yesterday and came to the same conclusion. There were also some lower bit modes (1, 2, 4 I think) but they didn't seem relevant for now.

Thanks for the arch defs link.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants