Merge pull request #204 from mcmasterg/bram_config3

BRAM READ/WRITE width
This commit is contained in:
John McMaster 2018-10-29 15:40:29 -07:00 committed by GitHub
commit 6a989b6934
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 170 additions and 43 deletions

View File

@ -1,4 +1,5 @@
N := 1 # read/write width is relatively slow to resolve
N := 4
SPECIMENS := $(addprefix build/specimen_,$(shell seq -f '%03.0f' $(N))) SPECIMENS := $(addprefix build/specimen_,$(shell seq -f '%03.0f' $(N)))
SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS)) SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS))

View File

@ -5,6 +5,77 @@ import json
from prjxray.segmaker import Segmaker from prjxray.segmaker import Segmaker
from prjxray import verilog from prjxray import verilog
def isenv_tags(segmk, ps, site):
# all of these bits are inverted
ks = [
('IS_CLKARDCLK_INVERTED', 'ZINV_CLKARDCLK'),
('IS_CLKBWRCLK_INVERTED', 'ZINV_CLKBWRCLK'),
('IS_ENARDEN_INVERTED', 'ZINV_ENARDEN'),
('IS_ENBWREN_INVERTED', 'ZINV_ENBWREN'),
('IS_RSTRAMARSTRAM_INVERTED', 'ZINV_RSTRAMARSTRAM'),
('IS_RSTRAMB_INVERTED', 'ZINV_RSTRAMB'),
('IS_RSTREGARSTREG_INVERTED', 'ZINV_RSTREGARSTREG'),
('IS_RSTREGB_INVERTED', 'ZINV_RSTREGB'),
]
for param, tagname in ks:
segmk.add_site_tag(site, tagname, 1 ^ verilog.parsei(ps[param]))
def bus_tags(segmk, ps, site):
'''
parameter DOA_REG = 1'b0;
parameter DOB_REG = 1'b0;
parameter SRVAL_A = 18'b0;
parameter SRVAL_B = 18'b0;
parameter INIT_A = 18'b0;
parameter INIT_B = 18'b0;
'''
for param, tagname in [('SRVAL_A', 'ZSRVAL_A'), ('SRVAL_B', 'ZSRVAL_B'),
('INIT_A', 'ZINIT_A'), ('INIT_B', 'ZINIT_B')]:
bitstr = verilog.parse_bitstr(ps[param])
ab = param[-1]
# Are all bits present?
hasparity = ps['READ_WIDTH_' + ab] == 18
for i in range(18):
# Magic bit positions from experimentation
# we could just only solve when parity, but this check documents the fine points a bit better
if hasparity or i not in (1, 9):
segmk.add_site_tag(site, '%s[%u]' % (param, i), 1 ^ bitstr[i])
def rw_width_tags(segmk, ps, site):
'''
Y0.READ_WIDTH_A
width 001_03 001_04 001_05
1 0 0 0
2 1 0 0
4 0 1 0
9 1 1 0
18 0 0 1
'''
'''
for param, vals in {
"READ_WIDTH_A": [1, 2, 4, 9, 18],
"READ_WIDTH_B": [1, 2, 4, 9, 18],
"WRITE_WIDTH_A": [1, 2, 4, 9, 18],
"WRITE_WIDTH_B": [1, 2, 4, 9, 18],
}.items():
set_val = int(ps[param])
for val in vals:
has = set_val == val
segmk.add_site_tag(site, '%s_B0' % (param), has)
'''
for param in ["READ_WIDTH_A", "READ_WIDTH_B", "WRITE_WIDTH_A",
"WRITE_WIDTH_B"]:
set_val = int(ps[param])
segmk.add_site_tag(site, '%s_B0' % (param), set_val in (2, 9))
segmk.add_site_tag(site, '%s_B1' % (param), set_val in (4, 9))
segmk.add_site_tag(site, '%s_B2' % (param), set_val in (18, ))
def run():
segmk = Segmaker("design.bits", verbose=True) segmk = Segmaker("design.bits", verbose=True)
#segmk.set_def_bt('BLOCK_RAM') #segmk.set_def_bt('BLOCK_RAM')
@ -18,32 +89,16 @@ for l in f:
site = verilog.unquote(ps['LOC']) site = verilog.unquote(ps['LOC'])
#print('site', site) #print('site', site)
# all of these bits are inverted isenv_tags(segmk, ps, site)
ks = [ bus_tags(segmk, ps, site)
('IS_CLKARDCLK_INVERTED', 'ZINV_CLKARDCLK'), rw_width_tags(segmk, ps, site)
('IS_CLKBWRCLK_INVERTED', 'ZINV_CLKBWRCLK'),
('IS_ENARDEN_INVERTED', 'ZINV_ENARDEN'),
('IS_ENBWREN_INVERTED', 'ZINV_ENBWREN'),
('IS_RSTRAMARSTRAM_INVERTED', 'ZINV_RSTRAMARSTRAM'),
('IS_RSTRAMB_INVERTED', 'ZINV_RSTRAMB'),
('IS_RSTREGARSTREG_INVERTED', 'ZINV_RSTREGARSTREG'),
('IS_RSTREGB_INVERTED', 'ZINV_RSTREGB'),
]
for param, tagname in ks:
segmk.add_site_tag(site, tagname, 1 ^ verilog.parsei(ps[param]))
'''
parameter DOA_REG = 1'b0;
parameter DOB_REG = 1'b0;
parameter SRVAL_A = 18'b0;
parameter SRVAL_B = 18'b0;
parameter INIT_A = 18'b0;
parameter INIT_B = 18'b0;
'''
for param, tagname in [('SRVAL_A', 'ZSRVAL_A'), ('SRVAL_B', 'ZSRVAL_B'),
('INIT_A', 'ZINIT_A'), ('INIT_B', 'ZINIT_B')]:
bitstr = verilog.parse_bitstr(ps[param])
for i in range(18):
segmk.add_site_tag(site, '%s[%u]' % (param, i), 1 ^ bitstr[i])
segmk.compile() def bitfilter(frame, bit):
# rw_width_tags() aliasing interconnect on large widths
return frame not in (20, 21)
segmk.compile(bitfilter=bitfilter)
segmk.write() segmk.write()
run()

