1 `timescale 1 ns / 10 ps
3 address_a
, byteena_a
, wrdata_a
, wren_a
, rddata_a
,
4 address_b
, byteena_b
, wrdata_b
, wren_b
, rddata_b
);
6 parameter DATA_WIDTH
= 32;
7 parameter ADDR_WIDTH
= 7;
8 parameter INIT_FILE
= "somefile"; // No .mif!
13 input [ADDR_WIDTH
-1:0] address_a
;
14 input [DATA_WIDTH
/8-1:0] byteena_a
;
15 input [DATA_WIDTH
-1:0] wrdata_a
;
17 output reg [DATA_WIDTH
-1:0] rddata_a
;
19 input [ADDR_WIDTH
-1:0] address_b
;
20 input [DATA_WIDTH
-1:0] wrdata_b
;
21 input [DATA_WIDTH
/8-1:0] byteena_b
;
23 output reg [DATA_WIDTH
-1:0] rddata_b
;
25 // Declare the RAM variable
26 reg [DATA_WIDTH
/4-1:0] ram0
[(1 << ADDR_WIDTH
)-1:0];
27 reg [DATA_WIDTH
/4-1:0] ram1
[(1 << ADDR_WIDTH
)-1:0];
28 reg [DATA_WIDTH
/4-1:0] ram2
[(1 << ADDR_WIDTH
)-1:0];
29 reg [DATA_WIDTH
/4-1:0] ram3
[(1 << ADDR_WIDTH
)-1:0];
31 always @(posedge clock
) begin
33 if (byteena_a
[0]) ram0
[address_a
] <= wrdata_a
[ 7: 0];
34 if (byteena_a
[1]) ram1
[address_a
] <= wrdata_a
[15: 8];
35 if (byteena_a
[2]) ram2
[address_a
] <= wrdata_a
[23:16];
36 if (byteena_a
[3]) ram3
[address_a
] <= wrdata_a
[31:24];
40 if (byteena_b
[0]) ram0
[address_b
] <= wrdata_b
[ 7: 0];
41 if (byteena_b
[1]) ram1
[address_b
] <= wrdata_b
[15: 8];
42 if (byteena_b
[2]) ram2
[address_b
] <= wrdata_b
[23:16];
43 if (byteena_b
[3]) ram3
[address_b
] <= wrdata_b
[31:24];
46 // Read (if read_addr == write_addr, return OLD data). To return
47 // NEW data, use = (blocking write) rather than <= (non-blocking write)
48 // in the write assignment. NOTE: NEW data may require extra bypass
49 // logic around the RAM.
50 rddata_a
<= {ram3
[address_a
],ram2
[address_a
],ram1
[address_a
],ram0
[address_a
]};
51 rddata_b
<= {ram3
[address_b
],ram2
[address_b
],ram1
[address_b
],ram0
[address_b
]};
54 $display("%05d dram[%d] = %d", $time,
56 {ram3
[address_a
],ram2
[address_a
],ram1
[address_a
],ram0
[address_a
]});
58 $display("%05d dram[%d] <-a %d/%d [%d/%d/%d]", $time,
59 address_a
, wrdata_a
, byteena_a
, address_b
, wren_b
, byteena_b
);
61 $display("%05d dram[%d] <-b %d/%d [%d/%d/%d]", $time,
62 address_b
, wrdata_b
, byteena_b
, address_a
, wren_a
, byteena_a
);
67 * This is so lame, but it looks like a Verilog limitation that we
70 * if (byteena_b[3]) ram[address_b][31:24] <= wrdata_b[31:24];
72 * thus we have to manually split the ram into four blocks if we desire
75 reg [DATA_WIDTH
-1:0] ram_initial
[(1 << ADDR_WIDTH
)-1:0];
80 #0 $readmemh({INIT_FILE
,".data"}, ram_initial
);
81 for (i
= 0; i
< 1 << ADDR_WIDTH
; i
= i
+ 1)
82 {ram3
[i
],ram2
[i
],ram1
[i
],ram0
[i
]} = ram_initial
[i
];