1. 程式人生 > >Verilog RTL 程式碼設計新手上路(學生實驗4--11)

Verilog RTL 程式碼設計新手上路(學生實驗4--11)

學生實驗
把加法器的輸出訊號改成4位元位寬,編譯,波形模擬。觀察輸出結果,說出輸出和輸入的對應關係。
把加法器的輸入訊號改成8位元位寬,編譯,波形模擬。觀察加法器的輸出延遲,和4位元輸入位寬的情況對比,你有什麼結論,為什麼?
4位元位寬實驗程式碼如下:
module unadd4_4(
IN1,
IN2,
OUT);
input [3:0] IN1,IN2;
output [3:0] OUT;
reg [3:0] OUT;
always @ (IN1 or IN2) begin
OUT = IN1 + IN2;
end
endmodule
模擬結果如下:
在這裡插入圖片描述
8位元位寬實驗程式碼如下:
module unadd8_5(
IN1,
IN2,
OUT);
input [7:0] IN1,IN2;
output [4:0] OUT;
reg[4:0] OUT;
always @ (IN1 or IN2) begin
OUT = IN1 + IN2;
end
endmodule
模擬結果如下:
在這裡插入圖片描述


學生實驗

把加法器的輸出訊號改成4位元位寬,編譯,波形模擬。觀察輸出結果,觀察輸出結果在什麼時候是正確的?。 把加法器的輸入訊號改成8位元位寬,編譯,波形模擬。觀察加法器的輸出延遲,和4位元輸入位寬的情況對比,你有什麼結論,為什麼?

4位元位寬實驗程式碼如下:
module sigadd4_4(
IN1,
IN2,
OUT);
input signed [3:0] IN1,IN2;
output signed [3:0] OUT;
reg signed [3:0] OUT;

always @ (IN1 or IN2) begin
OUT = IN1 + IN2;
end
endmodule

模擬結果如下:
在這裡插入圖片描述
8位元位寬實驗程式碼如下:
module sigadd8_5(
IN1,
IN2,
OUT);
input signed [7:0] IN1,IN2;
output signed [4:0] OUT;
reg signed [4:0] OUT;

always @ (IN1 or IN2) begin
OUT = IN1 + IN2;
end
endmodule
模擬結果如下:
在這裡插入圖片描述
學生實驗

不改變流水線的級數,把加法器的輸入訊號改成8位元位寬,編譯,波形模擬,和不帶流水線的情況對比一下,你有什麼結論? 在8位元輸入位寬的情況下,在輸入上再新增一級流水線,觀察編譯和模擬的結果,你有什麼結論?

不改變流水線的級數,8位元位寬實驗程式碼如下:
module liadd8_5(
IN1,
IN2,
CLK,
OUT);

input [7:0] IN1,IN2;
input CLK;
output [4:0] OUT;
reg [7:0] in1_dir,in2_dir;
reg [4:0] adder_out,OUT;

always @ (posedge CLK) begin
in1_dir <= IN1;
in2_dir <= IN2;
OUT <= adder_out;
end

always @ (in1_dir or in2_dir) begin
adder_out = in1_dir + in2_dir;
end
endmodule

模擬結果如下:
在這裡插入圖片描述
不改變流水線的級數,8位元位寬實驗程式碼如下:
module liadd2_4_5(
IN1,
IN2,
CLK,
OUT);

input [3:0] IN1,IN2;
input CLK;
output [4:0] OUT;
reg [3:0] in1_d1r,in2_d1r,in1_d2r,in2_d2r;
reg [4:0] adder_out,OUT;

always @ (posedge CLK) begin
in1_d1r <= IN1;
in2_d2r <= IN2;
in1_d2r <= in1_d1r;
in2_d2r <= in2_d1r;
OUT <= adder_out;

end

always @ (in1_d2r or in2_d2r) begin
adder_out = in1_d2r + in2_d2r;
end
endmodule

模擬結果如下:
在這裡插入圖片描述
學生實驗
(1)改變乘法器的輸入位寬為8位元,編譯,波形模擬,觀察訊號毛刺的時間長度。
(2)選一款沒有硬體乘法器的FPGA晶片(例如Cyclone EP1C6)對比8位元的乘法器和加法器兩者編譯之後的資源開銷(Logic Cell的數目)
(3)編寫一個輸入和輸出都有D觸發器的流水線乘法器程式碼,編譯後波形模擬,觀察組合邏輯延遲和毛刺的時間,和不帶流水線的情況下對比。

