📄 blockgen.java
字号:
import java.io.*;import java.util.*;/** * Generate a memory module using one or more BlockRams with the appropriate * address and data decoding and pre-initialization. * * Can use either a text file with hex values or Altera-style MIF file for * initialization data. * * @author Ed Anuff (ed@anuff.com) * */public class BlockGen { static String build_date = "Feb 2 2004 4:01 PM PST"; int depth = 512; int width = 8; int block = 4096; String src_filename = ""; String dst_filename = ""; File src_file; String module_name = ""; String dst_dir = ""; boolean init_ram = false; boolean preserve_depth = false; public BlockGen(String[] args) { processOptions(args); } public void process() { try { if (!stringEmpty(src_filename)) { src_file = new File(src_filename); dst_dir = src_file.getParent(); } if (stringEmpty(module_name) && (src_file.getName().indexOf('.') > 0)) { module_name = src_file.getName().substring(0, src_file.getName().indexOf('.')); } if (stringEmpty(module_name)) module_name = "ram"; if (stringEmpty(dst_filename)) dst_filename = dst_dir + File.separator + module_name + ".vhd"; System.out.println("BlockRam Generator"); System.out.println("Module: " + module_name); String binary_string = ""; if (!stringEmpty(src_filename)) { File file = new File(src_filename); if (!file.exists()) { System.out.println("Input file not found: " + src_filename); System.exit(-1); } init_ram = true; if (src_filename.endsWith(".mif")) binary_string = parseMifFile(); else binary_string = parseTextFile(); } if (init_ram) { System.out.println("Input file: " + src_filename); } else { System.out.println("No input file for pre-initialization specified."); } System.out.println("Output file: " + dst_filename); PrintWriter pw = new PrintWriter(new FileWriter(dst_filename)); int bitcount = width * depth; if (init_ram) bitcount = binary_string.length(); int block_bitcount = width * depth; if (bitcount > block_bitcount) { System.out.println("Data (" + bitcount + " bits) is larger than BlockRam capacity at the specified width and depth."); System.exit(1); } if ((bitcount % width) != 0) { System.out.println("Input data not bit aligned to the specified width."); System.exit(1); } int block_count = 1; int port_width = 1; int max_port_width = 16; boolean ramb16 = block == 16384; if (ramb16) max_port_width = 32; while (port_width <= max_port_width) { if (depth <= (block / port_width)) { block_count = width / port_width; } if (depth * 2 > (block / port_width)) { break; } port_width = port_width * 2; } if (port_width > max_port_width) port_width = max_port_width; if (block_count < 1) block_count = 1; int pl = 0; int ph = port_width - 1; int ah = Integer.toBinaryString((block / port_width) - 1).length() - 1; int wh = width - 1; int pbh = 0; int cpw = port_width; if (port_width == 16) { pbh = 1; } else if (port_width == 32) { pbh = 3; } String pbhi = zero(pbh + 1); if (ramb16) cpw = port_width + pbh + 1; boolean pad_addr = false; int mah = ah; String addr_prefix = ""; if (preserve_depth) { mah = Integer.toBinaryString(depth - 1).length() - 1; if (mah < ah) { pad_addr = true; addr_prefix = "p_"; } } String rtype = "RAMB4"; String rsta = "RSTA"; String rstb = "RSTB"; if (ramb16) { rtype = "RAMB16"; rsta = "SSRA"; rstb = "SSRB"; } pw.println("--"); pw.println("-- " + (new File(dst_filename)).getName()); pw.println("--"); pw.println("-- Generated by BlockGen"); pw.println("-- " + (new Date()).toLocaleString()); pw.println("--"); if (ramb16) pw.println("-- This module will synthesize on Spartan3 and Virtex2/2Pro/2ProX devices."); else pw.println("-- This module will synthesize on Spartan2/2E and Virtex/E devices."); pw.println("--"); pw.println(); pw.println("library IEEE;"); pw.println("use IEEE.std_logic_1164.all;"); pw.println("use IEEE.std_logic_arith.all;"); pw.println("use IEEE.std_logic_unsigned.all;"); pw.println("library unisim;"); pw.println("use unisim.vcomponents.all;"); pw.println(); pw.println("entity " + module_name + " is"); pw.println("\tport ("); pw.println("\t\ta_rst : in std_logic;"); pw.println("\t\ta_clk : in std_logic;"); pw.println("\t\ta_en : in std_logic;"); pw.println("\t\ta_wr : in std_logic;"); pw.println("\t\ta_addr : in std_logic_vector(" + mah + " downto 0);"); pw.println("\t\ta_din : in std_logic_vector(" + wh + " downto 0);"); pw.println("\t\ta_dout : out std_logic_vector(" + wh + " downto 0);"); pw.println("\t\tb_rst : in std_logic;"); pw.println("\t\tb_clk : in std_logic;"); pw.println("\t\tb_en : in std_logic;"); pw.println("\t\tb_wr : in std_logic;"); pw.println("\t\tb_addr : in std_logic_vector(" + mah + " downto 0);"); pw.println("\t\tb_din : in std_logic_vector(" + wh + " downto 0);"); pw.println("\t\tb_dout : out std_logic_vector(" + wh + " downto 0)"); pw.println("\t);"); pw.println("end " + module_name + ";"); pw.println(); pw.println("architecture rtl of " + module_name + " is"); pw.println(); pw.println("\tcomponent " + rtype + "_S" + cpw + "_S" + cpw); pw.println("\t\tport ("); pw.println("\t\t\tDIA : in std_logic_vector (" + ph + " downto 0);"); pw.println("\t\t\tDIB : in std_logic_vector (" + ph + " downto 0);"); pw.println("\t\t\tENA : in std_logic;"); pw.println("\t\t\tENB : in std_logic;"); pw.println("\t\t\tWEA : in std_logic;"); pw.println("\t\t\tWEB : in std_logic;"); pw.println("\t\t\t" + rsta + " : in std_logic;"); pw.println("\t\t\t" + rstb + " : in std_logic;"); if (ramb16 && (port_width >= 8)) { pw.println("\t\t\tDIPA : in std_logic_vector (" + pbh + " downto 0);"); pw.println("\t\t\tDIPB : in std_logic_vector (" + pbh + " downto 0);"); pw.println("\t\t\tDOPA : out std_logic_vector (" + pbh + " downto 0);"); pw.println("\t\t\tDOPB : out std_logic_vector (" + pbh + " downto 0);"); } pw.println("\t\t\tCLKA : in std_logic;"); pw.println("\t\t\tCLKB : in std_logic;"); pw.println("\t\t\tADDRA : in std_logic_vector (" + ah + " downto 0);"); pw.println("\t\t\tADDRB : in std_logic_vector (" + ah + " downto 0);"); pw.println("\t\t\tDOA : out std_logic_vector (" + ph + " downto 0);"); pw.println("\t\t\tDOB : out std_logic_vector (" + ph + " downto 0)"); pw.println("\t\t); "); pw.println("\tend component;"); pw.println(); if (init_ram) { pw.println("\tattribute INIT: string;"); int attribute_count = block / 256; for (int i = 0; i < attribute_count; i ++) { pw.println("\tattribute INIT_" + toHex(i, 2) + ": string;"); } pw.println(); for (int block_i = 0; block_i < block_count; block_i ++) { String block_bits = getBlockBits(binary_string, port_width, width, block_i); block_bits = padTrailingBitsToBlockSize(block_bits, block); String[] init_string = split(block_bits, 256); for (int i = 0; i < init_string.length; i++ ) { String init_hex = longBinaryStringToHex(reverse(init_string[i], port_width)); pw.println("\tattribute INIT_" + toHex(i, 2) + " of cmp_ram_" + block_i + ": label is \"" + init_hex + "\";"); } pw.println(); } } if (pad_addr) { pw.println("\tsignal p_a_addr : std_logic_vector (" + ah + " downto 0);"); pw.println("\tsignal p_b_addr : std_logic_vector (" + ah + " downto 0);"); pw.println(); } pw.println("begin"); pw.println(); if (pad_addr) { pw.println("\tp_a_addr <= \"" + zero(ah - mah) + "\" & a_addr;"); pw.println("\tp_b_addr <= \"" + zero(ah - mah) + "\" & b_addr;"); pw.println(); } for (int block_i = 0; block_i < block_count; block_i ++) { pw.println("\tcmp_ram_" + block_i + " : " + rtype + "_S" + cpw + "_S" + cpw); pw.println("\t\tport map ("); pw.println("\t\t\tWEA => a_wr,"); pw.println("\t\t\tWEB => b_wr,"); pw.println("\t\t\tENA => a_en,"); pw.println("\t\t\tENB => b_en,"); pw.println("\t\t\t" + rsta + " => a_rst,"); pw.println("\t\t\t" + rstb + " => b_rst,"); if (ramb16 && (port_width >= 8)) { pw.println("\t\t\tDIPA => \"" + pbhi + "\","); pw.println("\t\t\tDIPB => \"" + pbhi + "\","); pw.println("\t\t\tDOPA => open,"); pw.println("\t\t\tDOPB => open,"); } pw.println("\t\t\tCLKA => a_clk,"); pw.println("\t\t\tCLKB => b_clk,"); pw.println("\t\t\tDIA => a_din(" + ph + " downto " + pl + "),"); pw.println("\t\t\tADDRA => " + addr_prefix + "a_addr,"); pw.println("\t\t\tDOA => a_dout(" + ph + " downto " + pl + "),"); pw.println("\t\t\tDIB => b_din(" + ph + " downto " + pl + "),"); pw.println("\t\t\tADDRB => " + addr_prefix + "b_addr,"); pw.println("\t\t\tDOB => b_dout(" + ph + " downto " + pl + ")"); pw.println("\t\t);"); pw.println(); pl += port_width; ph += port_width; } pw.println("end rtl;"); pw.close(); System.out.print(block_count + " block"); if (block_count > 1) System.out.print("s"); System.out.println(" used (" + block + " bits/block)."); System.out.println("Done."); } catch (IOException e) { System.out.println(e.getMessage()); System.exit(-1); } } private static final int SEEK_GENERAL = 0; private static final int SEEK_ADDR = 1; private static final int SEEK_DATA = 2; /** * Parse a file in Altera MIF file format. * * @return String containing binary data * @throws IOException */ public String parseMifFile() throws IOException { FileReader fr = new FileReader(src_filename); StreamTokenizer st = new StreamTokenizer(fr); st.resetSyntax(); st.eolIsSignificant(true); st.slashStarComments(true); st.slashSlashComments(true); st.lowerCaseMode(true); st.commentChar('%'); st.commentChar('-'); st.wordChars('0', '9'); st.wordChars('a', 'z'); st.wordChars('A', 'Z'); st.wordChars('_', '_'); st.wordChars('[', '['); st.wordChars(']', ']'); st.wordChars('.', '.'); st.whitespaceChars(0, ' '); int state = SEEK_GENERAL; int address_radix = 16; int data_radix = 16; int addr = 0; int addr_range_lo = 0; int addr_range_hi = 0; boolean is_addr_range = false; long[] mem = null; while (st.nextToken() != StreamTokenizer.TT_EOF) { if (state == SEEK_GENERAL) { if ("width".equalsIgnoreCase(st.sval)) { st.nextToken(); st.nextToken(); if (!stringEmpty(st.sval)) { width = Integer.parseInt(st.sval); } } else if ("depth".equalsIgnoreCase(st.sval)) { st.nextToken(); st.nextToken(); if (!stringEmpty(st.sval)) { depth = Integer.parseInt(st.sval); mem = new long[depth]; } } else if ("address_radix".equalsIgnoreCase(st.sval)) { st.nextToken(); st.nextToken(); if ("bin".equalsIgnoreCase(st.sval)) address_radix = 2; else if ("dec".equalsIgnoreCase(st.sval)) address_radix = 10; else if ("hex".equalsIgnoreCase(st.sval)) address_radix = 16; else if ("oct".equalsIgnoreCase(st.sval)) address_radix = 8; } else if ("data_radix".equalsIgnoreCase(st.sval)) { st.nextToken(); st.nextToken(); if ("bin".equalsIgnoreCase(st.sval)) data_radix = 2; else if ("dec".equalsIgnoreCase(st.sval)) data_radix = 10; else if ("hex".equalsIgnoreCase(st.sval)) data_radix = 16; else if ("oct".equalsIgnoreCase(st.sval)) data_radix = 8; } else if ("begin".equalsIgnoreCase(st.sval)) { state = SEEK_ADDR; } } else if ((state == SEEK_ADDR) && (st.ttype == StreamTokenizer.TT_WORD)) { if (!stringEmpty(st.sval)) { if ("end".equalsIgnoreCase(st.sval)) { break; } else if (st.sval.startsWith("[")) { is_addr_range = true; addr_range_lo = Integer.parseInt(st.sval.substring(1, st.sval.indexOf('.')), address_radix); addr_range_hi = Integer.parseInt(st.sval.substring(st.sval.lastIndexOf('.') + 1, st.sval.length() - 1), address_radix); } else { is_addr_range = false; addr = Integer.parseInt(st.sval, address_radix); } state = SEEK_DATA; } } else if ((state == SEEK_DATA) && (st.ttype == StreamTokenizer.TT_EOL)) { state = SEEK_ADDR; } else if ((state == SEEK_DATA) && (st.ttype == StreamTokenizer.TT_WORD)) { if (!stringEmpty(st.sval)) { long data = Long.parseLong(st.sval, data_radix); if (is_addr_range) { for (addr = addr_range_lo; addr <= addr_range_hi; addr++) { if (addr >= 0 && addr < mem.length) mem[addr] = data; else { System.out.println("Warning: Data at address " + addr + " is outside the range of the specified depth."); } } } else { if (addr >= 0 && addr < mem.length) mem[addr] = data; else { System.out.println("Warning: Data at address " + addr + " is outside the range of the specified depth."); } } addr++; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -