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 |