본문 바로가기

verilog HDL

[Verilog HDL] 실습2

FSM

module traffic_fsm (nRST, CLK, RO, GO, LO, YO);
input  nRST, CLK;
output RO, GO, LO, YO;
reg    RO, GO, LO, YO;

parameter RED = 0;
parameter GRN = 1;
parameter LEF = 2;
parameter YEL = 3;

reg       state_en;
reg [4:0] state_cnt;
reg [1:0] CS_state; // current state
reg [1:0] NS_state; // next state

// state enable counter
always@(negedge nRST or posedge CLK)
  if(!nRST)
    state_cnt <= 0;
  else if(state_en)
    state_cnt <= 0;
  else
    

// state enable
always@*
  case(CS_state)
    RED : state_en = (state_cnt == 19);
GRN : state_en = (state_cnt == 19);
LEF : state_en = (state_cnt == 9);
YEL : state_en = (state_cnt == 2);
default : state_en = 1'bx;
  endcase

// Current state machine
always@(negedge nRST or posedge CLK)
  if(!nRST)
    CS_state <= RED;
  else if(state_en)
    CS_state <= NS_state;
  
// Next state condition (moore machine)
always@*
  case(CS_state)
     RED : NS_state = GRN;
GRN : NS_state = LEF;
LEF : NS_state = YEL;
YEL : NS_state = RED;
default : NS_state = 2'bx;
  endcase

// Output generation
always@*
  case(CS_state)
   RED : {RO, GO, LO, YO} = 4'b1000; // RED : begin RO = 1'b1 , GO = 1'b0 , ..... end
GRN : {RO, GO, LO, YO} = 4'b0100;
LEF : {RO, GO, LO, YO} = 4'b0010;
YEL : {RO, GO, LO, YO} = 4'b0001;
default : {RO, GO, LO, YO} = 4'bx;
  endcase

endmodule

 

module tb_fsm;

reg  nRST = 0, CLK = 0;
wire REDO, YELO, LEFO, GRNO;

initial
forever #5 CLK = ~CLK;

initial
#10   nRST = 1;

traffic_fsm DUT(.nRST(nRST), .CLK(CLK), .RO(REDO), .GO(GRNO), .LO(LEFO), .YO(YELO));

endmodule

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UART

module uartTX (nRST, CLK, EN, DATA8, TXD);
input       nRST, CLK, EN;
input [7:0] DATA8;
output      TXD;
reg         TXD;

parameter baud  = 1042;
parameter IDLE  = 0;
parameter START = 1;
parameter TX    = 2;
parameter END   = 3;

wire       baud_dur;
reg [10:0] baud_cnt;
reg [ 7:0] data_cnt, PDATA_reg;
reg [ 1:0] CS_state; // current state
reg [ 1:0] NS_state; // next state

// baud duration counter
always@(negedge nRST or posedge CLK)
  if(!nRST)
    baud_cnt <= 0;
  else if(baud_dur)
    baud_cnt <= 0;
  else if(CS_state>0)
    baud_cnt <= baud_cnt + 1;

// baud duration enable
assign baud_dur = (baud_cnt == baud-1); //CS_state != idle &&

// data counter
always@(negedge nRST or posedge CLK)
  if(!nRST)
    data_cnt <= 0;
  else if(EN || CS_state==END) // clear
    data_cnt <= 0;
  else if(CS_state==TX && baud_dur)
    data_cnt <= data_cnt + 1;

// Current state machine
always@(negedge nRST or posedge CLK)
  if(!nRST)
    CS_state <= IDLE;
  else if(baud_dur || EN)
    CS_state <= NS_state;
  
// Next state condition
always@*
  case(CS_state)
    IDLE  : NS_state = START;
    START : NS_state = TX;
    TX    : if (data_cnt==7) NS_state = END;
            else             NS_state = TX;
    END   : NS_state = IDLE;
    default : NS_state = 2'bx;
  endcase

// Parallel data catch
always@(posedge CLK)
  if(EN)
    PDATA_reg <= DATA8;

