Skip to content

Commit eca36f7

Browse files
committed
example of BRAM is added.
1 parent 89e68b3 commit eca36f7

File tree

3 files changed

+315
-0
lines changed

3 files changed

+315
-0
lines changed

examples/bram/Makefile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
TARGET=$(shell ls *.py | grep -v test | grep -v parsetab.py)
2+
ARGS=
3+
4+
PYTHON=python3
5+
#PYTHON=python
6+
#OPT=-m pdb
7+
#OPT=-m cProfile -s time
8+
#OPT=-m cProfile -o profile.rslt
9+
10+
.PHONY: all
11+
all: test
12+
13+
.PHONY: run
14+
run:
15+
$(PYTHON) $(OPT) $(TARGET) $(ARGS)
16+
17+
.PHONY: test
18+
test:
19+
$(PYTHON) -m pytest -vv
20+
21+
.PHONY: check
22+
check:
23+
$(PYTHON) $(OPT) $(TARGET) $(ARGS) > tmp.v
24+
iverilog -tnull -Wall tmp.v
25+
rm -f tmp.v
26+
27+
.PHONY: clean
28+
clean:
29+
rm -rf *.pyc __pycache__ parsetab.py .cache *.out *.png *.dot tmp.v uut.vcd

examples/bram/bram.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
from __future__ import absolute_import
2+
from __future__ import print_function
3+
import sys
4+
import os
5+
import math
6+
7+
# the next line can be removed after installation
8+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
9+
10+
from veriloggen import *
11+
import veriloggen.dataflow as dataflow
12+
13+
def mkBram(datawidth=32, addrwidth=10, numports=2):
14+
m = Module('BRAM%d' % numports)
15+
16+
clk = m.Input('CLK')
17+
ports = []
18+
for i in range(numports):
19+
addr = m.Input('ADDR%d' % i, addrwidth)
20+
din = m.Input('DIN%d' % i, datawidth)
21+
we = m.Input('WE%d' % i)
22+
dout = m.Output('DOUT%d' % i, datawidth)
23+
delay_addr = m.Reg('delay_ADDR%d' % i, addrwidth)
24+
ports.append( (addr, din, we, dout, delay_addr) )
25+
26+
mem = m.Reg('mem', datawidth, length=2**addrwidth)
27+
28+
for i in range(numports):
29+
addr, din ,we, dout, delay_addr = ports[i]
30+
m.Always(Posedge(clk))(
31+
If(we)(
32+
mem[addr](din)
33+
),
34+
delay_addr(addr)
35+
)
36+
m.Assign(dout(mem[delay_addr]))
37+
38+
return m
39+
40+
def mkMain(n=128, datawidth=32, numports=2):
41+
m = Module('main')
42+
43+
clk = m.Input('CLK')
44+
rst = m.Input('RST')
45+
46+
addrwidth = int(math.log(n, 2)) * 2
47+
48+
bram = mkBram(datawidth, addrwidth, numports)
49+
50+
bram_ports = []
51+
for i in range(numports):
52+
addr = m.Reg('bram_addr%d' % i, addrwidth)
53+
din = m.Reg('bram_din%d' % i, datawidth)
54+
we = m.Reg('bram_we%d' % i)
55+
dout = m.Wire('bram_dout%d' % i, datawidth)
56+
bram_ports.append( [addr, din, we, dout] )
57+
58+
ports = [ clk ]
59+
for bram_port in bram_ports:
60+
ports.extend(bram_port)
61+
62+
# BRAM instance
63+
m.Instance(bram, 'bram_inst', params=(), ports=ports)
64+
65+
# example how to access BRAM
66+
fsm = FSM(m, 'fsm', clk, rst)
67+
68+
for addr, din, we, dout in bram_ports:
69+
fsm.add( addr(0), din(0), we(0) )
70+
71+
fsm.goto_next()
72+
73+
count = m.Reg('count', 32, initval=0)
74+
for port, (addr, din, we, dout) in enumerate(bram_ports):
75+
fsm.add( addr(count+port*n//numports), din(count), we(1), count.inc() )
76+
77+
fsm.goto_next(cond=count==n//numports-1)
78+
79+
fsm.make_always()
80+
81+
return m
82+
83+
def mkTest():
84+
m = Module('test')
85+
86+
# target instance
87+
main = mkMain()
88+
89+
# copy paras and ports
90+
params = m.copy_params(main)
91+
ports = m.copy_sim_ports(main)
92+
93+
clk = ports['CLK']
94+
rst = ports['RST']
95+
96+
uut = m.Instance(main, 'uut',
97+
params=m.connect_params(main),
98+
ports=m.connect_ports(main))
99+
100+
simulation.setup_waveform(m, uut, m.get_vars())
101+
simulation.setup_clock(m, clk, hperiod=5)
102+
init = simulation.setup_reset(m, rst, m.make_reset(), period=100)
103+
104+
init.add(
105+
Delay(1000 * 100),
106+
Systask('finish'),
107+
)
108+
109+
return m
110+
111+
if __name__ == '__main__':
112+
test = mkTest()
113+
verilog = test.to_verilog('tmp.v')
114+
print(verilog)

examples/bram/test_bram.py

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
from __future__ import absolute_import
2+
from __future__ import print_function
3+
import bram
4+
5+
expected_verilog = """
6+
module test
7+
(
8+
9+
);
10+
11+
reg CLK;
12+
reg RST;
13+
14+
main
15+
uut
16+
(
17+
.CLK(CLK),
18+
.RST(RST)
19+
);
20+
21+
22+
initial begin
23+
$dumpfile("uut.vcd");
24+
$dumpvars(0, uut, CLK, RST);
25+
end
26+
27+
28+
initial begin
29+
CLK = 0;
30+
forever begin
31+
#5 CLK = !CLK;
32+
end
33+
end
34+
35+
36+
initial begin
37+
RST = 0;
38+
#100;
39+
RST = 1;
40+
#100;
41+
RST = 0;
42+
#100000;
43+
$finish;
44+
end
45+
46+
47+
endmodule
48+
49+
50+
51+
module main
52+
(
53+
input CLK,
54+
input RST
55+
);
56+
57+
reg [14-1:0] bram_addr0;
58+
reg [32-1:0] bram_din0;
59+
reg bram_we0;
60+
wire [32-1:0] bram_dout0;
61+
reg [14-1:0] bram_addr1;
62+
reg [32-1:0] bram_din1;
63+
reg bram_we1;
64+
wire [32-1:0] bram_dout1;
65+
66+
BRAM2
67+
bram_inst
68+
(
69+
.CLK(CLK),
70+
.ADDR0(bram_addr0),
71+
.DIN0(bram_din0),
72+
.WE0(bram_we0),
73+
.DOUT0(bram_dout0),
74+
.ADDR1(bram_addr1),
75+
.DIN1(bram_din1),
76+
.WE1(bram_we1),
77+
.DOUT1(bram_dout1)
78+
);
79+
80+
reg [32-1:0] fsm;
81+
localparam fsm_init = 0;
82+
reg [32-1:0] count;
83+
localparam fsm_1 = 1;
84+
localparam fsm_2 = 2;
85+
86+
always @(posedge CLK) begin
87+
if(RST) begin
88+
fsm <= fsm_init;
89+
count <= 0;
90+
end else begin
91+
case(fsm)
92+
fsm_init: begin
93+
bram_addr0 <= 0;
94+
bram_din0 <= 0;
95+
bram_we0 <= 0;
96+
bram_addr1 <= 0;
97+
bram_din1 <= 0;
98+
bram_we1 <= 0;
99+
fsm <= fsm_1;
100+
end
101+
fsm_1: begin
102+
bram_addr0 <= count + 0;
103+
bram_din0 <= count;
104+
bram_we0 <= 1;
105+
count <= count + 1;
106+
bram_addr1 <= count + 64;
107+
bram_din1 <= count;
108+
bram_we1 <= 1;
109+
count <= count + 1;
110+
if(count == 63) begin
111+
fsm <= fsm_2;
112+
end
113+
end
114+
endcase
115+
end
116+
end
117+
118+
119+
endmodule
120+
121+
122+
123+
module BRAM2
124+
(
125+
input CLK,
126+
input [14-1:0] ADDR0,
127+
input [32-1:0] DIN0,
128+
input WE0,
129+
output [32-1:0] DOUT0,
130+
input [14-1:0] ADDR1,
131+
input [32-1:0] DIN1,
132+
input WE1,
133+
output [32-1:0] DOUT1
134+
);
135+
136+
reg [14-1:0] delay_ADDR0;
137+
reg [14-1:0] delay_ADDR1;
138+
reg [32-1:0] mem [0:16384-1];
139+
140+
always @(posedge CLK) begin
141+
if(WE0) begin
142+
mem[ADDR0] <= DIN0;
143+
end
144+
delay_ADDR0 <= ADDR0;
145+
end
146+
147+
assign DOUT0 = mem[delay_ADDR0];
148+
149+
always @(posedge CLK) begin
150+
if(WE1) begin
151+
mem[ADDR1] <= DIN1;
152+
end
153+
delay_ADDR1 <= ADDR1;
154+
end
155+
156+
assign DOUT1 = mem[delay_ADDR1];
157+
158+
endmodule
159+
"""
160+
161+
def test():
162+
test_module = bram.mkTest()
163+
code = test_module.to_verilog()
164+
165+
from pyverilog.vparser.parser import VerilogParser
166+
from pyverilog.ast_code_generator.codegen import ASTCodeGenerator
167+
parser = VerilogParser()
168+
expected_ast = parser.parse(expected_verilog)
169+
codegen = ASTCodeGenerator()
170+
expected_code = codegen.visit(expected_ast)
171+
172+
assert(expected_code == code)

0 commit comments

Comments
 (0)