Kraklog

[Study] 디지털 논리 회로 설계 본문

Study/VerilogHDL

[Study] 디지털 논리 회로 설계

Krakens 2023. 9. 2. 10:34
728x90

프로그램 : Quaturs Prime lite edition 18.1, VScode , Model SIM

사용문법 : Verilog 2001

보드 : DE1-SOC

 

들어가기에 앞서,
Verilog HDL은 VHDL과 함께 가장 일반적으로 쓰이는 HDL중 하나이다.
Verilog는 95년도에 IEEE 표준으로 채택되었고, verilog-95 standard로 이용되었으나, 2001년 문법체계가 업데이트 되었다.

HDL을 이용해 모델링때 사용되는 Abstraction level (추상화 레벨)은 다음과 같다.

 

  1. 알고리즘 레벨 : Behavior level (동작레벨)이라고도 불리며, 순차적인 방법으로 표현된다. 즉, 알고리즘이 순서에 맞게 실행되는 명령어로 구성되어 있다.
  2. 레지스터 전달 레벨 : Data flow 라고도 불리며 회로를 데이터 이동으로 표현 한 것.
    RTL 설계에서는 외부 클럭이 사용되고, 동기화된 시간에 동작이 발생하도록 스케줄 된다.
  3. 게이트 레벨 : 시스템 동작을 논리 게이틔 연결로 표현 한다. 모든 신호들의 입력 값은 0 1 x z 의 논리 값을 갖으며 논리 소자들을 연결하는 것과 유사함.
  4. 스위치 레벨 : 가장 저 레벨의 추상화이며, MOS 트랜지스터를 이용해 게이트 내부의 동작을 나타낸다. 

 

1. 기본 논리 게이트

◎ 코드 작성

다이어그

// Verilog code for logic gates

module AndOr(
  input   a       ,
  input   b       ,
  output  OUT_OR , 
  output  OUT_AND  , 
  output  OUT_NOT  
);

  assign OUT_AND = a&b;
  assign OUT_OR = a|b;
  assign OUT_NOT = ~a;

endmodule

a,b의 입력을 받는 AND OR NOT 게이트의 블록 다이어그램을 작성하고, 이를 Verilog 를 이용해서 표현했다.
입력에는 1과 0 의 2진수만을 받을것이기 때문에 [1:0]을 선언해주었어도 되었을듯하다.
assign 구문을 통해 출력부를 할당해주었고, & (and 연산) | (or 연산) ~ (Not 연산) 을 통해 값을 넣도록 했다.

&& 와 &의 차이점은 논리연산인지 아닌지에대한 차이점을 갖고 있다.

◎ Simulation

model sim을 사용하위해 test bench (테스트 벤치)를 작성해주었다. 입력핀은 reg로 연결해주고 출력핀은 wire를 통해 연결해주었다. 
이를 다이어그램으로 표현하면 다음과 같다.

module tb_AndOr();

reg  a       ; 
reg  b       ; 
wire   OUT_OR  ;
wire   OUT_AND ;  
wire   OUT_NOT ; 

AndOr U_AndOr(
.a      (a      ),
.b      (b      ),
.OUT_OR (OUT_OR ),
.OUT_AND(OUT_AND),
.OUT_NOT(OUT_NOT)
);

initial begin
  a=0;
  b=0;
  #10
  a=2'b1;
  b=2'b0;
  #10 a=2'b0;
  b=2'b1;
  #10 a=2'b1;
  b=2'b1;
end


endmodule

model sim의 tcl 기능을 사용하기 위해 do 파일을 작성했다.

work 라이브러리를 선언하고, AndOr과 tb_AndOr의 코드를 비교하는데 시뮬레이션은 tb_AndOr를 이용하기로 선언하고
tb_AndOr 중 a b OUT_AND OUT_OR OUT_NOT을 wave에 추가하라는 명령어이다. 

vlib work
vlog AndOr.v tb_AndOr.v
vsim -t ns work.tb_AndOr
view wave
add wave -radix bin /a
add wave -radix bin /b
add wave -radix bin /OUT_AND
add wave -radix bin /OUT_OR
add wave -radix bin /OUT_NOT
run 50 ns

그 값을 시뮬레이션을 통해서 봤을때 예상한 값이 나옴을 알 수 있다.
예시로 15ns 값을 보면 a와 b는 각 1,0 이  들어오고 있다.
and 연산을 하면 0, OR 연산을 하면 1, ~a 는 0 임을 계산해볼 수 있는데  시뮬레이션 또한 같은 값을 보인다.

2. 전가산기

앞선 포스트에서 Full Adder는 많이 다뤘지만, 다시 해보기로 했다.
Full Adder 는 조합 논리회로를 이해하기 좋은 예제로 잘 알려져 있다. 
이번 과정에서는 카르노맵, 진리표, 논리식을 이용해서 작성하는것이 목표이다.

코드 작성

다이어그램
Full Adder 진리표 및 카르노맵 간소화

module Full_Adder (
  input   X ,
  input   Y ,
  input   Z ,
  output  reg  C , 
  output  reg  S  
);

  assign k_C = (X&Y)|(X&Z)|(Y&Z);  //Used Karnaugh Map
  assign k_S = (X&~Y&~Z)|(~X&~Y&Z)|(X&Y&Z)|(~X&Y&~Z);

//used Logic
  assign o_XY1 = (X^Y);
  assign o_Sum = (o_XY1 ^ Z);
  assign O_carry = ((o_XY1)&Z)|(X&Y);


  wire [2:0]  w_full;
  assign w_full = {X , Y , Z}; //Used Truth table
  
  always @(w_full) begin
  case (w_full)
    3'b001  : begin
    C <= 1'b0;
    S <= 1'b1;
   end  
    3'b010  : begin
    C <= 1'b0;
    S <= 1'b1;
   end  
    3'b011  : begin
    C <= 1'b1;
    S <= 1'b0;
   end  
    3'b100  : begin
    C <= 1'b0;
    S <= 1'b1;
   end  
    3'b101  : begin
    C <= 1'b1;
    S <= 1'b0;
   end  
    3'b110  : begin
    C <= 1'b1;
    S <= 1'b0;
   end  
    3'b111  : begin
    C <= 1'b1;
    S <= 1'b1;
   end  
  
    default: begin
      C <= 1'b0;
      S <= 1'b0;
    end 
  endcase
    
  end
  
endmodule

설계 순서는 다음과 같다.

1. 카르노맵을 이용한 설계
2. 논리식을 이용한 설계
3. 진리표를 이용한 설계

◎ Simulation

module tb_Full_Adder ();
  reg X;
  reg Y;
  reg Z;
  wire C;
  wire S;


Full_Adder u_Full_Adder(
  .X(X) ,
  .Y(Y) ,
  .Z(Z) ,
  .C(C) , 
  .S(S)  
);

initial begin
  X=0; Y=0; Z=0;
  #10 
  X=0; Y=0; Z=1;
  #20 
  X=0; Y=1; Z=0;
  #30 
  X=0; Y=1; Z=1;
  #40 
  X=1; Y=0; Z=0;
  #50 
  X=1; Y=0; Z=1;
  #60 
  X=1; Y=1; Z=0;
  #70 
  X=1; Y=1; Z=1;
  
end
endmodule

 

vlib work
vlog Full_Adder.v tb_Full_Adder.v
vsim -t ns work.tb_Full_Adder
view wave
add wave -radix bin /X
add wave -radix bin /Y
add wave -radix bin /Z
add wave tb_Full_Adder/u_Full_Adder/k_C
add wave tb_Full_Adder/u_Full_Adder/k_S
add wave tb_Full_Adder/u_Full_Adder/o_Sum
add wave tb_Full_Adder/u_Full_Adder/O_carry
add wave tb_Full_Adder/u_Full_Adder/w_full

run 500ns

 

k_C, k_S 는 카르노맵을 이용한 Carry와 Sum 
o_Carry , o_Sum 은 논리식을 이용한 Carry 와 Sum
C와 S는 진리표를 이용한 Carry 와 Sum이다.
모두 진리표와 같은 출력을 갖는다. 

3. 디코더 

//build Decorder - Case
module Decoder1 (
  input [2:0]       inp   ,
  input             en    ,
  output reg [7:0]  o_Dec  
);

  always @(*) begin
  0_Dec = 8'h00; //define case default
    if (en) begin
      case (inp)
        3'h1 : o_Dec = 8'h01;
        3'h2 : o_Dec = 8'h02;
        3'h3 : o_Dec = 8'h03;
        3'h4 : o_Dec = 8'h04;
        3'h5 : o_Dec = 8'h05; 
        3'h6 : o_Dec = 8'h06;
        3'h7 : o_Dec = 8'h07;
        default : o_Dec = 8'h00; 
      endcase
      
    end
    
  end
  
endmodule

//build Decorder - assign
module Decoder2 (
  input [2:0]       inp   ,
  input             en    ,
  output [7:0]      o_Dec  
);

assign o_Dec = (en) ? 1'b1 << inp : 8'h00;

endmodule

4. 입출력 장치 실습

푸시버튼 스위치 값 LED 표현

module SwitchEncoder (
  input               clk     ,
  input       [15:0]  key     ,
  output reg  [3:0]   keyval   
);

always @(posedge clk) begin
  case (key)
    16'b0000_0000_0000_0001 : keyval = 4'b0000; 
    16'b0000_0000_0000_0010 : keyval = 4'b0001; 
    16'b0000_0000_0000_0100 : keyval = 4'b0010; 
    16'b0000_0000_0000_1000 : keyval = 4'b0011; 
    16'b0000_0000_0001_0000 : keyval = 4'b0100; 
    16'b0000_0000_0010_0000 : keyval = 4'b0101; 
    16'b0000_0000_0100_0000 : keyval = 4'b0110; 
    16'b0000_0000_1000_0000 : keyval = 4'b0111; 
    16'b0000_0001_0000_0000 : keyval = 4'b1000; 
    16'b0000_0010_0000_0000 : keyval = 4'b1001; 
    16'b0000_0100_0000_0000 : keyval = 4'b1010; 
    16'b0000_1000_0000_0000 : keyval = 4'b1011; 
    16'b0001_0000_0000_0000 : keyval = 4'b1100; 
    16'b0010_0000_0000_0000 : keyval = 4'b1101; 
    16'b0100_0000_0000_0000 : keyval = 4'b1110; 
    16'b1000_0000_0000_0000 : keyval = 4'b1111; 
    default: ;
  endcase
  
end
  
endmodule

module SwitchEncoder_tb;
  reg clk;
  reg [15:0] key;
  wire [3:0] keyval;

  SwitchEncoder uut (
    .clk(clk),
    .key(key),
    .keyval(keyval)
  );

  // 클럭 생성
initial begin
  clk=0;
  forever
    #10 clk = ~clk;
  end
  
  initial begin
    key = 16'b0;
    #10 key=16'b1;
    #20 key=16'd2;
    forever
    #20 key = key +2;
 
  end

endmodule
vlib work
vlog SwitchEncoder.v SwitchEncoder_tb.v
vsim -t ns work.SwitchEncoder_tb
view wave
add wave -radix bin /clk
add wave -radix unsigned /key
add wave -radix unsigned /keyval

run 200ns

7segment 2개를 이용한 16진수 표현

세그먼트를 나타내는 방식은 다음과 같다.

case (input value)
 트리거 1 : FND = 7'b000_0000;
 ...
 트리거 last : FND = 7'b000_0000;
 default : ;
 endcase

7segment bin,hex code

module Segment (
  input             clk     ,
  input      [3:0]  sw1     ,
  input      [3:0]  sw2     ,
  output reg [6:0]  FND1    ,
  output reg [6:0]  FND2     
);

 always @(posedge clk) begin
  
 case (sw1)
    4'b0001 : FND1 = 7'b011_0000;
    4'b0010 : FND1 = 7'b110_1101;
    4'b0011 : FND1 = 7'b111_1001;
    4'b0100 : FND1 = 7'b011_0011;
    4'b0101 : FND1 = 7'b101_1011;
    4'b0110 : FND1 = 7'b101_1111;
    4'b0111 : FND1 = 7'b111_0010;
    4'b1000 : FND1 = 7'b111_1111;
    4'b1001 : FND1 = 7'b111_1011;
    4'b1010 : FND1 = 7'b111_0111;
    4'b1011 : FND1 = 7'b001_1111;
    4'b1100 : FND1 = 7'b100_1110;
    4'b1101 : FND1 = 7'b011_1101;
    4'b1110 : FND1 = 7'b100_1111;
    4'b1111 : FND1 = 7'b100_0111;  
    default: FND1 = 7'b111_1110; 
 endcase

case (sw2)
    4'b0001 : FND2 = 7'b011_0000;
    4'b0010 : FND2 = 7'b110_1101;
    4'b0011 : FND2 = 7'b111_1001;
    4'b0100 : FND2 = 7'b011_0011;
    4'b0101 : FND2 = 7'b101_1011;
    4'b0110 : FND2 = 7'b101_1111;
    4'b0111 : FND2 = 7'b111_0010;
    4'b1000 : FND2 = 7'b111_1111;
    4'b1001 : FND2 = 7'b111_1011;
    4'b1010 : FND2 = 7'b111_0111;
    4'b1011 : FND2 = 7'b001_1111;
    4'b1100 : FND2 = 7'b100_1110;
    4'b1101 : FND2 = 7'b011_1101;
    4'b1110 : FND2 = 7'b100_1111;
    4'b1111 : FND2 = 7'b100_0111;  
    default: FND2 = 7'b111_1110; 
 endcase    
  end

endmodule
module tb_Segment (
  
);

  reg          clk     ;
  reg   [3:0]  sw1     ;
  reg   [3:0]  sw2     ;
  wire  [6:0]  FND1    ;
  wire  [6:0]  FND2    ;  

  Segment u_segment1(

    .clk (clk ),
    .sw1 (sw1 ),
    .sw2 (sw2 ),
    .FND1(FND1),
    .FND2(FND2)

  );

 initial begin
  clk=0;
  forever
    #10 clk = ~clk;
  end

  initial begin
    sw1=4'b0;
    #10 sw1=4'd1;
    forever
    #10 sw1 = sw1+1; 
  end

  initial begin
    sw2=4'b0;
    forever
    #10 sw2 = sw2+sw1;
  end

endmodule

module Segment_kar (
  input      [3:0]  sw1     ,
  output     [6:0]  FND    
);

assign FND[6] = ~sw1[3] & ~sw1[2] & ~sw1[1] & sw1[0]
                | ~sw1[3] & sw1[2] & ~sw1[1] & ~sw1[0]
                | sw1[3] & sw1[2] & ~sw1[1] & sw1[0]
                | sw1[3] & ~sw1[2] & sw1[1] & sw1[0] ; //a

assign FND[5] = sw1[2] & sw1[1] & ~sw1[0]
                | sw1[3] & sw1[1] & sw1[0]
                | ~sw1[3] & sw1[2] & ~sw1[1] & sw1[0]
                | sw1[3] & sw1[2] & ~sw1[1] & ~sw1[0] ; //b

assign FND[4] = ~sw1[3] & ~sw1[2] & sw1[1] & ~sw1[0]
                | sw1[3] & sw1[2] & sw1[1]
                | sw1[3] & sw1[2] & ~sw1[0]; //c

assign FND[3] = ~sw1[3] & ~sw1[2] & ~sw1[1] & sw1[0]
                | ~sw1[3] & sw1[2] & ~sw1[1] & ~sw1[0]
                | sw1[3] & ~sw1[2] & sw1[1] & ~sw1[0]
                | sw1[2] & sw1[1] & sw1[0] ; //d

assign FND[2] = ~sw1[3] & sw1[0]
                | ~sw1[3] & sw1[2] & ~sw1[1]
                | ~sw1[2] & ~sw1[1] & sw1[0] ;//e

assign FND[1] = ~sw1[3] & ~sw1[2] & sw1[0]
                | ~sw1[3] & ~sw1[2] & sw1[1]
                | ~sw1[3] & sw1[1] & sw1[0]
                | sw1[3] & sw1[2] & ~sw1[1] & sw1[0] ; //f

assign FND[0] = ~sw1[3] & ~sw1[2] & ~sw1[1]
                | sw1[3] & sw1[2] & ~sw1[1] & ~sw1[0]
                | ~sw1[3] & sw1[2] & sw1[1] & sw1[0] ; //g

endmodule
module tb_Segment_kar (
  
);


  reg   [3:0]  sw1     ;
  wire  [6:0]  FND      ;

  Segment_kar u_Segment_kar1(

    .sw1 (sw1 ),
    .FND (FND )
  );



  initial begin
    sw1=4'b0;
    #10 sw1=4'd1;
    forever
    #10 sw1 = sw1+1; 
  end

endmodule

5. 4x1멀티플렉서

module my_mux4x1(
  input [1:0] s,
  input [3:0] i,
  output reg  y 

);


  always @(*) 
    begin : MUX
    case(s)
      2'b01:y=i[1];
      2'b10:y=i[2];
      2'b11:y=i[3]; 
    default : y=i[0];
  
    endcase      
  end
endmodule
`timescale 1ns/1ns  // 시뮬레이션 스케일을 설정합니다.

module tb_my_mux4x1();
  reg [1:0] s;
  reg [3:0] i;
  wire y;
  // 모듈을 인스턴스화합니다.
  my_mux4x1 uMy_mux4x1 (
    .s(s),
    .i(i),
    .y(y)
  );

  initial begin
    s = 2'b00;
    forever #40 s= s+2'b01;
  end

  initial begin
    i=4'b0101;
    #160;
    i=4'b0000;
  end

endmodule

 

6. 크기 비교기

`define param 4

module my_comparator (
    input   [`param-1:0]    a           ,
    input   [`param-1:0]    b           ,
    output  reg             aLessb      ,
    output  reg             aGreaterb   ,
    output  reg             aEqualb      
); 

always @(*) begin
    if (a>b) begin
        aLessb <= 1'b0;
        aEqualb <=  1'b0;
        aGreaterb <= 1'b1;

    end else if (a==b) begin
        aLessb <= 1'b0;
        aEqualb <= 1'b1;
        aGreaterb <= 1'b0;
    
    end else begin
        aLessb <= 1'b1;
        aEqualb <= 1'b0;
        aGreaterb <= 1'b0;
    end
    
end

endmodule

 

`define param 4


module tb_my_comparator (
    reg   [`param-1:0]    a         ;        
    reg   [`param-1:0]    b         ;        
    wire                  aLessb    ;
    wire                  aGreaterb ;
    wire                  aEqualb   ;
); 

my_comparator uMy_comparator (
    .a        (a        )   ,
    .b        (b        )   ,
    .aLessb   (aLessb   )   ,
    .aGreaterb(aGreaterb)   ,
    .aEqualb  (aEqualb  )    
); 

initial begin
    a=4'b0000;
    forever #20 a=a+4'b0001;
end

initial begin
    b=4'b0000;
    forever #25 b=b+4'b0001;
end

endmodule

 

7 n비트 가감산기

module my_nBitAddSub3 (
  input               clk     ,
  input               m       ,
  input       [3:0]   a       ,
  input       [3:0]   b       ,
  output reg  [6:0]   FND1    ,
  output reg  [6:0]   FND2    ,
  output reg  [1:0]   FND1Sel ,
  output reg  [1:0]   FND2Sel  
);

  integer ai=0, bi=0;
  integer hex1=0, hex2=0;
  integer result;
  integer k=0;
  reg sign;
  reg [6:0] FND1Val1, FND1Val2; // Separate variables for FND1Val1 and FND1Val2
  reg clk100Hz;

  always @(posedge clk) begin
    if (k >= 499999) begin
      k <= 0;
      clk100Hz <= ~clk100Hz;
    end else
      k <= k+1;
  end

  always @ (a or b or result) begin
    ai = a;
    bi = b;

    if (m==1'b0) 
      result = ai+bi;
      else
      result = ai-bi;


    if (m == 1'b0) begin
      sign = 1'b1;
      hex2 = ~result / 16;
      hex1 = ~result % 16;
    end else begin
      sign = 1'b0;
      hex2 = result / 16;
      hex1 = result % 16;
    end
  end


  always @ (hex1 or hex2) begin
    case (hex2)
      0   : FND1Val2 = 7'b1111110;
      1   : FND1Val2 = 7'b0110000;
      2   : FND1Val2 = 7'b1101101;
      3   : FND1Val2 = 7'b1111001;
      4   : FND1Val2 = 7'b0110011;
      5   : FND1Val2 = 7'b1011011;
      6   : FND1Val2 = 7'b1011111;
      7   : FND1Val2 = 7'b1110000;
      8   : FND1Val2 = 7'b1111111;
      9   : FND1Val2 = 7'b1110011;
      10  : FND1Val2 = 7'b1111101;
      11  : FND1Val2 = 7'b0011111;
      12  : FND1Val2 = 7'b0001101;
      13  : FND1Val2 = 7'b0111101;
      14  : FND1Val2 = 7'b1101111;
      15  : FND1Val2 = 7'b1000111;
      default : FND1Val2 = 7'b0000000;  
    endcase

    case (hex1)
      0   : FND1Val1 = 7'b1111110;
      1   : FND1Val1 = 7'b0110000;
      2   : FND1Val1 = 7'b1101101;
      3   : FND1Val1 = 7'b1111001;
      4   : FND1Val1 = 7'b0110011;
      5   : FND1Val1 = 7'b1011011;
      6   : FND1Val1 = 7'b1011111;
      7   : FND1Val1 = 7'b1110000;
      8   : FND1Val1 = 7'b1111111;
      9   : FND1Val1 = 7'b1110011;
      10  : FND1Val1 = 7'b1111101;
      11  : FND1Val1 = 7'b0011111;
      12  : FND1Val1 = 7'b0001101;
      13  : FND1Val1 = 7'b0111101;
      14  : FND1Val1 = 7'b1101111;
      15  : FND1Val1 = 7'b1000111;
      default : FND1Val1 = 7'b0000000;  
    endcase
  end

  always @(posedge clk) begin
    if (clk100Hz) begin
      FND1Sel[0] <= 1'b0;
      FND1Sel[1] <= 1'b1;
      FND1 <= FND1Val1;
    end else begin
      FND1Sel[0] <= 1'b0;
      FND1Sel[1] <= 1'b1;
      FND1 <= FND1Val2;
    end
  end

  always @* begin
    if (sign == 1'b1)
      FND2 <= 7'b0000001;
    else
      FND2 <= 7'b0000000;
  end

  always @(posedge clk100Hz or posedge clk) begin
    if (clk100Hz) begin
      FND2Sel[0] <= 1'b0;
      FND2Sel[1] <= 1'b1;
    end else begin
      FND2Sel[0] <= 1'b0;
      FND2Sel[1] <= 1'b1;
    end
  end

endmodule
module tb_my_nBitAddSub3();
  reg                 clk     ;
  reg                 m       ;
  reg         [3:0]   a       ;
  reg         [3:0]   b       ;
  wire        [6:0]   FND1    ;
  wire        [6:0]   FND2    ;
  wire        [1:0]   FND1Sel ;
  wire        [1:0]   FND2Sel ;

my_nBitAddSub3 uMy_nBitAddSub3(
  .clk    (clk    ) ,
  .m      (m      ) ,
  .a      (a      ) ,
  .b      (b      ) ,
  .FND1   (FND1   ) ,
  .FND2   (FND2   ) ,
  .FND1Sel(FND1Sel) ,
  .FND2Sel(FND2Sel)  
);

initial fork 
  clk_gen();
  data_gen();
  cntrl_gen();
join

task clk_gen; 
begin
  clk = 1'b0;
  forever #10 clk = clk+1'b1;
end
endtask

/*
task data_gen;
begin
  a=3'b0;
  b=3'b0;
  repeat(3)@(negedge clk);
  forever begin
    #20;
    a=a+1;
    b=b+1;
  end
 end
endtask
*/
task data_gen;
integer i;
begin
  a=3'd0;
  b=3'd0;
   repeat(3)@(negedge clk);
  for (i =0   ;i<16 ;i=i+1 ) begin
    #20;
    a=a+1;
    b=b+1;  
  end
end
endtask


task cntrl_gen;
begin
  m=1'b0;
  repeat(19) @(negedge clk);
  m=1'b1;
  repeat(19)@(negedge clk);
end
endtask

endmodule

DE1-SOC 에 맞춰 다시 빌드한 코드

module my_nBitAddSub3 (
  input               clk     ,
  input               m       ,
  input       [3:0]   a       ,
  input       [3:0]   b       ,
  output reg  [6:0]   FND1    ,
  output reg  [6:0]   FND2    ,
	output      [1:0]   FND2Sel ,
	output reg  [1:0]   FND1Sel  
  );

  integer ai=0, bi=0;
  integer hex1=0, hex2=0;
  integer result;
  reg sign;
  reg [6:0] FND1Val1, FND1Val2; // Separate variables for FND1Val1 and FND1Val2
  reg clk100Hz;


  integer k=0;
  always @(posedge clk) begin
    if (k >= 249999) begin
      k <= 0;
      clk100Hz <= ~clk100Hz;
    end else
      k <= k+1;
  end

  always @ (a or b or m or result) begin
    ai = a;
    bi = b;

    if (m==1'b0) 
      result = ai+bi;
      else
      result = ai-bi;


    if (m == 1'b0) begin
      sign = 1'b0;
      hex2 = -result / 16;
      hex1 = -result % 16;
    end else begin
      sign = 1'b1;
      hex2 = result / 16;
      hex1 = result % 16;
    end
  end


  always @ (hex1 or hex2) begin
    case (hex2)
	 //0   : FND1Val2 = 7'bgfedcba;
      0   : FND1Val2 = ~7'b0111111;
      1   : FND1Val2 = ~7'b0000110;
      2   : FND1Val2 = ~7'b1011011;
      3   : FND1Val2 = ~7'b1001111;
      4   : FND1Val2 = ~7'b1100110;
      5   : FND1Val2 = ~7'b1101101;
      6   : FND1Val2 = ~7'b1111101;
      7   : FND1Val2 = ~7'b0100111;
      8   : FND1Val2 = ~7'b1111111;
      9   : FND1Val2 = ~7'b1100111;
      10  : FND1Val2 = ~7'b1110111;
      11  : FND1Val2 = ~7'b1111100;
      12  : FND1Val2 = ~7'b0111001;
      13  : FND1Val2 = ~7'b1011110;
      14  : FND1Val2 = ~7'b1111001;
      15  : FND1Val2 = ~7'b1110001;
      default : FND1Val2 = ~7'b0000000;  
    endcase

    case (hex1)
      0   : FND1Val2 = ~7'b0111111;
      1   : FND1Val2 = ~7'b0000110;
      2   : FND1Val2 = ~7'b1011011;
      3   : FND1Val2 = ~7'b1001111;
      4   : FND1Val2 = ~7'b1100110;
      5   : FND1Val2 = ~7'b1101101;
      6   : FND1Val2 = ~7'b1111101;
      7   : FND1Val2 = ~7'b0100111;
      8   : FND1Val2 = ~7'b1111111;
      9   : FND1Val2 = ~7'b1100111;
      10  : FND1Val2 = ~7'b1110111;
      11  : FND1Val2 = ~7'b1111100;
      12  : FND1Val2 = ~7'b0111001;
      13  : FND1Val2 = ~7'b1011110;
      14  : FND1Val2 = ~7'b1111001;
      15  : FND1Val2 = ~7'b1110001;
      default : FND1Val1 = ~7'b0000000;  
    endcase
  end

 assign FND2Sel[1]= 1'b0;
 assign FND2Sel[0]= 1'b1;

  always @(sign) begin
    if (sign == 1'b1)
      FND2 = ~7'b1000000;
    else
      FND2 = ~7'b0000000;
  end

always @(clk100Hz, FND1Val2, FND1Val1) begin
  if (clk100Hz) begin
    FND1Sel[0] = 1'b0;
    FND1Sel[1] = 1'b1;
    FND1=FND1Val1;
  end else begin
    FND1Sel[0] = 1'b0;
    FND1Sel[1] = 1'b1;
    FND1=FND1Val2;
  end
end



endmodule

 

 

8. '1' 개수 카운터

module one_counter(
    input           [7:0]   d       ,
    output  reg     [6:0]   FND     ,
    output                  FNDSel1 ,
    output                  FNDSel2  
);

integer     oneCount, i=0;

always @(d or oneCount) begin
    oneCount =0;
    for (i =0 ;i<8 ;i=i+1 ) begin
        if (d[i]) begin
            oneCount = oneCount +1;
        end
    end    
end

assign FNDSel2 = 1'b1;
assign FNDSel1 = 1'b0;

always @(oneCount) begin
    case (oneCount)
        0: FND = 7'b1111110;
        1: FND = 7'b0110000;
        2: FND = 7'b1101101;
        3: FND = 7'b1111001;
        4: FND = 7'b0110011;
        5: FND = 7'b1011011;
        6: FND = 7'b1011111;
        7: FND = 7'b1110000;
        8: FND = 7'b1111111;
        default: FND=7'b1011011;
    endcase
end
    
endmodule

 

728x90

'Study > VerilogHDL' 카테고리의 다른 글

[Study] 기타회로 설계 [진행중]  (0) 2023.09.02
[Study] 순차논리회로 설계 [진행중]  (0) 2023.09.02
자습 방향 설정  (0) 2023.09.02
[Vivado] FSM (Stop Watch, 가산기) with button.  (0) 2023.08.04
레지스터와 카운터  (0) 2023.08.04