2013-06-14 15:20:28
简单组合逻辑电路的verilog实现,包括三态门、3-8译码器、8-3优先编码器、8bit奇偶校验器,测试功能正确、可综合。
小结:
- assign与always都可实现组合逻辑,有什么区别?
组合逻辑用数据流描述(一般将用assign描述的称为数据流描述)或者RTL描述(一般将用always描述的称为数据流描述)都可以实现;
当组合逻辑较为简单时(如用一句话就可以实现的求反、求和assign sum = a + b; assign dout = ~din;等),用assign比较方便;
若组合逻辑比较复杂,则用always比较合适。
- 组合逻辑用always实现时,敏感列表一定要写全;
- 写代码时,脑子里要有硬件的的概念,这是与C语言等软件语言的重要区别之一;
- 为防止锁存器,对if语句要加上else,对case语句,要加上default
如下面的就会产生锁存器:
1 always@(din) 2 begin 3 if(din[7] == 1'b1) dout = 3'b111; 4 else if(din[6] == 1'b1) dout = 3'b110; 5 else if(din[5] == 1'b1) dout = 3'b101; 6 else if(din[4] == 1'b1) dout = 3'b100; 7 else if(din[3] == 1'b1) dout = 3'b011; 8 else if(din[2] == 1'b1) dout = 3'b010; 9 else if(din[1] == 1'b1) dout = 3'b001;10 else if(din[0] == 1'b1) dout = 3'b000;11 else dout = dout; 12 end
改为如下,则不会有锁存器:
1 always@(din) 2 begin 3 if(din[7] == 1'b1) dout = 3'b111; 4 else if(din[6] == 1'b1) dout = 3'b110; 5 else if(din[5] == 1'b1) dout = 3'b101; 6 else if(din[4] == 1'b1) dout = 3'b100; 7 else if(din[3] == 1'b1) dout = 3'b011; 8 else if(din[2] == 1'b1) dout = 3'b010; 9 else if(din[1] == 1'b1) dout = 3'b001;10 else dout = 3'b000; //防止产生锁存器,将上面两行换为这一行11 end
简单门电路的门级、数据流、RTL描述
实现组合逻辑:f = ~(ab)|(bcd)代码:
1 odule simple_gate( 2 a, 3 b, 4 c, 5 d, 6 f 7 ); 8 9 input a;10 input b; 11 input c;12 input d;13 14 output f;15 /*16 //门级描述17 nand (f1,a,b);18 and (f2,b,c,d);19 20 or(f,f1,f2);21 22 //数据流描述23 assign f = ~(a & b) | (b & c & d);24 */25 //RTL描述26 reg f;27 always@(a,b,c,d)28 begin29 f = ~(a & b) | (b & c & d);30 end31 32 endmodule
门级描述综合后得到的RTL级电路:
数据流描述综合后得到的RTL级电路:
RTL描述综合后得到的RTL级电路与数据流描述综合后得到的RTL级电路完全相同。
三态门的门级、数据流、RTL描述:
代码:
1 module tri_gate( 2 din, 3 en, 4 dout 5 ); 6 7 8 input din; 9 input en;10 11 output dout;12 13 //门级描述14 //bufif1 (dout,din,en);15 16 //数据流描述17 //assign dout = en ? din : 1'bz;18 19 //RTL描述20 reg dout;21 22 always@(din,en)23 if(en)24 dout = din;25 else26 dout = 1'bz;27 28 endmodule
门级描述综合,RTL图:
数据流描述综合,RTL图与门级的完全相同。
RTL描述综合,RTL图同样与门级的完全相同。
3-8译码器的verilog实现
RTL描述,用case语句或if...if 语句实现,如下:
1 module decode_3to8( 2 din, 3 dout 4 ); 5 6 input [2:0] din; 7 output [7:0] dout; 8 9 reg [7:0] dout;10 11 //case语句实现12 always@(din)13 case(din)14 3'b000 : dout = 8'b0000_0001;15 3'b001 : dout = 8'b0000_0010;16 3'b010 : dout = 8'b0000_0100;17 3'b011 : dout = 8'b0000_1000;18 3'b100 : dout = 8'b0001_0000;19 3'b101 : dout = 8'b0010_0000;20 3'b110 : dout = 8'b0100_0000;21 3'b111 : dout = 8'b1000_0000;22 endcase23 /* 24 //if...if语句实现25 always@(din)26 begin 27 if (din == 3'b000) dout = 8'b0000_0001;28 if (din == 3'b001) dout = 8'b0000_0010;29 if (din == 3'b010) dout = 8'b0000_0100;30 if (din == 3'b011) dout = 8'b0000_1000;31 if (din == 3'b100) dout = 8'b0001_0000;32 if (din == 3'b101) dout = 8'b0010_0000;33 if (din == 3'b110) dout = 8'b0100_0000;34 if (din == 3'b111) dout = 8'b1000_0000;35 end36 */ 37 endmodule
用case语句或if语句时:
综合选项中Decoder Extraction设为YES,自动综合为用器件本身的硬件译码器实现,如下:
若综合选项Decoder Extraction设为NO,用case语句或if语句,综合RTL图为:
是用8bitROM实现的
8-3优先编码器的verilog实现
RTL描述,用if...else的特点实现优先编码,如下:
1 module encoder_8to3( 2 din, 3 dout 4 ); 5 6 input [7:0] din; 7 output [2:0] dout; 8 9 reg [2:0] dout;10 11 //if语句中仅仅判断1个bit即可12 always@(din)13 begin14 if(din[7] == 1'b1) dout = 3'b111;15 else if(din[6] == 1'b1) dout = 3'b110;16 else if(din[5] == 1'b1) dout = 3'b101;17 else if(din[4] == 1'b1) dout = 3'b100;18 else if(din[3] == 1'b1) dout = 3'b011;19 else if(din[2] == 1'b1) dout = 3'b010;20 else if(din[1] == 1'b1) dout = 3'b001;21 //else if(din[0] == 1'b1) dout = 3'b000;22 //else dout = dout; 23 else dout = 3'b000; //防止产生锁存器,将上面两行换为这一行24 end25 26 /*27 //if语句中仅仅判断1个bit即可,这种是错误的28 always@(din)29 begin30 if(din == 8'b1000_0000) dout = 3'b111;31 else if(din == 8'b0100_0000) dout = 3'b110;32 else if(din == 8'b0010_0000) dout = 3'b101;33 else if(din == 8'b0001_0000) dout = 3'b100;34 else if(din == 8'b0000_1000) dout = 3'b011;35 else if(din == 8'b0000_0100) dout = 3'b010;36 else if(din == 8'b0000_0010) dout = 3'b001;37 else if(din == 8'b0000_0001) dout = 3'b000;38 end39 */40 endmodule
综合选项中Priority Encoder Extraction为YES,但是综合结果并没有使用优先编码器,原因未知。
改变代码,去掉锁存器:
//else if(din[0] == 1'b1) dout = 3'b000;
//else dout = dout; else dout = 3'b000; //防止产生锁存器,将上面两行换为这一行综合结果,可以看到,没有锁存器了:
奇偶校验器的verilog实现
数据流描述:
1 module odd_even_check( 2 din, 3 dout_even, 4 dout_odd 5 ); 6 7 input [7:0] din; 8 output dout_even; 9 output dout_odd;10 11 assign dout_odd = ^din; //奇校验位12 assign dout_even = ~dout_odd; //偶校验位13 14 endmodule
综合RTL图:
4选1数据选择器
可以用case或者if语句实现:
1 module mux( 2 din1, 3 din2, 4 din3, 5 din4, 6 sel, 7 dout 8 ); 9 10 input din1;11 input din2;12 input din3;13 input din4;14 input [1:0] sel;15 16 output dout;17 18 reg dout;19 /*20 //用case语句实现21 always@(din1,din2,din3,din4,sel)22 begin23 case(sel)24 2'b00 : dout = din1;25 2'b01 : dout = din2;26 2'b10 : dout = din3;27 default : dout = din4; 28 endcase29 end 30 */31 32 //用if语句实现33 always@(din1,din2,din3,din4,sel)34 begin35 if(sel == 2'b00) dout = din1;36 else if(sel == 2'b01) dout = din2;37 else if(sel == 2'b10) dout = din3;38 else dout = din4;39 end40 41 endmodule
case语句与if语句描述综合结果完全相同,如下: