URL
https://opencores.org/ocsvn/thor/thor/trunk
Subversion Repositories thor
[/] [thor/] [trunk/] [FT64/] [rtl/] [common/] [cam.v] - Rev 48
Go to most recent revision | Compare with Previous | Blame | View Log
// ============================================================================ // __ // \\__/ o\ (C) 2017-2018 Robert Finch, Waterloo // \ __ / All rights reserved. // \/_// robfinch<remove>@finitron.ca // || // // cam.v // CAM primitives // // // This source file is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This source file is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // // // The cam is implemented as two memories. The first memory is the data memory // which is used to store the data as per usual. The second memory is a bitmap // of which memory locations the data is stored in. // Because two memories are used writing is a two step process. First the // bit of where the old data is stored must be updated by clearing it for old // data. Next the bitmap of the data storage is set for the new data. // ============================================================================ // //`define DUAL_READ 1'b1 module cam6x32(clk, we, wr_addr, din, cmp_din, match_addr, match); input clk; input we; input [4:0] wr_addr; input [5:0] din; input [5:0] cmp_din; output [31:0] match_addr; output match; (* RAM_STYLE="DISTRIBUTED" *) reg [31:0] bmem [0:63]; reg [5:0] dmem [0:31]; reg [5:0] din2; integer n; initial begin for (n = 0; n < 64; n = n + 1) bmem[n] = 0; for (n = 0; n < 32; n = n + 1) dmem[n] = 0; end reg we2; wire [5:0] madr = (we2 & ~we) ? din2 : we ? dmem[wr_addr] : cmp_din; always @(posedge clk) begin din2 <= din; we2 <= we; if (we & ~we2) bmem[madr] <= bmem[madr] & ~(32'd1 << wr_addr); else if (we2 & ~we) bmem[madr] <= bmem[madr] | (32'd1 << wr_addr); if (we2 & ~we) dmem[wr_addr] <= din2; end assign match_addr = bmem[madr]; assign match = |match_addr; endmodule // Write six bits of data to one of 64 addresses module cam6x64(rst, clk, we, wr_addr, din, cmp_din, match_addr, match); input rst; input clk; input we; input [5:0] wr_addr; input [5:0] din; input [5:0] cmp_din; output [63:0] match_addr; output match; (* RAM_STYLE="DISTRIBUTED" *) reg [63:0] bmem [0:63]; reg [5:0] dmem [0:63]; reg [5:0] din2; integer n; initial begin for (n = 0; n < 64; n = n + 1) bmem[n] = 0; for (n = 0; n < 64; n = n + 1) dmem[n] = 0; end reg we2; wire [5:0] madr = (we2 & ~we) ? din2 : we ? dmem[wr_addr] : cmp_din; always @(posedge clk) din2 <= din; always @(posedge clk) we2 <= we; // This looks like it might be updating the same address during we and we2 ubt // bmem[adr] actually likely changes inbetween the write pulses due to an // update of dmem[wr_addr]. always @(posedge clk) if (rst) begin for (n = 0; n < 64; n = n + 1) bmem[n] <= 0; end else begin if (we & ~we2) bmem[madr] <= bmem[madr] & ~(64'd1 << wr_addr); else if (we2 & ~we) bmem[madr] <= bmem[madr] | (64'd1 << wr_addr); end always @(posedge clk) if (rst) begin for (n = 0; n < 64; n = n + 1) dmem[n] <= 0; end else begin if (we2 & ~we) dmem[wr_addr] <= din2; end `ifdef DUAL_READ assign match_addr = bmem[cmp_din]; `else assign match_addr = bmem[madr]; `endif assign match = |match_addr; endmodule // Write six bits of data to one of 64 addresses module cam6x256(rst, clk, we, wr_addr, din, cmp_din, match_addr, match); input rst; input clk; input we; input [7:0] wr_addr; input [5:0] din; input [5:0] cmp_din; output [255:0] match_addr; output match; reg [255:0] bmem [0:63]; reg [5:0] dmem [0:255]; reg [5:0] din2; integer n; initial begin for (n = 0; n < 64; n = n + 1) bmem[n] = 0; for (n = 0; n < 256; n = n + 1) dmem[n] = 0; end reg we2; wire [5:0] madr = (we2 & ~we) ? din2 : we ? dmem[wr_addr] : cmp_din; always @(posedge clk) din2 <= din; always @(posedge clk) we2 <= we; // This looks like it might be updating the same address during we and we2 ubt // bmem[adr] actually likely changes inbetween the write pulses due to an // update of dmem[wr_addr]. always @(posedge clk) if (rst) begin for (n = 0; n < 64; n = n + 1) bmem[n] <= 0; end else begin if (we & ~we2) bmem[madr] <= bmem[madr] & ~(256'd1 << wr_addr); else if (we2 & ~we) bmem[madr] <= bmem[madr] | (256'd1 << wr_addr); end always @(posedge clk) if (rst) begin for (n = 0; n < 256; n = n + 1) dmem[n] <= 0; end else begin if (we2 & ~we) dmem[wr_addr] <= din2; end assign match_addr = bmem[madr]; assign match = |match_addr; endmodule module cam36x32(clk, we, wr_addr, din, cmp_din, match_addr, match); input clk; input we; input [4:0] wr_addr; input [35:0] din; input [35:0] cmp_din; output [31:0] match_addr; output match; wire [31:0] match_addr0, match_addr1, match_addr2, match_addr3, match_addr4, match_addr5; wire [31:0] match_addr = match_addr0 & match_addr1 & match_addr2 & match_addr3 & match_addr4 & match_addr5; DSD9_cam6x32 u1 (clk, we, wr_addr, din[ 5: 0], cmp_din[ 5: 0], match_addr0); DSD9_cam6x32 u2 (clk, we, wr_addr, din[11: 6], cmp_din[11: 6], match_addr1); DSD9_cam6x32 u3 (clk, we, wr_addr, din[17:12], cmp_din[17:12], match_addr2); DSD9_cam6x32 u4 (clk, we, wr_addr, din[23:18], cmp_din[23:18], match_addr3); DSD9_cam6x32 u5 (clk, we, wr_addr, din[29:24], cmp_din[29:24], match_addr4); DSD9_cam6x32 u6 (clk, we, wr_addr, din[35:30], cmp_din[35:30], match_addr5); assign match = |match_addr; endmodule module cam36x64(rst, clk, we, wr_addr, din, cmp_din, match_addr, match); input rst; input clk; input we; input [5:0] wr_addr; input [35:0] din; input [35:0] cmp_din; output [63:0] match_addr; output match; wire [63:0] match_addr0, match_addr1, match_addr2, match_addr3, match_addr4, match_addr5; wire [63:0] match_addr = match_addr0 & match_addr1 & match_addr2 & match_addr3 & match_addr4 & match_addr5; cam6x64 u1 (rst, clk, we, wr_addr, din[ 5: 0], cmp_din[ 5: 0], match_addr0); cam6x64 u2 (rst, clk, we, wr_addr, din[11: 6], cmp_din[11: 6], match_addr1); cam6x64 u3 (rst, clk, we, wr_addr, din[17:12], cmp_din[17:12], match_addr2); cam6x64 u4 (rst, clk, we, wr_addr, din[23:18], cmp_din[23:18], match_addr3); cam6x64 u5 (rst, clk, we, wr_addr, din[29:24], cmp_din[29:24], match_addr4); cam6x64 u6 (rst, clk, we, wr_addr, din[35:30], cmp_din[35:30], match_addr5); assign match = |match_addr; endmodule
Go to most recent revision | Compare with Previous | Blame | View Log