存储器在FPGA设计中可分为两类:一类是FPGA自带的存储单元,这些存储单元可以灵活设置成ROM、SRAM、FIFO及所需要的其他形式,使用方便;但是FPGA自带的存储器与FPGA的等级有关,等级越高,存储器容量越大,价格也就越高。另一类是FPGA的外部存储器,他们的大嘴有点就是存储容量不再是问题,不过他们一般专有一种功能,要么是ROM,要么就是SRAM,再者就是FIFO等,而且操作也比前一类更为复杂。
下面说一个找工作面试官最容易问到的低级问题,那就是:你所使用的微处理器的内部存储器有多大?
Cyclone II 内嵌存储器是由多列M4K存储器块组成,每个M4K块相当于4608RAM位,是这样计算得来的:
M4k+512位校验位= 4*1024+512=4608 M4K指的是4kbits
而开发板使用的EP2C8具有36个M4K RAM块(4K位+512位校验位),所以RAM位总位数是:165888。
下面贴出的是用于存储char型字符的ROM设计:
/*******************************************************
ROM Design
********************************************************/
module char_rom(
address ,
data
);
input [5:0]address; //输入地址
output [7:0]data;
//输出数据
reg [7:0]data;
//输出数据时reg类型
function [7:0] char_to_integer; //这里使用了function,注意function的使用方法
input [7:0]indata;
reg [7:0]result; //一个字符型需要8bit来装
begin
case(indata)
" " :
result = 32; //字符型要使用双引号
"!" :
result = 33;
"\"" :
result = 34;
"#" :
result = 35;
"$" :
result = 36;
"%" :
result = 37;
"&" :
result = 38;
"'" :
result = 39;
"(" :
result = 40;
")" :
result = 41;
"*" :
result = 42;
"+" :
result = 43;
"," :
result = 44;
"-" :
result = 45;
"." :
result = 46;
"/" :
result = 47;
"0" :
result = 48;
"1" :
result = 49;
"2" :
result = 50;
"3" :
result = 51;
"4" :
result = 52;
"5" :
result = 53;
"6" :
result = 54;
"7" :
result = 55;
"8" :
result = 56;
"9" :
result = 57;
":" :
result = 58;
";" :
result = 59;
"<" :
result = 60;
"=" :
result = 61;
">" :
result = 62;
"?" :
result = 63;
"@" :
result = 64;
"A" :
result = 65;
"B" :
result = 66;
"C" :
result = 67;
"D" :
result = 68;
"E" :
result = 69;
"F" :
result = 70;
"G" :
result = 71;
"H" :
result = 72;
"I" :
result = 73;
"J" :
result = 74;
"K" :
result = 75;
"L" :
result = 76;
"M" :
result = 77;
"N" :
result = 78;
"O" :
result = 79;
"P" :
result = 80;
"Q" :
result = 81;
"R" :
result = 82;
"S" :
result = 83;
"T" :
result = 84;
"U" :
result = 85;
"V" :
result = 86;
"W" :
result = 87;
"X" :
result = 88;
"Y" :
result = 89;
"Z" :
result = 90;
"[" :
result = 91;
//
"\\" :
result = 92;
"]" :
result = 93;
"^" :
result = 94;
"_" :
result = 95;
"`" :
result = 96;
"a" :
result = 97;
"b" :
result = 98;
"c" :
result = 99;
"d" :
result = 100;
"e" :
result = 101;
"f" :
result = 102;
"g" :
result = 103;
"h" :
result = 104;
"i" :
result = 105;
"j" :
result = 106;
"k" :
result = 107;
"l" :
result = 108;
"m" :
result = 109;
"n" :
result = 110;
"o" :
result = 111;
"p" :
result = 112;
"q" :
result = 113;
"r" :
result = 114;
"s" :
result = 115;
"t" :
result = 116;
"u" :
result = 117;
"v" :
result = 118;
"w" :
result = 119;
"x" :
result = 120;
"y" :
result = 121;
"z" :
result = 122;
"{" :
result = 123;
"|" :
result = 124;
"}" :
result = 125;
"~" :
result = 126;
default : result = 32;
endcase
char_to_integer = result;
end
endfunction
always @(address)
begin
case (address) //根据地址调用相应的数据
6'b000000 :data <= char_to_integer ("W");
6'b000001 :data <= char_to_integer ("e");
6'b000010 :data <= char_to_integer ("l");
6'b000011 :data <= char_to_integer ("e");
6'b000100 :data <= char_to_integer ("c");
6'b000101 :data <= char_to_integer ("o");
6'b000110 :data <= char_to_integer ("m");
6'b000111 :data <= char_to_integer ("e");
6'b001000 :data <= char_to_integer (" ");
6'b001001 :data <= char_to_integer (" ");
6'b001010 :data <= char_to_integer ("B");
6'b001011 :data <= char_to_integer ("A");
6'b001100 :data <= char_to_integer ("I");
6'b001101 :data <= char_to_integer ("X");
6'b001110 :data <= char_to_integer ("U");
6'b001111 :data <= char_to_integer ("N");
6'b010000 :data <= char_to_integer (" ");
6'b010001 :data <= char_to_integer (" ");
6'b010010 :data <= char_to_integer ("B");
6'b010011 :data <= char_to_integer ("o");
6'b010100 :data <= char_to_integer ("a");
6'b010101 :data <= char_to_integer ("r");
6'b010110 :data <= char_to_integer ("d");
6'b010111 :data <= char_to_integer ("!");
default :data <= char_to_integer (" ");
endcase
end
endmodule
这里值得一提的是function的使用方法,多个输入,但是只能有一个输出,输出就是函数名本身,所以定义函数的时候应该设定输出的范围,不然会被默认为一位。而定义字符型的时候不用像VHDL那样专门指出是character类型,而是直接使用一个8位的reg即可,而且字符和VHDL的表示也不一样,VHDL里面是使用了单引号表示字符,而verilog无论是字符还是字符串都应该使用双引号。而存储多个字符串的时候也不用使用数组,只要把reg位数设置足够宽就行了,例如 reg [0:31]love = "love"; 4*8 =32bit;
当然如果需要装载比较大的内容的时候,我们还使用这样的方法就显得很麻烦,很多工具书都有介绍使用LMP来完成片上ROM的设计,这种方法很简单,在初始化ROM的时候只要(.mif)文件里面输出需要存储的内容即可。
我相信,只要脚踏实地积累,总会有“玩转”的一天。