View File

@ -3,6 +3,7 @@ import random
random.seed(int(os.getenv("SEED"), 16)) random.seed(int(os.getenv("SEED"), 16))
from prjxray import util from prjxray import util
from prjxray import verilog from prjxray import verilog
from prjxray.verilog import vrandbit, vrandbits
import sys import sys
import json import json
@ -57,21 +58,6 @@ print(
'module roi(input clk, input [%d:0] din, output [%d:0] dout);' % 'module roi(input clk, input [%d:0] din, output [%d:0] dout);' %
(DIN_N - 1, DOUT_N - 1)) (DIN_N - 1, DOUT_N - 1))
def vrandbit():
if random.randint(0, 1):
return "1'b1"
else:
return "1'b0"
def vrandbits(n):
ret = "%u'b" % n
for _i in range(n):
ret += str(random.randint(0, 1))
return ret
for loci, (site_type, site) in enumerate(brams): for loci, (site_type, site) in enumerate(brams):
def place_bram18(): def place_bram18():
@ -80,6 +66,11 @@ for loci, (site_type, site) in enumerate(brams):
'din': 'din[ %d +: 8]' % (8 * loci, ), 'din': 'din[ %d +: 8]' % (8 * loci, ),
'dout': 'dout[ %d +: 8]' % (8 * loci, ), 'dout': 'dout[ %d +: 8]' % (8 * loci, ),
} }
# Datasheet says 72 is legal in some cases, but think its a copy paste error from BRAM36
# also 0 and 36 aren't real sizes
# Bias choice to 18 as its needed to solve certain bits quickly
widths = [1, 2, 4, 9, 18, 18, 18, 18]
params = { params = {
'LOC': verilog.quote(site), 'LOC': verilog.quote(site),
'IS_CLKARDCLK_INVERTED': vrandbit(), 'IS_CLKARDCLK_INVERTED': vrandbit(),
@ -99,7 +90,12 @@ for loci, (site_type, site) in enumerate(brams):
"SRVAL_B": vrandbits(18), "SRVAL_B": vrandbits(18),
"INIT_A": vrandbits(18), "INIT_A": vrandbits(18),
"INIT_B": vrandbits(18), "INIT_B": vrandbits(18),
"READ_WIDTH_A": random.choice(widths),
"READ_WIDTH_B": random.choice(widths),
"WRITE_WIDTH_A": random.choice(widths),
"WRITE_WIDTH_B": random.choice(widths),
} }
return ('my_RAMB18E1', ports, params) return ('my_RAMB18E1', ports, params)
def place_bram36(): def place_bram36():
@ -211,6 +207,10 @@ module my_RAMB18E1 (input clk, input [7:0] din, output [7:0] dout);
parameter INIT_A = 18'b0; parameter INIT_A = 18'b0;
parameter INIT_B = 18'b0; parameter INIT_B = 18'b0;
parameter READ_WIDTH_A = 0;
parameter READ_WIDTH_B = 0;
parameter WRITE_WIDTH_A = 0;
parameter WRITE_WIDTH_B = 0;
''') ''')
print('''\ print('''\
(* LOC=LOC *) (* LOC=LOC *)
@ -240,7 +240,12 @@ print(
.SRVAL_A(SRVAL_A), .SRVAL_A(SRVAL_A),
.SRVAL_B(SRVAL_B), .SRVAL_B(SRVAL_B),
.INIT_A(INIT_A), .INIT_A(INIT_A),
.INIT_B(INIT_B) .INIT_B(INIT_B),
.READ_WIDTH_A(READ_WIDTH_A),
.READ_WIDTH_B(READ_WIDTH_B),
.WRITE_WIDTH_A(WRITE_WIDTH_A),
.WRITE_WIDTH_B(WRITE_WIDTH_B)
) ram ( ) ram (
.CLKARDCLK(din[0]), .CLKARDCLK(din[0]),
.CLKBWRCLK(din[1]), .CLKBWRCLK(din[1]),

View File

@ -37,4 +37,6 @@ build/roi_bram18iy1_bit01.diff:
build/roi_bramis_bit01.diff: build/roi_bramis_bit01.diff:
$(MAKE) -f diff.mk OUT_DIFF=build/roi_bramis_bit01.diff PRJL=roi_bramis_bit0 PRJR=roi_bramis_bit1 $(MAKE) -f diff.mk OUT_DIFF=build/roi_bramis_bit01.diff PRJL=roi_bramis_bit0 PRJR=roi_bramis_bit1
build/roi_bram18_width.diff:
$(MAKE) -f diff.mk OUT_DIFF=build/roi_bram18_width.diff PRJL=roi_bram18_width_a PRJR=roi_bram18_width_b

View File

@ -265,6 +265,21 @@ module roi_hck(input clk, input [255:0] din, output [255:0] dout);
endmodule endmodule
/******************************************************************************
Misc ROI
******************************************************************************/
module roi_bram18_width_a(input clk, input [255:0] din, output [255:0] dout);
ram_RAMB18E1 #(.LOC("RAMB18_X0Y40"), .READ_WIDTH_A(1))
r0(.clk(clk), .din(din[ 0 +: 8]), .dout(dout[ 0 +: 8]));
endmodule
//"READ_WIDTH_A": [0, 1, 2, 4, 9, 18, 36],
module roi_bram18_width_b(input clk, input [255:0] din, output [255:0] dout);
ram_RAMB18E1 #(.LOC("RAMB18_X0Y40"), .READ_WIDTH_A(0))
r0(.clk(clk), .din(din[ 0 +: 8]), .dout(dout[ 0 +: 8]));
endmodule
/****************************************************************************** /******************************************************************************
Library Library
******************************************************************************/ ******************************************************************************/
@ -280,10 +295,33 @@ for i in xrange(0x40): print '.INIT_%02X(INIT),' % i
*/ */
module ram_RAMB18E1 (input clk, input [7:0] din, output [7:0] dout); module ram_RAMB18E1 (input clk, input [7:0] din, output [7:0] dout);
parameter LOC = ""; parameter LOC = "";
parameter INIT0 = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INIT0 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter INIT = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INIT = 256'h0000000000000000000000000000000000000000000000000000000000000000;
parameter RAM_MODE = "TDP";
parameter IS_CLKARDCLK_INVERTED = 1'b0;
parameter IS_CLKBWRCLK_INVERTED = 1'b0;
parameter IS_ENARDEN_INVERTED = 1'b0; parameter IS_ENARDEN_INVERTED = 1'b0;
parameter IS_ENBWREN_INVERTED = 1'b0;
parameter IS_RSTRAMARSTRAM_INVERTED = 1'b0;
parameter IS_RSTRAMB_INVERTED = 1'b0;
parameter IS_RSTREGARSTREG_INVERTED = 1'b0;
parameter IS_RSTREGB_INVERTED = 1'b0;
parameter RAM_MODE = "TDP";
parameter WRITE_MODE_A = "WRITE_FIRST";
parameter WRITE_MODE_B = "WRITE_FIRST";
parameter DOA_REG = 1'b0;
parameter DOB_REG = 1'b0;
parameter SRVAL_A = 18'b0;
parameter SRVAL_B = 18'b0;
parameter INIT_A = 18'b0;
parameter INIT_B = 18'b0;
parameter READ_WIDTH_A = 0;
parameter READ_WIDTH_B = 0;
parameter WRITE_WIDTH_A = 0;
parameter WRITE_WIDTH_B = 0;
(* LOC=LOC *) (* LOC=LOC *)
RAMB18E1 #( RAMB18E1 #(
@ -361,18 +399,29 @@ module ram_RAMB18E1 (input clk, input [7:0] din, output [7:0] dout);
.INIT_3E(INIT), .INIT_3E(INIT),
.INIT_3F(INIT), .INIT_3F(INIT),
.IS_CLKARDCLK_INVERTED(1'b0), .IS_CLKARDCLK_INVERTED(IS_CLKARDCLK_INVERTED),
.IS_CLKBWRCLK_INVERTED(1'b0), .IS_CLKBWRCLK_INVERTED(IS_CLKBWRCLK_INVERTED),
.IS_ENARDEN_INVERTED(IS_ENARDEN_INVERTED), .IS_ENARDEN_INVERTED(IS_ENARDEN_INVERTED),
.IS_ENBWREN_INVERTED(1'b0), .IS_ENBWREN_INVERTED(IS_ENBWREN_INVERTED),
.IS_RSTRAMARSTRAM_INVERTED(1'b0), .IS_RSTRAMARSTRAM_INVERTED(IS_RSTRAMARSTRAM_INVERTED),
.IS_RSTRAMB_INVERTED(1'b0), .IS_RSTRAMB_INVERTED(IS_RSTRAMB_INVERTED),
.IS_RSTREGARSTREG_INVERTED(1'b0), .IS_RSTREGARSTREG_INVERTED(IS_RSTREGARSTREG_INVERTED),
.IS_RSTREGB_INVERTED(1'b0), .IS_RSTREGB_INVERTED(IS_RSTREGB_INVERTED),
.RAM_MODE(RAM_MODE), .RAM_MODE(RAM_MODE),
.WRITE_MODE_A("WRITE_FIRST"), .WRITE_MODE_A(WRITE_MODE_A),
.WRITE_MODE_B("WRITE_FIRST"), .WRITE_MODE_B(WRITE_MODE_B),
.SIM_DEVICE("VIRTEX6")
.DOA_REG(DOA_REG),
.DOB_REG(DOB_REG),
.SRVAL_A(SRVAL_A),
.SRVAL_B(SRVAL_B),
.INIT_A(INIT_A),
.INIT_B(INIT_B),
.READ_WIDTH_A(READ_WIDTH_A),
.READ_WIDTH_B(READ_WIDTH_B),
.WRITE_WIDTH_A(WRITE_WIDTH_A),
.WRITE_WIDTH_B(WRITE_WIDTH_B)
) ram ( ) ram (
.CLKARDCLK(din[0]), .CLKARDCLK(din[0]),
.CLKBWRCLK(din[1]), .CLKBWRCLK(din[1]),

View File

@ -1,4 +1,5 @@
import sys import sys
import random
def top_harness(DIN_N, DOUT_N, f=sys.stdout): def top_harness(DIN_N, DOUT_N, f=sys.stdout):
@ -76,3 +77,17 @@ def parse_bitstr(s):
bitstr = postfix[1:] bitstr = postfix[1:]
assert len(bitstr) == n assert len(bitstr) == n
return [int(x) for x in bitstr] return [int(x) for x in bitstr]
def vrandbit():
if random.randint(0, 1):
return "1'b1"
else:
return "1'b0"
def vrandbits(n):
ret = "%u'b" % n
for _i in range(n):
ret += str(random.randint(0, 1))
return ret