简单组合逻辑电路的verilog实现(包括三态门、3-8译码器、8-3优先编码器、8bit奇偶校验器)
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 begin 29 f = ~(a & b) | (b & c & d); 30 end 31 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 else 26 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 endcase 23 /* 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 end 36 */ 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 begin 14 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 end 25 26 /* 27 //if语句中仅仅判断1个bit即可,这种是错误的 28 always@(din) 29 begin 30 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 end 39 */ 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 begin 23 case(sel) 24 2'b00 : dout = din1; 25 2'b01 : dout = din2; 26 2'b10 : dout = din3; 27 default : dout = din4; 28 endcase 29 end 30 */ 31 32 //用if语句实现 33 always@(din1,din2,din3,din4,sel) 34 begin 35 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 end 40 41 endmodule
case语句与if语句描述综合结果完全相同,如下: