propagate new use_svp64_ldst_dec mode through TestCore and TestIssuer
[soc.git] / src / unused / iommu / axi_rab / ram_tp_write_first.py
1 # // Copyright 2018 ETH Zurich and University of Bologna.
2 # // Copyright and related rights are licensed under the Solderpad Hardware
3 # // License, Version 0.51 (the "License"); you may not use this file except in
4 # // compliance with the License. You may obtain a copy of the License at
5 # // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6 # // or agreed to in writing, software, hardware and materials distributed under
7 # // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 # // CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 # // specific language governing permissions and limitations under the License.
10 #
11 # /*
12 # * ram_tp_write_first
13 # *
14 # * This code implements a parameterizable two-port memory. Port 0 can read and
15 # * write while Port 1 can read only. Xilinx Vivado will infer a BRAM in
16 # * "write first" mode, i.e., upon a read and write to the same address, the
17 # * new value is read. Note: Port 1 outputs invalid data in the cycle after
18 # * the write when reading the same address.
19 # *
20 # * For more information, see Xilinx PG058 Block Memory Generator Product Guide.
21 # */
22
23 from nmigen import Signal, Module, Const, Cat, Elaboratable
24 from nmigen import Memory
25
26 import math
27 #
28 # module ram_tp_write_first
29 # #(
30 ADDR_WIDTH = 10
31 DATA_WIDTH = 36
32 # )
33 # (
34 # input clk,
35 # input we,
36 # input [ADDR_WIDTH-1:0] addr0,
37 # input [ADDR_WIDTH-1:0] addr1,
38 # input [DATA_WIDTH-1:0] d_i,
39 # output [DATA_WIDTH-1:0] d0_o,
40 # output [DATA_WIDTH-1:0] d1_o
41 # );
42
43
44 class ram_tp_write_first(Elaboratable):
45
46 def __init__(self):
47 self.we = Signal() # input
48 self.addr0 = Signal(ADDR_WIDTH) # input
49 self.addr1 = Signal(ADDR_WIDTH) # input
50 self.d_i = Signal(DATA_WIDTH) # input
51 self.d0_o = Signal(DATA_WIDTH) # output
52 self.d1_o = Signal(DATA_WIDTH) # output
53
54 DEPTH = int(math.pow(2, ADDR_WIDTH))
55 self.ram = Memory(width=DATA_WIDTH, depth=DEPTH)
56
57 #
58 # localparam DEPTH = 2**ADDR_WIDTH;
59 #
60 # (* ram_style = "block" *) reg [DATA_WIDTH-1:0] ram[DEPTH];
61 # reg [ADDR_WIDTH-1:0] raddr0;
62 # reg [ADDR_WIDTH-1:0] raddr1;
63 #
64 # always_ff @(posedge clk) begin
65 # if(we == 1'b1) begin
66 # ram[addr0] <= d_i;
67 # end
68 # raddr0 <= addr0;
69 # raddr1 <= addr1;
70 # end
71 #
72 # assign d0_o = ram[raddr0];
73 # assign d1_o = ram[raddr1];
74 #
75
76 def elaborate(self, platform=None):
77 m = Module()
78 m.submodules.read_ram0 = read_ram0 = self.ram.read_port()
79 m.submodules.read_ram1 = read_ram1 = self.ram.read_port()
80 m.submodules.write_ram = write_ram = self.ram.write_port()
81
82 # write port
83 m.d.comb += write_ram.en.eq(self.we)
84 m.d.comb += write_ram.addr.eq(self.addr0)
85 m.d.comb += write_ram.data.eq(self.d_i)
86
87 # read ports
88 m.d.comb += read_ram0.addr.eq(self.addr0)
89 m.d.comb += read_ram1.addr.eq(self.addr1)
90 m.d.sync += self.d0_o.eq(read_ram0.data)
91 m.d.sync += self.d1_o.eq(read_ram1.data)
92
93 return m