본문 바로가기

verilog HDL

[Verilog HDL]

shift

module shifter1 (A, B, Y);
input  [7:0] A;
input  [3:0] B;
output [7:0] Y;

assign Y = A << B;

endmodule

 

module shifter2 (A, B, Y);
input [7:0] A;
input [3:0] B;
output [7:0] Y;
reg [7:0] Y;

always@*
  case(B)
0: Y = A;
     1: Y = {A[6:0],1b'0}; 
   2: Y = {A[5:0],2b'0};
     3: Y = {A[4:0],3b'0};
     4: Y = {A[3:0],4b'0};   
     5: Y = {A[2:0],5b'0};
     6: Y = {A[1:0],6b'0};
     7: Y = {A[0],7b'0};
     default: Y = 0;
  endcase

endmodule

 

module shifter3 (A, B, Y);
input [7:0] A;
input [3:0] B;
output [7:0] Y;

wire [7:0] BitShift[0:3];

// initial
assign BitShift[0] = A;

// Recursive structure, can be designed by using for-loop
assign BitShift[1] = B[2] ? {BitShift[0][3:0], 4b'0} : BitShift[0];  
assign BitShift[2] = B[1] ? {BitShift[1][5:0], 2b'0} : BitShift[1];
assign BitShift[3] = B[0] ? {BitShift[2][6:0], 1b'0} : BitShift[2];

// final output
assign Y = B[3]? 0 : BitShift[3];

endmodule

 

module tb_shifter;

reg [7:0] X = 0;
reg [3:0] Y = 0;
wire [7:0] SO1, SO2, SO3;

initial
begin
X = 255; Y = 8;
repeat(8) #10 Y=Y-1;
end

shifter1 U1 (X, Y, SO1); //position mapping
shifter2 U2 (.A(X), .B(Y), .Y(SO2));  //named mapping
shifter3 U3 (.A(X), .Y(SO3), .B(Y));

endmodule

 

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

divider

module divider1 (A, B, Y);
input [7:0] A, B;
output [7:0] Y;

assign Y = A / B;

endmodule

 

module divider2 (A, B, Y);
input  [7:0] A, B;
output [7:0] Y;
 
wire  [8:0] sub_results[1:7];
wire  [8:0] part_divd[0:7];

  // A[7]
assign part_divd[7] = {8'b0, A[7]};
assign sub_results[7] = part_divd[7] >= B ? part_divd[7] - B : part_divd[7];
assign Y[7] = (part_divd[7] >= B);

  // A[6]
assign part_divd[6] = {sub_results[7][7:0], A[6]};
assign sub_results[6] = part_divd[6] >= B? part_divd[6] - B : part_divd[6];
assign Y[6] = (part_divd[6] >= B);

  // A[5]
assign part_divd[5] = {sub_results[6][6:0], A[5]};
assign sub_results[5] = part_divd[5] >= B? part_divd[5] - B : part_divd[5];
assign Y[5] = (part_divd[5] >= B);

  // A[4]
assign part_divd[4] = {sub_results[5][7:0], A[4]};
assign sub_results[4] = part_divd[4] >= B? part_divd[4] - B : part_divd[4];
assign Y[4] = (part_divd[4] >= B);

  // A[3]
assign part_divd[3] = {sub_results[4][7:0], A[3]};
assign sub_results[3] = part_divd[3] >= B? part_divd[3] - B : part_divd[3];
assign Y[3] = (part_divd[3] >= B);

  // A[2]
assign part_divd[2] = {sub_results[3][7:0], A[2]};
assign sub_results[2] = part_divd[2] >= B? part_divd[2] - B : part_divd[2];
assign Y[2] = (part_divd[2] >= B);

  // A[1]
assign part_divd[1] = {sub_results[2][7:0], A[1]};
assign sub_results[2] = part_divd[2] >= B? part_divd[1] - B : part_divd[1];
assign Y[1] = (part_divd[1] >= B);

  // A[0]
assign part_divd[0] = {sub_results[1][7:0], A[0]};
assign Y[0] = (part_divd[0] >= B);

endmodule

 

위의 내용과 동일한 루프구조

module divider2_loop (A, B, Y);
input [7:0] A, B;
output [7:0] Y;
 
reg  [8:0] sub_results[0:8];
reg  [8:0] part_divd[0:7];
reg  [7:0] Y;
integer i;

always@*
begin
  sub_results[0] = 0;
 
  for(i=0; i<8; i=i+1)
  begin
    part_divd[i] = {sub_results[i][7:0], A[7-i]};
    if (part_divd[i] >= B)
    begin
      sub_results[i+1] = part_divd[i] - B;
      Y[7-i] = 1;
    end
    else
    begin
      sub_results[i+1] = part_divd[i];
      Y[7-i] = 0;
    end
  end

end

endmodule

 

module divider3 (nRST, CLK, ENI, A, B, ENO, Y);
input        nRST, CLK, ENI;
input  [7:0] A, B;
output       ENO;
output [7:0] Y;
reg          ENO;
reg    [7:0] Y;

reg  [3:0] ctrl_cnt;
reg  [8:0] CSpart_divd;
 
wire [8:0] sub_results = CSpart_divd - B;
wire [8:0] data_sel_res = (CSpart_divd>=B)? sub_results : CSpart_divd;
wire       Quo = (CSpart_divd>=B)? 1 : 0;
     wire [7:0] NSpart_divd = data_sel_res[7:0];

always@(posedge CLK or negedge nRST)
  if(!nRST)
    ctrl_cnt <= 0;
  else if (ctrl_cnt == 8) // division process during ctrl_cnt=1 ~ 8
    ctrl_cnt <= 0;
  else if (ENI || (ctrl_cnt !=0))
    ctrl_cnt <= ctrl_cnt + 1;

always@(posedge CLK)
  if (ENI)
    CSpart_divd <={7'b0, A[7]}; // CSpart_divd valid point : ctrl_cnt=1
    else if (0<ctrl_cnt && ctrl_cnt<8)
    CSpart_divd <= {NSpart_divd ,A[7-ctrl_cnt]};  

always@(posedge CLK)
  if (ENI)
    Y <= 0;
  else if (ctrl_cnt!=0) // Quotient calulation valid point : ctrl_cnt=1
    Y <= {Y[6:0], Quo};  // Output valid point = 9 clock latency

always@(posedge CLK or negedge nRST)
  if (!nRST)
    ENO <= 0;
  else if (ctrl_cnt == 8)
    ENO <= 1;
  else 
    ENO <= 0;

endmodule

 

module tb_div;

reg        nRST = 0, CLK = 0, ENI = 0;
reg  [7:0] X = 0, Y = 0;
wire       ENO;
wire [7:0] DIVO1, DIVO2, DIVO2_LOOP, DIVO3;

initial
forever #5 CLK = ~CLK;

initial
begin
    #16  nRST = 1;
#100 ENI = 1; X = 255; Y = 255;
#10  ENI = 0;

#100 ENI = 1; X = 255; Y = 0;
#10  ENI = 0;

#100 ENI = 1; X = 0; Y = 255;
#10  ENI = 0;

#100 ENI = 1; X = 0; Y = 0;
#10  ENI = 0;

#100 ENI = 1; X = 123; Y = 13;
#10  ENI = 0;

#100 ENI = 1; X = 208; Y = 3;
#10  ENI = 0;
end

divider1 U1 (.A(X), .B(Y), .Y(DIVO1));
divider2 U2 (.A(X), .B(Y), .Y(DIVO2)); 
divider2_loop U3 (.A(X), .B(Y), .Y(DIVO2_LOOP));
divider3 U4 (.nRST(nRST), .CLK(CLK), .ENI(ENI), .A(X), .B(Y), .ENO(ENO), .Y(DIVO3));

endmodule

 

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

push button detector

module pb_detector (nRST, CLK, PB, PBO);
input   nRST, CLK, PB;
output  PBO;

reg       PB_meta, PB_SYNC;
reg [9:0] CNT;
always@(negedge nRST or posedge CLK)
begin
  PB_meta <= PB; // 1F/F
  PB_SYNC <= PB_meta; // 2F/F
  
  if(!nRST)
    CNT <= 0;
  else if (PB_SYNC)   // Push button is not activated
CNT <= 0;
  else if (CNT != 1001) // counting limit=1,001(100us) : cnt holding
    CNT <= CNT + 1;
end

    assign PBO = (CNT==1000);

endmodule

 

module tb_pb;

reg  nRST = 0, CLK = 0, PBI = 1;
wire PBO;

initial
forever #50 CLK = ~CLK;

initial
begin
#100        nRST = 1;
repeat(10) #(100*20) PBI = ~PBI;
#(100*  10) PBI = 0;
#(100*1100) PBI = 1;
#(100*1000) PBI = 0;
repeat(10) #100 PBI = ~PBI;
#(100*  10) PBI = 0;
#(100*1500) PBI = 1;
#(100*1000) PBI = 0;
#(100* 100) PBI = 1;
end

pb_detector DUT(.nRST(nRST), .CLK(CLK), .PB(PBI), .PBO(PBO));

endmodule

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

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