module cfq(result,a,b); parameter width = 8; input [width:1] a,b; output [2*width-1:0] result; // wire [width:1] a,b; 一开始定义为reg类型报错,输入端口为非线型变量,不可定义为reg类型 reg [2*width-1:0] result; integer index; always @(a or b) begin result = 0; for(index = 0;index <= width;index = index+1) begin if(b[index]) begin result = result + (a << (index-1)); end end end endmodule
首先欲利用操作数地址访问存储器,应当想到将操作数拆分,因为如果不拆分的话,就直接合并只能得到一个地址,只能查找到一个结果,下面以1101 x 1011为例,首先想到的拆分应该是从中间位置拆分,1101拆分为11和01,1011拆分为10和11,再通过拆分得到的部分想办法与结果联系起来,即:1101 x 1011 = (1100 + 0001)x(1000 + 0011),再因式分解一下,得到1100 x 1000 + 1100 x 0011 + 0001 x 1000 + 0001 x 0011,另firsta=11,seconda=01,firstb=10,secondb=11,上述结果又可表示为((firsta x firstb)<<4) + ((firsta x secondb)<<2) + ((seconda x firstb)<<2) + (seconda x secondb),每部分移位的位数也就是应该放大的倍数,自行理解就好。
module lookup(out,a,b,clk); //新建设计文件用于引用 output [3:0] out; input [1:0] a,b; input clk; reg [3:0] out; reg [3:0] address; always @(*) begin address = {a,b}; //将拆分的a,b组成的地址作为索引,注意:与乘数因子含义不同 case(address) 4'h0: out =4'b0000; 4'h1: out =4'b0000; 4'h2: out =4'b0000; 4'h3: out =4'b0000; 4'h4: out =4'b0000; 4'h5: out =4'b0001; 4'h6: out =4'b0010; 4'h7: out =4'b0011; 4'h8: out =4'b0000; 4'h9: out =4'b0010; 4'ha: out =4'b0100; 4'hb: out =4'b0110; 4'hc: out =4'b0000; 4'hd: out =4'b0011; 4'he: out =4'b0110; 4'hf: out =4'b1001; //拆分之后前半部分和后半部分各四种可能,分别为00,01,10,11,相乘即有16种可能,分别分析做出case事件 default: out = 'bx; endcase end endmodule