基于ROM的乘法器
1、原理简介
乘法器的另一种实现思想是采用ROM的方式,即将被乘数和乘数连接起来拼成地址,把两者所有可能的乘积按照地址放在ROM的地址空间中,两个数相乘时,根据两者构成的地址从ROM中读取乘积结果。ROM可采用分布式逻辑资源实现(用于存储数据量小的情况比较合适),也可采用嵌入式BRAM实现(用于存储量数据大的情况比较合适)。 两个N-bit的二进制数相乘,其结果为2N-bit。这意味着ROM的深度为2的2N次方,宽度为2N。以两个4-bit数相乘为例,其存储空间的大小为256x8-bit(256为深度,8为宽度),显然,随着位宽的增加存储空间将以指数速度膨胀。 改进方法:将被乘数和乘数进行位分解,即将大位宽的数分解为多个小位宽的数来分别相乘。例如两个4-bit数相乘,可将4-bit数分解成两个2-bit数,为了保证最终乘积结果的正确性,需要对中间结果进行移位。为方便起见,以两个无符号二进制数1101(对应十进制为11)和0110(对应十进制数为0110)相乘为例。其相乘位分解处理流程如下图所示。采用的ROM深度为16,宽度为4。存储的内容为两个无符号数相乘的结果。地址及其对应的存储内容如下:地址 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 内容(十进制) 0 0 0 0 0 1 2 3 0 2 4 6 0 3 6 9 内容(十进制) 0000 0000 0000 0000 0000 0001 0010 0011 0000 0010 0100 0110 0000 0011 0110 1001
2、verilog代码实现 2.1节介绍ROM使用Distributed Memory Generator生成的IP核。2.2节介绍使用Xilinx原语生成的ROM(其实使用的也是分布式资源)。Block Memeory Generator生成的IP核使用的是BlockRAM,当存储大量数据时,使用比较方便,和Distributed Memory Generator类似,不再详细介绍。2.1ROM采用分布式资源生成的IP核设置ROM的位宽,深度等。ROM进行初始化,采用coe文件。coe文件的内容为:MEMORY_INITIALIZATION_RADIX=10;MEMORY_INITIALIZATION_VECTOR=0,0,0,0,0,1,2,3,0,2,4,6,0,3,6,9;说明:MEMORY_INITIALIZATION_RADIX=10,表明下面的数据为10进制,还可以取值2,8,16。MEMORY_INITIALIZATION_VECTOR=,后面的内容依次为地址(0-15)所存储的内容,中间用逗号分隔,最后用分号。最后生成ROM核。verilog代码实现module rom_top( input clk, input rst_n, input [3:0] a, input [3:0] b, output [7:0] c ); wire [3:0] spo0,spo1,spo2,spo3; wire [3:0] a0,a1,a2,a3; assign a0={a[3:2],b[3:2]}; assign a1={a[3:2],b[1:0]}; assign a2={a[1:0],b[3:2]}; assign a3={a[1:0],b[1:0]}; reg [7:0] spo0_r,spo1_r,spo2_r,spo3_r; always@(posedge clk) begin if(!rst_n) begin spo0_r<=0;spo1_r<=0;spo2_r<=0;spo3_r<=0; end else begin spo0_r<={spo0,4'b0000}; spo1_r<={2'b00,spo1,2'b00}; spo2_r<={2'b00,spo2,2'b00}; spo3_r<={spo3}; end end assign c=(spo0_r+spo1_r)+(spo2_r+spo3_r); // Instantiate the Unit Under Test (UUT) rom uut0 ( //rom为生成的IP核 .a(a0), .spo(spo0) ); rom uut1 ( .a(a1), .spo(spo1) ); rom uut2 ( .a(a2), .spo(spo2) ); rom uut3 ( .a(a3), .spo(spo3) ); endmodule testbench文件 module romtop_tb; // Inputs reg clk; reg rst_n; reg [3:0] a; reg [3:0] b; // Outputs wire [7:0] c; // Instantiate the Unit Under Test (UUT) rom_top uut ( .clk(clk), .rst_n(rst_n), .a(a), .b(b), .c(c) ); always #5 clk = ~clk; initial begin // Initialize Inputs clk = 0; rst_n = 0; a = 0; b = 0; // Wait 100 ns for global reset to finish #100; rst_n=1; #10; #3; a=2;b=6; #10; a=3;b=7; #10; a=15;b=9; #10; a=12;b=11; #10; a=6;b=7; #100 $stop; // Add stimulus here end endmodule在modelsim中仿真生成的波形图:axb=c. 2x6=12 3x7=21 15x9=1352.2ROM采用Xilinx原语生成verilog代码module d_rom_top( input clk, input rst_n, input [3:0] a, input [3:0] b, output [7:0] c ); wire [3:0] addra,addrb,addrc,addrd; assign addra={a[3:2],b[3:2]}; assign addrb={a[3:2],b[1:0]}; assign addrc={a[1:0],b[3:2]}; assign addrd={a[1:0],b[1:0]}; wire [3:0] Oa,Ob,Oc,Od; reg [7:0] Oa_r,Ob_r,Oc_r,Od_r; always@(posedge clk)begin if(!rst_n) begin Oa_r<=0;Ob_r<=0;Oc_r<=0;Od_r<=0; end else begin Oa_r<={Oa,4'b0000}; Ob_r<={2'b00,Ob,2'b00}; Oc_r<={2'b00,Oc,2'b00}; Od_r<={4'b0000,Od}; end end assign c=Oa_r+Ob_r+Oc_r+Od_r; genvar i0,i1,i2,i3; generate for(i0=0;i0<4;i0=i0+1) begin :rom_unita if(i0==0) begin ROM16X1 #(.INIT(16'b1010_0000_1010_0000)) rom_0 (.O(Oa[0]),.A0(addra[0]),.A1(addra[1]),.A2(addra[2]),.A3(addra[3])); end else if(i0==1)begin ROM16X1 #(.INIT(16'b0110_1010_1100_0000)) rom_1 (.O(Oa[1]),.A0(addra[0]),.A1(addra[1]),.A2(addra[2]),.A3(addra[3])); end else if(i0==2)begin ROM16X1 #(.INIT(16'b0100_1100_0000_0000)) rom_2 (.O(Oa[2]),.A0(addra[0]),.A1(addra[1]),.A2(addra[2]),.A3(addra[3])); end elsebegin ROM16X1 #(.INIT(16'b1000_0000_0000_0000)) rom_3 (.O(Oa[3]),.A0(addra[0]),.A1(addra[1]),.A2(addra[2]),.A3(addra[3])); end end endgenerate generate for(i1=0;i1<4;i1=i1+1) begin :rom_unitb if(i1==0) begin ROM16X1 #(.INIT(16'b1010_0000_1010_0000)) rom_0 (.O(Ob[0]),.A0(addrb[0]),.A1(addrb[1]),.A2(addrb[2]),.A3(addrb[3])); end else if(i1==1)begin ROM16X1 #(.INIT(16'b0110_1010_1100_0000)) rom_1 (.O(Ob[1]),.A0(addrb[0]),.A1(addrb[1]),.A2(addrb[2]),.A3(addrb[3])); end else if(i1==2)begin ROM16X1 #(.INIT(16'b0100_1100_0000_0000)) rom_2 (.O(Ob[2]),.A0(addrb[0]),.A1(addrb[1]),.A2(addrb[2]),.A3(addrb[3])); end elsebegin ROM16X1 #(.INIT(16'b1000_0000_0000_0000)) rom_3 (.O(Ob[3]),.A0(addrb[0]),.A1(addrb[1]),.A2(addrb[2]),.A3(addrb[3])); end end endgenerate generate for(i2=0;i2<4;i2=i2+1) begin :rom_unitc if(i2==0) begin ROM16X1 #(.INIT(16'b1010_0000_1010_0000)) rom_0 (.O(Oc[0]),.A0(addrc[0]),.A1(addrc[1]),.A2(addrc[2]),.A3(addrc[3])); end else if(i2==1)begin ROM16X1 #(.INIT(16'b0110_1010_1100_0000)) rom_1 (.O(Oc[1]),.A0(addrc[0]),.A1(addrc[1]),.A2(addrc[2]),.A3(addrc[3])); end else if(i2==2)begin ROM16X1 #(.INIT(16'b0100_1100_0000_0000)) rom_2 (.O(Oc[2]),.A0(addrc[0]),.A1(addrc[1]),.A2(addrc[2]),.A3(addrc[3])); end elsebegin ROM16X1 #(.INIT(16'b1000_0000_0000_0000)) rom_3 (.O(Oc[3]),.A0(addrc[0]),.A1(addrc[1]),.A2(addrc[2]),.A3(addrc[3])); end end endgenerate generate for(i3=0;i3<4;i3=i3+1) begin :rom_unitd if(i3==0) begin ROM16X1 #(.INIT(16'b1010_0000_1010_0000)) rom_0 (.O(Od[0]),.A0(addrd[0]),.A1(addrd[1]),.A2(addrd[2]),.A3(addrd[3])); end else if(i3==1)begin ROM16X1 #(.INIT(16'b0110_1010_1100_0000)) rom_1 (.O(Od[1]),.A0(addrd[0]),.A1(addrd[1]),.A2(addrd[2]),.A3(addrd[3])); end else if(i3==2)begin ROM16X1 #(.INIT(16'b0100_1100_0000_0000)) rom_2 (.O(Od[2]),.A0(addrd[0]),.A1(addrd[1]),.A2(addrd[2]),.A3(addrd[3])); end elsebegin ROM16X1 #(.INIT(16'b1000_0000_0000_0000)) rom_3 (.O(Od[3]),.A0(addrd[0]),.A1(addrd[1]),.A2(addrd[2]),.A3(addrd[3])); end end endgenerateendmoduletestbench:module d_rom_top_tb; // Inputs reg clk; reg rst_n; reg [3:0] a; reg [3:0] b; // Outputs wire [7:0] c; // Instantiate the Unit Under Test (UUT) d_rom_top uut ( .clk(clk), .rst_n(rst_n), .a(a), .b(b), .c(c) ); always #5 clk=~clk; initial begin // Initialize Inputs clk = 0; rst_n = 0; a = 0; b = 0; // Wait 100 ns for global reset to finish #100; rst_n=1; #10; #3; a=2;b=6; #10; a=3;b=7; #10; a=15;b=9; #10; a=12;b=11; #10; a=6;b=7; end endmodule仿真图形:附件:http://down.51cto.com/data/2362729声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。