// Output generation
always@(negedge nRST or posedge CLK)
  if(!nRST)
    TXD <= 1'b1;
  else if(CS_state==START)
    TXD <= 1'b0;
  else if(CS_state==END || CS_state==IDLE)
    TXD <= 1'b1;
  else
    case(data_cnt)
      0 : TXD <= PDATA_reg[0];
      1 : TXD <= PDATA_reg[1];
      2 : TXD <= PDATA_reg[2];
      3 : TXD <= PDATA_reg[3];
      4 : TXD <= PDATA_reg[4];
      5 : TXD <= PDATA_reg[5];
      6 : TXD <= PDATA_reg[6];
      7 : TXD <= PDATA_reg[7];
      default : TXD <= 1'bx;
    endcase

endmodule

 

`timescale 1ns/1ns

module tb_uartTX;
reg       nRST = 0, CLK = 0, EN = 0;
reg [7:0] PDATA = 0; 
wire      TXD;
parameter baud = 1042;

initial
forever #50 CLK = ~CLK; //10MHz clock

initial
begin
#100    nRST = 1;
repeat (baud * 3) #100;
#100    EN = 1; PDATA = 11001111;
#100    EN = 0;

repeat (baud * 20) #100;
#100    EN = 1; PDATA = 01101001;
#100    EN = 0;

repeat (baud * 20) #100;
#100    EN = 1; PDATA = 01001010;
#100    EN = 0;

end

uartTX #(baud) DUT(.nRST(nRST), .CLK(CLK), .EN(EN), .DATA8(PDATA), .TXD(TXD));

endmodule

 

/////////////////////////////////////////////////////////////////////////////////////////////

multiplier

module StoP_multiplier(CLK, ENI, A, B, ENO, YO);
input         CLK, ENI;
input  [ 7:0] A, B;
output        ENO;
output [15:0] YO;

// Serial to Parallel processing
reg [1:0] Iorder_cnt;
always@(posedge CLK)
  if(!ENI)
    Iorder_cnt <= 0;
  else
    Iorder_cnt <= Iorder_cnt + 1;

reg [7:0] PA[0:3], PB[0:3];
    always@(posedge CLK)
  if(ENI)
  begin
  PA[Iorder_cnt]<= A;
          PA[Iorder_cnt]<= B;
  end

// Parallel processing multiplier
reg [15:0] PY[0:3];
integer i;
always@(posedge CLK)
  for(i=0; i<4; i=i+1)
    PY[i] <= PA[i] * PB[i];

// Final output
reg [4:0] temp_ENO;
reg [1:0] Oorder_cnt;
always@(posedge CLK)
begin
  temp_ENO <= {temp_ENO[3:0], ENI}; //5clk delay
  
  if(!ENO)
    Oorder_cnt <= 0;
  else
    Oorder_cnt <= Oorder_cnt + 1;
end  
  
assign ENO = temp_ENO[4];
assign YO  = PY[Oorder_cnt];

endmodule

 

`timescale 1ns/100ps

module tb_multiplier;
reg       clk=0, en=0;
reg [7:0] mulcant, mulier;

initial forever #0.5 clk = ~clk; //1GHz clock
  
initial begin
  #105.5 en = 1;
  #100   en = 0;  //number of test input = 100
end

initial begin
  mulcant = $random; // System task for random data generation
  mulier  = $random;
end
always@(posedge clk)
  if(en) begin
    mulcant <= $random;   
mulier  <= $random;
  end

//reference signal
reg [7:0] mult_array[0:5], mulr_array[0:5];
integer i;
always@(posedge clk) begin
  mult_array[0] <= mulcant;
  mulr_array[0] <= mulier;
  for(i=1; i<5; i=i+1) begin
mult_array[i] <= mult_array[i-1];
mulr_array[i] <= mulr_array[i-1];
  end  
end
wire [15:0] ref_mult = mult_array[4] * mulr_array[4];

// Parallel processing multiplier
wire [15:0] mult_out;
StoP_multiplier DUT(.CLK(clk), .ENI(en), .A(mulcant), .B(mulier), .ENO(valid), .YO(mult_out));

// error check
wire error = (ref_mult!==mult_out);

endmodule

 

////////////////////////////////////////////////////////////////

fixed adder / multiplier

module adder_fixed(A, B, Y);
input  [15:0] A; //u(8, 8)
input  [15:0] B; //u(5, 11)
output [15:0] Y; //u(8, 8)

wire [18:0] extA = {A, 3'b0};   //u(8,11)
wire [18:0] extSum = extA + B; //u(8,11), Overflow is not considered!
    assign Y = extSum[18:3]; //u(8,8), Round is not considered!

endmodule

 

module multiplier_fixed(A, B, Y);
input  [15:0] A; //u( 8, 8)
input  [15:0] B; //u( 5, 11)
output [23:0] Y; //u(13, 11)

    wire [31:0] multo   = A * B;    // u(13, 19)
assign Y = multo[7] ? multo[31:8] + 1 : multo[31:8]; // round (LSB 8bit), no Overflow                                 

endmodule

 

`timescale 1ns/1ns

module tb_fixed;
real floatX, floatY;

initial
begin
  #10 floatX=3.5;     floatY=2.7;
  #10 floatX=20.23;   floatY=11.45;
  #10 floatX=0.123;   floatY=2.475;
  #10 floatX=255.999; floatY=31.99999999;
end
  
//fixed-point number
wire [15:0] fixedX = $rtoi(floatX * (2**8));  //u(8, 8), System task for real to integer conversion
wire [15:0] fixedY = $rtoi(floatY * (2**11)); //u(5,11)

    //reference
real refadd_float, refmult_float;
always@(*)
begin
  refadd_float  = floatX + floatY;
  refmult_float = floatX * floatY;
end
  
// fixed-point adder & multiplier
wire [15:0] add_fixed;
wire [23:0] mult_fixed;
    adder_fixed DUT0(.A(fixedX), .B(fixedY), .Y(add_fixed));
multiplier_fixed DUT1(.A(fixedX), .B(fixedY), .Y(mult_fixed));

// Error check
real add_float, mult_float, AQuant_err, MQuant_err;
always@(*)
begin
  add_float = $itor(add_fixed) / (2**8); //u(8, 8)
  AQuant_err = add_float - refadd_float;
  
  mult_float = $itor(mult_fixed) / (2**11); //u(13,11)
  MQuant_err = mult_float - refmult_float;
end

endmodule

/////////////////////////////////////////////////////////////////////////////////////////////

ROM

excel

A = 0~255

B =INT(SIN(2*PI()*A1/256)*1023)

C =IF(B1<0,2048+B1,B1)

D =DEC2HEX(C1)

 

module ROM_behav(CLK, ADDR, RDATA);
input         CLK;
input  [ 7:0] ADDR; 
output [10:0] RDATA; 

//synopsys translate_off 
reg [10:0] RDATA;
reg [18:0] rom[0:255];
initial
  $readmemh("sine_wave.txt",rom);
  
    always@(posedge CLK)
  RDATA <= rom[ADDR]; 
//synopsys translate_on

endmodule

 

module sine_gen(nRST, CLK, SIN_WAV);
input         nRST, CLK;
output [10:0] SIN_WAV; 

//phase counter 
reg [7:0] phase_cnt;
always@(posedge CLK or negedge nRST)
  if(!nRST)
    phase_cnt <= 0;
  else
    phase_cnt <= phase_cnt + 1;

//LUT for sine_gen
ROM_behav SINE_ROM(.CLK(CLK), .ADDR(phase_cnt), .RDATA(SIN_WAV));

endmodule

 

`timescale 1ns/1ns

module tb_sinewav;
reg       CLK = 0, nRST = 0;

initial
  forever #50 CLK = ~CLK; //10MHz
  
initial
  #1005      nRST = 1;

// Sine wave generator
wire [10:0] sine_wave;
    sine_gen DUT(.nRST(nRST), .CLK(CLK), .SIN_WAV(sine_wave));

endmodule

waveform에서 decimal, analog파형으로 확인해봐야함.

 

 

 

 

'verilog HDL' 카테고리의 다른 글

[Verilog HDL] random / blocking, non-blocking  (0) 2022.11.02
[Verilog HDL]  (0) 2022.06.02
[Verilog] F/F or Counter  (0) 2022.03.21
[Verilog] Task / Function  (0) 2022.03.21
[Verilog] Behavior modeling 설계  (0) 2022.03.19