mirror of https://github.com/openXC7/prjxray.git
Merge pull request #204 from mcmasterg/bram_config3
BRAM READ/WRITE width
This commit is contained in:
commit
6a989b6934
|
|
@ -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))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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]),
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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]),
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue