硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3566|回复: 6
收起左侧

组合逻辑电路(4)----- 算数运算(加法器 ALU 流水线)

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107397
QQ
发表于 2013-1-25 16:23:53 | 显示全部楼层 |阅读模式
1.jpg
2.jpg
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107397
QQ
 楼主| 发表于 2013-1-25 16:39:09 | 显示全部楼层
【例3.1】4位全加器
module adder4(cout,sum,ina,inb,cin);
output[3:0] sum;
output cout;
input[3:0] ina,inb;
input cin;
assign {cout,sum}=ina+inb+cin;
endmodule
【例5.11】模为60的BCD码加法计数器
module count60(qout,cout,data,load,cin,reset,clk);
output[7:0] qout;
output cout;
input[7:0] data;
input load,cin,clk,reset;
reg[7:0] qout;
always @(posedge clk)            //clk上升沿时刻计数
begin
if (reset)      qout<=0;      //同步复位
else  if(load)    qout<=data;     //同步置数
else  if(cin)
begin
if(qout[3:0]==9)        //低位是否为9,是则
begin
qout[3:0]<=0;          //回0,并判断高位是否为5
if (qout[7:4]==5)  qout[7:4]<=0;
else
qout[7:4]<=qout[7:4]+1;     //高位不为5,则加1
end
else              //低位不为9,则加1
qout[3:0]<=qout[3:0]+1;
end
  end
assign cout=((qout==8'h59)&cin)?1:0;    //产生进位输出信号
endmodule
【例6.1】加法计数器中的进程
module count(data,clk,reset,load,cout,qout);
output cout;
output[3:0] qout;
reg[3:0] qout;
input[3:0] data;
input clk,reset,load;
always @(posedge clk)           //进程1,always过程块
    begin
if (!reset)    qout= 4'h00;         //同步清0,低电平有效
else if (load)   qout= data;     //同步预置
else        qout=qout + 1;        //加法计数
    end
assign cout=(qout==4'hf)?1:0;      //进程2,用持续赋值产生进位信号
endmodule
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107397
QQ
 楼主| 发表于 2013-1-25 21:43:18 | 显示全部楼层
1位半加器
【例7.9】调用门元件实现的1位半加器
module half_add1(a,b,sum,cout);
input a,b;
output sum,cout;
and  (cout,a,b);
xor  (sum,a,b);
endmodule
【例7.10】数据流方式描述的1位半加器
module half_add2(a,b,sum,cout);
input a,b;
output sum,cout;
assign sum=a^b;
assign cout=a&b;
endmodule
【例7.11】采用行为描述的1位半加器
module half_add3(a,b,sum,cout);
input a,b;
output sum,cout;
reg sum,cout;
always @(a or b)
begin
case ({a,b})                   //真值表描述
2'b00: begin  sum=0; cout=0;  end
2'b01: begin  sum=1; cout=0;  end
2'b10: begin  sum=1; cout=0;  end
2'b11: begin  sum=0; cout=1;  end
endcase
end
endmodule
【例7.12】采用行为描述的1位半加器
module half_add4(a,b,sum,cout);
input a,b;
output sum,cout;
reg sum,cout;
always @(a or b)
begin
sum= a^b;
cout=a&b;
end
endmodule
【例7.17】混合描述的1位全加器
module full_add5(a,b,cin,sum,cout);
input a,b,cin;
output sum,cout;
reg cout,m1,m2,m3;            //在always块中被赋值的变量应定义为reg型
wire s1;
xor x1(s1,a,b);                     //调用门元件
always @(a or b or cin)       //always块语句
    begin
m1 = a & b;
m2 = b & cin;
m3 = a & cin;
cout = (m1| m2) | m3;
end
assign sum = s1 ^ cin;      //assign持续赋值语句
endmodule
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107397
QQ
 楼主| 发表于 2013-1-26 09:24:15 | 显示全部楼层
【例9.28】用函数实现简单的处理器
module mpc(instr,out);
input[17:0] instr;                //instr为输入的指令
output[8:0] out;           //输出结果
reg[8:0] out;
reg func;
reg[7:0] op1,op2;          //从指令中提取的两个操作数

function[16:0] code_add;       //函数的定义
input[17:0] instr;
reg add_func;
reg[7:0] code,opr1,opr2;
begin
code=instr[17:16];        //输入指令instr的高2位是操作码
opr1=instr[7:0];         //输入指令instr的低8位是操作数opr1
case(code)
    2'b00:  
begin
add_func=1;
opr2=instr[15:8];      //从instr中取第二个操作数
end
    2'b01:
begin
    add_func=0;
   opr2=instr[15:8];      //从instr中取第二个操作数
end
    2'b10:
begin
    add_func=1;
    opr2=8'd1;          //第二个操作数取为1,实现+1操作
end
    default:
begin
   add_func=0;
   opr2=8'd1;          //实现-1操作
end
    endcase
code_add={add_func,opr2,opr1};
end
endfunction

always @(instr)
begin
     {func,op2,op1}=code_add(instr);   //调用函数
    if(func==1)  out=op1+op2;             //实现两数相加、操作数1加1操作
     else         out=op1-op2;                 //实现两数相减、操作数1减1操作
    end
endmodule
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107397
QQ
 楼主| 发表于 2013-1-26 10:00:43 | 显示全部楼层
【例10.1】非流水线方式8位全加器
module adder8(cout,sum,ina,inb,cin,clk);
output[7:0] sum;
output cout;
input[7:0] ina,inb;
input cin,clk;
reg[7:0] tempa,tempb,sum;
reg cout;
reg tempc;
always @(posedge clk)
begin
tempa=ina;  tempb=inb;  tempc=cin;     //输入数据锁存
end
always @(posedge clk)
begin
{cout,sum}=tempa+tempb+tempc;
end
endmodule
【例10.2】4级流水方式的8位全加器
module pipeline(cout,sum,ina,inb,cin,clk);
output[7:0] sum;
output cout;
input[7:0] ina,inb;
input cin,clk;
reg[7:0] tempa,tempb,sum;
reg tempci,firstco,secondco,thirdco,cout;
reg[1:0] firsts,thirda,thirdb;
reg[3:0] seconda,secondb,seconds;
reg[5:0] firsta,firstb,thirds;

always @(posedge clk)
begin
tempa=ina;  tempb=inb;  tempci=cin;    //输入数据缓存
end
always @(posedge clk)
begin
{firstco,firsts}=tempa[1:0]+tempb[1:0]+tempci;
//第一级加(低2位)
firsta=tempa[7:2];        //未参加计算的数据缓存
firstb=tempb[7:2];
end
always @(posedge clk)
begin
{secondco,seconds}={firsta[1:0]+firstb[1:0]+firstco,firsts};  
//第二级加(第2、3位相加)
seconda=firsta[5:2];        //数据缓存
secondb=firstb[5:2];
end
always @(posedge clk)
begin
{thirdco,thirds}={seconda[1:0]+secondb[1:0]+secondco,seconds};
//第三级加(第4、5位相加)
thirda=seconda[3:2];    //数据缓存
thirdb=secondb[3:2];
end
always @(posedge clk)
begin
{cout,sum}={thirda[1:0]+thirdb[1:0]+thirdco,thirds};
//第四级加(高两位相加)
end
endmodule
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107397
QQ
 楼主| 发表于 2013-1-26 10:39:49 | 显示全部楼层
【例10.3】两个加法器和一个选择器的实现方式
module resource1(sum,a,b,c,d,sel);
parameter size=4;
output[size:0] sum;
input sel;
input[size-1:0] a,b,c,d;
reg[size:0] sum;
always @(a or b or c or d or sel)
begin
if(sel)  sum=a+b;
else    sum=c+d;
end
endmodule
【例10.4】两个选择器和一个加法器的实现方式
module resource2(sum,a,b,c,d,sel);
parameter size=4;
output[size-1:0] sum;
input sel;
input[size-1:0] a,b,c,d;
reg[size-1:0] atemp,btemp;
reg[size:0] sum;
always @(a or b or c or d or sel)
begin
if(sel)  begin  atemp=a;  btemp=b;  end
else    begin  atemp=c;  btemp=d;  end
sum=atemp+btemp;
end
endmo
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107397
QQ
 楼主| 发表于 2013-1-26 11:45:00 | 显示全部楼层
【例5.16】用for 语句实现2个8位数相乘
module mult_for(outcome,a,b);
parameter size=8;
input[size:1] a,b;                   //两个操作数
output[2*size:1] outcome;      //结果
reg[2*size:1] outcome;
integer i;
always @(a or b)
    begin
outcome=0;
for(i=1; i<=size; i=i+1)        //for语句
if(b)  outcome=outcome +(a << (i-1));
    end
endmodule
【例5.17】用repeat实现8位二进制数的乘法
module mult_repeat(outcome,a,b);
parameter size=8;
input[size:1] a,b;
output[2*size:1] outcome;
reg[2*size:1] temp_a,outcome;
reg[size:1] temp_b;
always @(a or b)
  begin
outcome=0;
temp_a=a;
temp_b=b;
repeat(size)         //repeat语句,size为循环次数
begin
if(temp_b[1])      //如果temp_b的最低位为1,就执行下面的加法
outcome=outcome+temp_a;
temp_a=temp_a<<1;      //操作数a左移一位
【例6.6】阶乘运算函数
module funct(clk,n,result,reset);
output[31:0] result;
input[3:0] n;
input reset,clk;
reg[31:0] result;
always @(posedge clk)          //在clk的上升沿时执行运算
begin
if(!reset)  result<=0;        //复位
else  begin
result <= 2 * factorial(n); //调用factorial函数
end
end

function[31:0] factorial;        //阶乘运算函数定义(注意无端口列表)
input[3:0] opa;                 //函数只能定义输入端,输出端口为函数名本身
reg[3:0] i;
begin
factorial = opa ? 1 : 0;
for(i= 2; i <= opa; i = i+1)   //该句若要综合通过,opa应赋具体的数值
factorial = i* factorial;       //阶乘运算
end

function[31:0] factorial;        //阶乘运算函数定义(注意无端口列表)
input[3:0] opa;                 //函数只能定义输入端,输出端口为函数名本身
reg[3:0] i;
begin
factorial = opa ? 1 : 0;
for(i= 2; i <= opa; i = i+1)   //该句若要综合通过,opa应赋具体的数值
factorial = i* factorial;       //阶乘运算
end
endfunction
endmodule
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-30 01:13 , Processed in 0.175614 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表