溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

基于ROM的乘法器

發(fā)布時(shí)間:2020-06-18 11:16:10 來源:網(wǎng)絡(luò) 閱讀:1546 作者:lihaichuan 欄目:開發(fā)技術(shù)

1、原理簡(jiǎn)介    

       乘法器的另一種實(shí)現(xiàn)思想是采用ROM的方式,即將被乘數(shù)和乘數(shù)連接起來拼成地址,把兩者所有可能的乘積按照地址放在ROM的地址空間中,兩個(gè)數(shù)相乘時(shí),根據(jù)兩者構(gòu)成的地址從ROM中讀取乘積結(jié)果。ROM可采用分布式邏輯資源實(shí)現(xiàn)(用于存儲(chǔ)數(shù)據(jù)量小的情況比較合適),也可采用嵌入式BRAM實(shí)現(xiàn)(用于存儲(chǔ)量數(shù)據(jù)大的情況比較合適)。
       兩個(gè)N-bit的二進(jìn)制數(shù)相乘,其結(jié)果為2N-bit。這意味著ROM的深度為2的2N次方,寬度為2N。以兩個(gè)4-bit數(shù)相乘為例,其存儲(chǔ)空間的大小為256x8-bit(256為深度,8為寬度),顯然,隨著位寬的增加存儲(chǔ)空間將以指數(shù)速度膨脹。
       改進(jìn)方法:將被乘數(shù)和乘數(shù)進(jìn)行位分解,即將大位寬的數(shù)分解為多個(gè)小位寬的數(shù)來分別相乘。例如兩個(gè)4-bit數(shù)相乘,可將4-bit數(shù)分解成兩個(gè)2-bit數(shù),為了保證最終乘積結(jié)果的正確性,需要對(duì)中間結(jié)果進(jìn)行移位。為方便起見,以兩個(gè)無符號(hào)二進(jìn)制數(shù)1101(對(duì)應(yīng)十進(jìn)制為11)和0110(對(duì)應(yīng)十進(jìn)制數(shù)為0110)相乘為例。其相乘位分解處理流程如下圖所示。
 

基于ROM的乘法器

采用的ROM深度為16,寬度為4。存儲(chǔ)的內(nèi)容為兩個(gè)無符號(hào)數(shù)相乘的結(jié)果。地址及其對(duì)應(yīng)的存儲(chǔ)內(nèi)容如下:

地址
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
內(nèi)容(十進(jìn)制)
0
0
0
0
0
1
2
3
0
2
4
6
0
3
6
9
內(nèi)容(十進(jìn)制)
0000
0000
0000
0000
0000
0001
0010
0011
0000
0010
0100
0110
0000
0011
0110
1001

2、verilog代碼實(shí)現(xiàn)
       2.1節(jié)介紹ROM使用Distributed Memory Generator生成的IP核。2.2節(jié)介紹使用Xilinx原語(yǔ)生成的ROM(其實(shí)使用的也是分布式資源)。Block Memeory Generator生成的IP核使用的是BlockRAM,當(dāng)存儲(chǔ)大量數(shù)據(jù)時(shí),使用比較方便,和Distributed Memory Generator類似,不再詳細(xì)介紹。
2.1 ROM采用分布式資源生成的IP核
 

基于ROM的乘法器

設(shè)置ROM的位寬,深度等。
 

基于ROM的乘法器

ROM進(jìn)行初始化,采用coe文件。
 

基于ROM的乘法器

coe文件的內(nèi)容為:
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,表明下面的數(shù)據(jù)為10進(jìn)制,還可以取值2,8,16。
MEMORY_INITIALIZATION_VECTOR=,后面的內(nèi)容依次為地址(0-15)所存儲(chǔ)的內(nèi)容,中間用逗號(hào)分隔,最后用分號(hào)。
最后生成ROM核。
verilog代碼實(shí)現(xiàn)
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=135
 

基于ROM的乘法器

2.2 ROM采用Xilinx原語(yǔ)生成
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
                     else begin           
                            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
                     else begin           
                            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
                     else begin           
                            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
                     else begin           
                            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
       endgenerate
 
endmodule
 
testbench:
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
仿真圖形:

基于ROM的乘法器

 

附件:http://down.51cto.com/data/2362729
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI