1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
//
// TODO: Add license text!
//
module modexpng_mem #
(
parameter MEM_WIDTH = 17,
parameter MEM_ADDR_BITS = 6
)
(
input clk,
input [MEM_ADDR_BITS-1:0] a_addr,
input a_en,
input a_wr,
input [MEM_WIDTH -1:0] a_in,
output [MEM_WIDTH -1:0] a_out,
input [MEM_ADDR_BITS-1:0] b_addr,
input b_en,
input b_reg_en,
output [MEM_WIDTH -1:0] b_out
);
//
// BRAM
//
(* RAM_STYLE="BLOCK" *)
reg [MEM_WIDTH-1:0] bram[0:(2**MEM_ADDR_BITS)-1];
//
// Initialization for Simulation
//
/*
integer c;
initial begin
for (c=0; c<(2**MEM_ADDR_BITS); c=c+1)
bram[c] = {MEM_WIDTH{1'b0}};
end
*/
//
// Output Registers
//
reg [MEM_WIDTH-1:0] bram_b;
reg [MEM_WIDTH-1:0] bram_b_reg;
assign a_out = 32'hDEADCE11;
assign b_out = bram_b_reg;
//
// Note, that when both ports are accessing the same location, conflict can
// potentionally arise. See Xilinx UG473 (pages 19-20, "Conflict
// Avoidance") for more information. In our configuration to avoid that the
// write port must be coded to operate in READ_FIRST mode. If the write
// port is overwriting the same address the read port is accessing, the
// write port must read the previously stored data (not the data it is
// writing, as that would be WRITE_FIRST mode).
//
//
// Write-Only Port A
//
always @(posedge clk)
//
if (a_en)
//
if (a_wr) bram[a_addr] <= a_in;
//
// Read-Only Port B
//
always @(posedge clk)
//
if (b_en)
//
bram_b <= bram[b_addr];
always @(posedge clk)
//
if (b_reg_en)
//
bram_b_reg <= bram_b;
endmodule
|