1 |
2 |
sinclairrf |
//
|
2 |
|
|
// PERIPHERAL: AXI4-Lite slave dual-port-RAM interface
|
3 |
|
|
//
|
4 |
|
|
// Note: While the AXI4-Lite protocol allows simultaneous read and write
|
5 |
|
|
// operations, only one side of the dual-port RAM is available to the AXI4-lite
|
6 |
|
|
// interface. This requires internal arbitration between the two operations
|
7 |
|
|
// with either the first or the write operation being preferred.
|
8 |
|
|
//
|
9 |
|
|
// Note: The dual-port-ram is implemented as write-through memory.
|
10 |
|
|
//
|
11 |
|
|
// Note: Xilinx' distributed RAM does not support dual-port write operations,
|
12 |
|
|
// so a Block RAM coding style is used instead.
|
13 |
|
|
//
|
14 |
|
|
generate
|
15 |
|
|
localparam L__SIZE = @SIZE@;
|
16 |
|
|
localparam L__NBITS_SIZE = $clog2(L__SIZE);
|
17 |
|
|
localparam L__RESP_OKAY = 2'b00;
|
18 |
|
|
localparam L__RESP_EXOKAY = 2'b01;
|
19 |
|
|
localparam L__RESP_SLVERR = 2'b10;
|
20 |
|
|
localparam L__RESP_DECERR = 2'b11;
|
21 |
|
|
// AXI4-Lite side of the dual-port memory;
|
22 |
|
|
initial o_bresp = L__RESP_OKAY;
|
23 |
|
|
initial o_rresp = L__RESP_OKAY;
|
24 |
|
|
reg s__axi_idle = 1'b1;
|
25 |
|
|
reg s__axi_got_waddr = 1'b0;
|
26 |
|
|
reg s__axi_got_wdata = 1'b0;
|
27 |
|
|
reg s__axi_got_raddr = 1'b0;
|
28 |
|
|
reg [L__NBITS_SIZE-1:2] s__axi_addr = {(L__NBITS_SIZE-2){1'b0}};
|
29 |
4 |
sinclairrf |
initial o_awready = 1'b0;
|
30 |
|
|
initial o_wready = 1'b0;
|
31 |
|
|
initial o_arready = 1'b0;
|
32 |
2 |
sinclairrf |
always @ (posedge i_aclk)
|
33 |
|
|
if (~i_aresetn) begin
|
34 |
|
|
s__axi_idle <= 1'b1;
|
35 |
|
|
s__axi_got_waddr <= 1'b0;
|
36 |
|
|
s__axi_got_wdata <= 1'b0;
|
37 |
|
|
s__axi_got_raddr <= 1'b0;
|
38 |
|
|
s__axi_addr <= {(L__NBITS_SIZE-2){1'b0}};
|
39 |
4 |
sinclairrf |
o_awready <= 1'b0;
|
40 |
|
|
o_wready <= 1'b0;
|
41 |
|
|
o_arready <= 1'b0;
|
42 |
2 |
sinclairrf |
end else begin
|
43 |
|
|
s__axi_idle <= s__axi_idle;
|
44 |
|
|
s__axi_got_waddr <= s__axi_got_waddr;
|
45 |
|
|
s__axi_got_wdata <= s__axi_got_wdata;
|
46 |
|
|
s__axi_got_raddr <= s__axi_got_raddr;
|
47 |
|
|
s__axi_addr <= s__axi_addr;
|
48 |
|
|
o_awready <= 1'b0;
|
49 |
|
|
o_wready <= 1'b0;
|
50 |
|
|
o_arready <= 1'b0;
|
51 |
|
|
if (s__axi_idle) begin
|
52 |
|
|
if (i_awvalid) begin
|
53 |
|
|
s__axi_idle <= 1'b0;
|
54 |
|
|
s__axi_got_waddr <= 1'b1;
|
55 |
|
|
s__axi_addr <= i_awaddr[L__NBITS_SIZE-1:2];
|
56 |
|
|
o_awready <= 1'b1;
|
57 |
|
|
end else if (i_arvalid) begin
|
58 |
|
|
s__axi_idle <= 1'b0;
|
59 |
|
|
s__axi_got_raddr <= 1'b1;
|
60 |
|
|
s__axi_addr <= i_araddr[L__NBITS_SIZE-1:2];
|
61 |
|
|
o_arready <= 1'b1;
|
62 |
|
|
end
|
63 |
|
|
end else if (s__axi_got_waddr) begin
|
64 |
|
|
if (i_wvalid) begin
|
65 |
|
|
s__axi_got_waddr <= 1'b0;
|
66 |
|
|
s__axi_got_wdata <= 1'b1;
|
67 |
|
|
o_wready <= 1'b1;
|
68 |
|
|
end
|
69 |
|
|
end else if (s__axi_got_wdata) begin
|
70 |
|
|
if (i_bready) begin
|
71 |
|
|
s__axi_got_wdata <= 1'b0;
|
72 |
|
|
s__axi_idle <= 1'b1;
|
73 |
|
|
end
|
74 |
|
|
end else if (s__axi_got_raddr) begin
|
75 |
|
|
if (i_rready) begin
|
76 |
|
|
s__axi_got_raddr <= 1'b0;
|
77 |
|
|
s__axi_idle <= 1'b1;
|
78 |
|
|
end
|
79 |
|
|
end
|
80 |
|
|
end
|
81 |
|
|
initial o_bvalid = 1'b0;
|
82 |
|
|
always @ (*)
|
83 |
|
|
o_bvalid = s__axi_got_wdata;
|
84 |
4 |
sinclairrf |
reg s__axi_arready_s = 1'b0;
|
85 |
|
|
always @ (posedge i_aclk)
|
86 |
|
|
if (~i_aresetn)
|
87 |
|
|
s__axi_arready_s <= 1'b0;
|
88 |
|
|
else
|
89 |
|
|
s__axi_arready_s <= o_arready;
|
90 |
2 |
sinclairrf |
initial o_rvalid = 1'b0;
|
91 |
4 |
sinclairrf |
always @ (posedge i_aclk)
|
92 |
|
|
if (~i_aresetn)
|
93 |
|
|
o_rvalid <= 1'b0;
|
94 |
|
|
else if (s__axi_arready_s)
|
95 |
|
|
o_rvalid <= 1'b1;
|
96 |
|
|
else if (i_rready)
|
97 |
|
|
o_rvalid <= 1'b0;
|
98 |
|
|
else
|
99 |
|
|
o_rvalid <= o_rvalid;
|
100 |
2 |
sinclairrf |
// signals common to both memory architectures
|
101 |
|
|
reg [L__NBITS_SIZE-1:2] s__axi_addr_s = {(L__NBITS_SIZE-2){1'b0}};
|
102 |
|
|
always @ (posedge i_aclk)
|
103 |
|
|
s__axi_addr_s <= s__axi_addr;
|
104 |
|
|
reg [3:0] s__wstrb = 4'd0;
|
105 |
|
|
genvar ix__wstrb;
|
106 |
|
|
for (ix__wstrb=0; ix__wstrb<4; ix__wstrb=ix__wstrb+1) begin : gen__wstrb
|
107 |
|
|
always @ (posedge i_aclk)
|
108 |
|
|
s__wstrb[ix__wstrb] <= s__axi_got_waddr && i_wvalid && i_wstrb[ix__wstrb];
|
109 |
|
|
end
|
110 |
|
|
reg [7:0] s__mc_wdata = 8'd0;
|
111 |
|
|
always @ (posedge i_clk)
|
112 |
|
|
s__mc_wdata <= s_N;
|
113 |
|
|
// different memory architectures required by different synthesis tools
|
114 |
|
|
if (@MEM8@) begin : gen_mem8
|
115 |
|
|
reg [7:0] s__mem[L__SIZE-1:0];
|
116 |
|
|
genvar ix__mem;
|
117 |
|
|
for (ix__mem=0; ix__mem<4; ix__mem=ix__mem+1) begin : gen__wr
|
118 |
|
|
localparam L__ix_mem = ix__mem;
|
119 |
|
|
always @ (posedge i_aclk) begin
|
120 |
|
|
if (s__wstrb[ix__mem])
|
121 |
|
|
s__mem[{ s__axi_addr_s, L__ix_mem[0+:2] }] = i_wdata[8*ix__mem+:8];
|
122 |
|
|
o_rdata[8*ix__mem+:8] <= s__mem[{ s__axi_addr_s, L__ix_mem[0+:2] }];
|
123 |
|
|
end
|
124 |
|
|
end
|
125 |
|
|
// Micro controller side of the dual-port memory.
|
126 |
|
|
reg s__mc_wr = 1'b0;
|
127 |
|
|
always @ (posedge i_clk)
|
128 |
|
|
s__mc_wr <= s_outport && (s_T == @IX_WRITE@);
|
129 |
|
|
reg [L__NBITS_SIZE-1:0] s__mc_addr_s = {(L__NBITS_SIZE){1'b0}};
|
130 |
|
|
always @ (posedge i_clk) begin
|
131 |
|
|
s__mc_addr_s <= s__mc_addr;
|
132 |
|
|
if (s__mc_wr)
|
133 |
|
|
s__mem[s__mc_addr_s] = s__mc_wdata;
|
134 |
|
|
s__mc_rdata <= s__mem[s__mc_addr_s];
|
135 |
|
|
end
|
136 |
|
|
end else begin : gen_mem32
|
137 |
|
|
reg [31:0] s__mem[L__SIZE/4-1:0];
|
138 |
|
|
integer ix__axi;
|
139 |
|
|
always @ (posedge i_aclk)
|
140 |
|
|
for (ix__axi=0; ix__axi<4; ix__axi=ix__axi+1)
|
141 |
|
|
if (s__wstrb[ix__axi]) s__mem[s__axi_addr_s][8*ix__axi+:8] = i_wdata[8*ix__axi+:8];
|
142 |
|
|
always @ (posedge i_aclk)
|
143 |
|
|
o_rdata <= s__mem[s__axi_addr_s];
|
144 |
|
|
// Micro controller side of the dual-port memory.
|
145 |
|
|
reg [L__NBITS_SIZE-1:2] s__mc_addr_s = {(L__NBITS_SIZE-2){1'b0}};
|
146 |
|
|
always @ (posedge i_clk)
|
147 |
|
|
s__mc_addr_s <= s__mc_addr[L__NBITS_SIZE-1:2];
|
148 |
|
|
integer ix__mc_wr;
|
149 |
|
|
reg [3:0] s__mc_wr = 4'd0;
|
150 |
|
|
always @ (posedge i_clk)
|
151 |
|
|
for (ix__mc_wr=0; ix__mc_wr<4; ix__mc_wr=ix__mc_wr+1)
|
152 |
|
|
s__mc_wr[ix__mc_wr] <= s_outport && (s_T == @IX_WRITE@) && (s__mc_addr[0+:2] == ix__mc_wr[0+:2]);
|
153 |
|
|
integer ix__mc_we;
|
154 |
|
|
always @ (posedge i_clk)
|
155 |
|
|
for (ix__mc_we=0; ix__mc_we<4; ix__mc_we=ix__mc_we+1)
|
156 |
|
|
if (s__mc_wr[ix__mc_we]) s__mem[s__mc_addr_s][8*ix__mc_we+:8] = s__mc_wdata;
|
157 |
|
|
reg [31:0] s__mc_rdata32 = 32'd0;
|
158 |
|
|
always @ (posedge i_clk)
|
159 |
|
|
s__mc_rdata32 <= s__mem[s__mc_addr_s];
|
160 |
|
|
always @ (*)
|
161 |
|
|
s__mc_rdata = (s__mc_addr[0+:2] == 2'd0) ? s__mc_rdata32[ 0+:8]
|
162 |
|
|
: (s__mc_addr[0+:2] == 2'd1) ? s__mc_rdata32[ 8+:8]
|
163 |
|
|
: (s__mc_addr[0+:2] == 2'd2) ? s__mc_rdata32[16+:8]
|
164 |
|
|
: s__mc_rdata32[24+:8];
|
165 |
|
|
end
|
166 |
|
|
endgenerate
|