(1)實驗程式碼如下:
module unmul8_8(
IN1,
IN2,
OUT);

input [7:0] IN1,IN2;
output [7:0] OUT;

reg [7:0] OUT;

always @ (IN1 or IN2) begin
OUT = IN1 * IN2;
end
endmodule

模擬結果如下:
在這裡插入圖片描述
(2)實驗程式碼如下:
module no_unmul8_8(
IN1,
IN2,
OUT);
input [7:0] IN1,IN2;
output [7:0] OUT;
reg [7:0] OUT;

always @ (IN1 or IN2) begin
OUT = IN1 * IN2;
end
endmodule

資源消耗對比如下:
在這裡插入圖片描述
在這裡插入圖片描述
(3)實驗程式碼如下:
module li2mul4_8(
IN1,
IN2,
CLK,
OUT);

input signed [3:0] IN1,IN2;
input CLK;
output signed[7:0] OUT;

reg signed [7:0] muler_out,OUT;
reg signed [3:0] in1_d1r,in2_d1r;

always @ (posedge CLK) begin
in1_d1r <= IN1;
in2_d1r <= IN2;
OUT <= muler_out;
end

always @ (in1_d1r or in2_d1r) begin
muler_out = in1_d1r * in2_d1r;
end
endmodule

模擬結果如下:
在這裡插入圖片描述
學生實驗
(1)設計一個最簡單的計數器,只有一個CLK輸入和一個OVerflow輸出,當計數到最大值的時鐘週期CLK輸出1
(2)設計複雜的計數器,和本例相似,帶有多種訊號,其中同步清零CLR的優先順序最高,使能EN次之,LOAD最低。

(1)實驗程式碼如下:
module countc_o(
clk,
cin,
cout,
Overflow,
Rst_n);

input clk;
input cin;
input Rst_n;
output reg cout = 0;
output reg [3:0] Overflow = 0;

always @(posedge cin or posedge clk or negedge Rst_n)
if(!Rst_n) Overflow = 0;
else if(clk) Overflow = 0;
else if(Overflow == 9)begin
Overflow<=0;cout<=1;
end
else begin
Overflow<=Overflow + 1;cout<=0;
end

endmodule

模擬結果如下:
在這裡插入圖片描述
(2)實驗程式碼如下:
module complex_count(
RST , // 非同步復位, 高有效
CLK , // 時鐘,上升沿有效
EN , // 輸入的計數使能,高有效
CLR , // 輸入的清零訊號,高有效
LOAD , // 輸入的資料載入使能訊號,高有效
DATA , // 輸入的載入資料訊號
CNTVAL, // 輸出的計數值訊號
OV );// 計數溢位訊號,計數值為最大值時該訊號為1

input RST , CLK , EN , CLR , LOAD ;
input [3:0] DATA ;
output [3:0] CNTVAL;
output OV;

reg [3:0] CNTVAL, cnt_next;
reg OV;
// 電路編譯引數,最大計數值
parameter CNT_MAX_VAL = 9;

// 組合邏輯,生成cnt_next
// 計數使能最優先,清零第二優先,載入第三優先
always @(EN or CLR or LOAD or DATA or CNTVAL) begin
if(CLR) begin // 使能有效
if(EN) begin // 清零有效
cnt_next = 0;
end
else begin // 清零無效
if(LOAD) begin // 載入有效
cnt_next = DATA;
end
else begin // 載入無效,正常計數
// 使能有效,清零和載入都無效,根據當前計數值計算下一值
if(CNTVAL < CNT_MAX_VAL) begin // 未計數到最大值, 下一值加1
cnt_next = CNTVAL + 1’b1;
end
else begin // 計數到最大值,下一計數值為0
cnt_next = 0;
end
end // else LOAD
end // else CLR
end // if EN
else begin // 使能無效,計數值保持不動
cnt_next = CNTVAL;
end // else EN
end

// 時序邏輯 更新下一時鐘週期的計數值
// CNTVAL 會被編譯為D觸發器
always @ (posedge CLK or posedge RST) begin
if(RST)
CNTVAL <= 0;
else
CNTVAL <= cnt_next;
end

// 組合邏輯,生成OV
always @ (CNTVAL) begin
if(CNTVAL == CNT_MAX_VAL)
OV = 1;
else
OV = 0;
end

endmodule

模擬結果如下:
在這裡插入圖片描述
學生實驗
設計一個用於識別2進位制序列“1011”的狀態機
基本要求:
電路每個時鐘週期輸入1位元資料,當捕獲到1011的時鐘週期,電路輸出1,否則輸出0
使用序列101011010作為輸出的測試序列
擴充套件要求:
給你的電路新增輸入使能埠,只有輸入使能EN為1的時鐘週期,才從輸入的資料埠向內部獲取1位元序列資料。

基本要求實驗程式碼如下:
module zhuangtaiji(
CLK , // clock
RST , // reset
CENT1IN , // input 1 cent coin
TINOUT ); // output 1 tin cola

input CLK ;
input RST ;
input CENT1IN ;
output TINOUT ;

parameter ST_0_CENT = 0;
parameter ST_1_CENT = 1;
parameter ST_2_CENT = 2;
parameter ST_3_CENT = 3;
parameter ST_4_CENT = 4;

reg [4-2:0]stateR ;
reg [4-2:0]next_state ;
reg TINOUT ;

// calc next state
always @ (CENT1IN or stateR) begin
case (stateR)
ST_0_CENT :begin if(CENT1IN) next_state = ST_1_CENT ; else next_state = ST_0_CENT; end
ST_1_CENT :begin if(CENT1IN) next_state = ST_2_CENT ; else next_state = ST_0_CENT; end
ST_2_CENT :begin if(CENT1IN) next_state = ST_3_CENT ; else next_state = ST_0_CENT; end
ST_3_CENT :begin if(CENT1IN) next_state = ST_4_CENT ; else next_state = ST_0_CENT; end
ST_4_CENT :begin next_state = ST_0_CENT;end
endcase
end

// calc output
always @ (stateR) begin
if(stateR == ST_4_CENT)
TINOUT = 1’b1;
else
TINOUT = 1’b0;
end

// state DFF
always @ (posedge CLK or posedge RST)begin
if(RST)
stateR <= ST_0_CENT;
else
stateR <= next_state;
end

endmodule

擴充套件要求實驗程式碼如下:
module shinengzhuangtaiji(
CLK , // clock
RST , // reset
CENT1IN , // input 1 cent coin
EN ,
TINOUT ); // output 1 tin cola

input CLK ;
input RST ;
input CENT1IN ;
input EN;
output TINOUT ;

parameter ST_0_CENT = 0;
parameter ST_1_CENT = 1;
parameter ST_2_CENT = 2;
parameter ST_3_CENT = 3;
parameter ST_4_CENT = 4;

reg [4-2:0]stateR ;
reg [4-2:0]next_state ;
reg TINOUT ;

// calc next state
always @ (CENT1IN or stateR) begin
if(EN)begin
case (stateR)
ST_0_CENT :begin if(CENT1IN) next_state = ST_1_CENT ; else next_state = ST_0_CENT; end
ST_1_CENT :begin if(CENT1IN) next_state = ST_2_CENT ; else next_state = ST_0_CENT; end
ST_2_CENT :begin if(CENT1IN) next_state = ST_3_CENT ; else next_state = ST_0_CENT; end
ST_3_CENT :begin if(CENT1IN) next_state = ST_4_CENT ; else next_state = ST_0_CENT; end
ST_4_CENT :begin next_state = ST_0_CENT;end
endcase
end
else
if(next_state!=ST_0_CENT)
next_state = ST_0_CENT;
end

// calc output
always @ (stateR) begin
if(stateR == ST_4_CENT)
TINOUT = 1’b1;
else
TINOUT = 1’b0;
end

// state DFF
always @ (posedge CLK or posedge RST)begin
if(RST)
stateR <= ST_0_CENT;
else
stateR <= next_state;
end

endmodule

學生實驗
設計一個如本節“電路描述”部分的“帶載入使能和移位使能的併入串出”的移位暫存器,電路的RTL結構圖如“電路描述”部分的RTL結構圖所示。

實驗程式碼如下:
module yiweijicunqi(
RST ,
CLK ,
LOAD ,
EN ,
IN ,
OUT );

input RST, CLK, EN,LOAD;
input [3:0]IN;
output OUT;
reg [3:0] shift_R;
reg OUT;

always @ (posedge CLK or posedge RST or posedge LOAD) begin
if(RST)
shift_R[3:0] <= 0;
else begin
if(LOAD) begin
shift_R[3:0] <= IN[3:0];
end
else begin
if(EN) begin
OUT = shift_R[3];
shift_R[3:1] <= shift_R[2:0];
shift_R[0] <= 0;
end
else begin
shift_R[3:0] <= shift_R[3:0];
end
end
end
end
endmodule

RTL Viewer:
在這裡插入圖片描述