1. 조합회로

1-1 4x1 MUX

 module mux4x1 (sel,d0,d1,d2,d3,m1,m2);
 input [1:0]      sel;
 input            d0, d1, d2, d3;
 output           m1, m2;
 wire             m1;
 reg              m2;
 
 assign m1 = (sel[1]) ? ( (sel[0]) ? d3 : d2) ) : ( (sel[0]) ? d1 : d0 );
 
 always @ (sel,d0,d1,d2,d3)
 if          (sel==2'b11) m2 = d3;
 else if     (sel==2'b11) m2 = d2;
 else if     (sel==2'b11) m2 = d1;
 else if     (sel==2'b11) m2 = d0;
 endmodule

4x1 MUX를 위와 같이 작성했다. assign문으로도 만들 수 있고 always ~ if 문으로도 만들 수 있지만, 중요한 것은 if 문 혹은 case문 사용시 꼭 default / else 를 써줘야 한다는 점이다.

 

위와 같이 else를 써주지 않고 mux_output m2를 만든 결과 스키매틱을 보면 MUX가 아닌 래치가 발생한 것을 확인할 수 있다. 

 

1-2 비교기 (A greater than B)

 module gt (a, b, agtb);
 parameter BW = 4;
 input [BW-1:0] a, b;
 output reg agtb;
 //reg agtb;
 
 always @ (a, b)
 begin
  agtb = 1'b0;
  if       (a[3]>b[3]) agtb=1'b1; 
  else if  ((a[3]==b[3]) && (a[2]>b[2])) agtb=1'b1;
  else if  ((a[3:2]==b[3:2]) && (a[1]>b[1])) agtb=1'b1;
  else if  ((a[3:1]==b[3:1]) && (a[0]>b[0])) agtb=1'b1;
  else agtb=1'b0;
 end
 
 endmodule

a와 b의 값을 비교하여 a의 값이 더 클 경우 1을 출력하는 비교기이다. 유의해야 할 점은 자리수를 비교할 때, 백의 자리를 비교한다면, 조건문에 -  천의자리는 같다는 전제 하에 백의 자리는 클 경우로 작성해주어야 한다.   

 

<테스트벤치>

module tb_abgt;

reg [3:0] a, b;
wire agtb;

gt U1 (a,b,agtb);

initial begin
a = 4'b0000; b = 4'b0000;
#10 a = 4'b1000; b = 4'b0000;
#10 a = 4'b1000; b = 4'b1000;
#10 a = 4'b1100; b = 4'b1000;
#10 a = 4'b1100; b = 4'b1100;
#10 a = 4'b1110; b = 4'b1100;
#10 a = 4'b1110; b = 4'b1110;
#10 a = 4'b1111; b = 4'b1110;
#10 a = 4'b1111; b = 4'b1111;
#10 a = 4'b0111; b = 4'b1111;
#10 a = 4'b1110; b = 4'b1111;
#10;
end
endmodule

테스트벤치로 시뮬레이션 돌린 결과이다. 파형을 보면 A가 B보다 클 때만 출력이 1이 되는 것을 확인할 수 있다.

 

 

2. 순차회로

2-1. D-f/f (synch, preset)

module d_ff_sync_pr (clk,pr,d,q);
input clk, pr, d;
output q;
reg q;

always @ (posedge clk)
    if (pr) q <= 1'b1;
	else      q <= d;
	
endmodule

 

 

 

2-2 D-f/f (asynch)

module d_ff_async (clk,rst,d,q,qb);
input clk, rst, d;
output q,qb;
reg q;
assign qb = ~q;

always @ (negedge rst or posedge clk)
    if (~rst) q <= 1'b0;
	else      q <= d;
	
endmodule

module tb_d_ff_async;

reg clk, rst, d;
wire q, qb;

d_ff_async  u1 (clk,rst,d,q,qb);

always #100 clk = ~clk;

initial
begin
        d = 1'b0; clk = 1'b0; rst =0;
#325    d = 1'b1; 
#100    rst = 1'b1;
#425    d = 1'b0; 
#270    d = 1'b1;
#100    rst = 1'b0;
#200    d = 1'b0;
#270    d = 1'b1;
#200;
$stop;
end

endmodule

 

3-2 0~15 counter 

module mod16_cnt (arst, clk, q, tco);
input arst, clk;
output [3:0] q;
output tco;
reg [3:0] q;

always @ (posedge arst or posedge clk)
    if (arst)  q <= 4'b0000;
	else      q <= q + 1'b1;
	
	//순차회로 조합회로 분리하는 것이 더 좋음
	
assign tco = (q == 4'b1111) ? 1'b0 : 1'b1;
// assign tco = ~(&q) //q가 모두 1이면 0나감 위와 같다

endmodule

module tb_mod16_cnt;

reg arst, clk;
wire [3:0] q; 
wire tco;

mod16_cnt u1 (arst, clk, q, tco);

always #100 clk = ~clk;

initial
begin
        arst = 1'b1; clk = 1'b0;
#400    arst = 1'b0;
#3600;
$stop;
end

endmodule

+ Recent posts