Verilog ----基礎6
【例9.1】基本門電路的幾種描述方法
(1)門級結構描述
module
gate1(F,A,B,C,D);
input A,B,C,D;
output F;
nand (F1,A,B); //調用門元件
and (F2,B,C,D);
or (F,F1,F2);
endmodule
(2 )資料流程描述
module gate2(F,A,B,C,D);
input A,B,C,D;
output F;
assign
F=(A&B)|(B&C&D);
//assign持續賦值
endmodule
(3 )行為描述
module gate3(F,A,B,C,D);
input A,B,C,D;
output F;
reg
F;
always @(A or B or C or D) //過程賦值
begin
F=(A&B)|(B&C&D);
end
endmodule
【例9.2 】用bufif1 關鍵字描述的三態門
module tri_1(in,en,out);
input in,en;
output out;
tri out;
bufif1 b1(out,in,en); //注意三態門埠的排列順序
endmodule
【例9.3 】用assign 語句描述的三態門
module tri_2(out,in,en);
output out;
input in,en;
assign out = en ? in : 'bz;
//若en=1,則out=in;若en=0,則out 為高阻態
endmodule
【例9.4 】三態雙向驅動器
module bidir(tri_inout,out,in,en,b);
inout tri_inout;
output out;
input in,en,b;
assign tri_inout = en ? in : 'bz;
assign out = tri_inout ^ b;
endmodule
【例9.5 】三態雙向驅動器
module bidir2(bidir,en,clk);
inout [7:0] bidir;
input en,clk;
reg [7:0] temp;
assign bidir= en ? temp : 8'bz;
always @(posedge clk)
begin
if (en)
temp=bidir;
else
temp=temp+1;
end
endmodule
【例9.6 】3-8 解碼器
module decoder_38(out,in);
output [7:0] out;
input [2:0] in;
reg [7:0] out;
always @(in)
begin
case (in)
3'd0: out=8'b11111110;
3'd1: out=8'b11111101;
3'd2: out=8'b11111011;
3'd3: out=8'b11110111;
3'd4: out=8'b11101111;
3'd5: out=8'b11011111;
3'd6: out=8'b10111111;
3'd7: out=8'b01111111;
endcase
end
endmodule
【例9.7 】8-3 優先編碼器
module
encoder8_3(none_on,outcode,a,b,c,d,e,f,g,h);
output none_on;
output [2:0] outcode;
input a,b,c,d,e,f,g,h;
reg [3:0] outtemp;
assign {none_on,outcode}=outtemp;
always @(a or b or c or d or e or f or g or h)
begin
if (h) outtemp=4'b0111;
else if (g) outtemp=4'b0110;
else if (f) outtemp=4'b0101;
else if (e) outtemp=4'b0100;
else if (d) outtemp=4'b0011;
else if (c) outtemp=4'b0010;
else if (b)
outtemp=4'b0001;
else if (a) outtemp=4'b0000;
else outtemp=4'b1000;
end
endmodule
【例9.8】用函數定義的8-3 優先編碼器
module code_83(din, dout);
input [7:0] din;
output
[2:0] dout;
function[2:0] code; //函數定義
input [7:0] din; //函數只有輸入埠,輸出為函數名本身
if (din[7]) code = 3'd7;
else if (din[6]) code = 3'd6;
else if (din[5]) code = 3'd5;
else if (din[4]) code = 3'd4;
else if (din[3]) code = 3'd3;
else if (din[2]) code = 3'd2;
else if (din[1]) code = 3'd1;
else code = 3'd0;
endfunction
assign
dout = code(din); //函數調用
endmodule
【例9.9 】七段數碼管解碼器
module
decode47(a,b,c,d,e,f,g,D3,D2,D1,D0);
output a,b,c,d,e,f,g;
input D3,D2,D1,D0; //輸入的4位BCD碼
reg
a,b,c,d,e,f,g;
always @(D3 or D2 or D1 or D0)
begin
case ({D3,D2,D1,D0}) //用case語句進行解碼
4'd0: {a,b,c,d,e,f,g}=7'b1111110;
4'd1: {a,b,c,d,e,f,g}=7'b0110000;
4'd2: {a,b,c,d,e,f,g}=7'b1101101;
4'd3: {a,b,c,d,e,f,g}=7'b1111001;
4'd4: {a,b,c,d,e,f,g}=7'b0110011;
4'd5: {a,b,c,d,e,f,g}=7'b1011011;
4'd6: {a,b,c,d,e,f,g}=7'b1011111;
4'd7: {a,b,c,d,e,f,g}=7'b1110000;
4'd8: {a,b,c,d,e,f,g}=7'b1111111;
4'd9: {a,b,c,d,e,f,g}=7'b1111011;
default: {a,b,c,d,e,f,g}=7'bx;
endcase
end
endmodule
【例9.10】奇偶校驗位產生器
module parity(even_bit,odd_bit,input_bus);
output even_bit,odd_bit;
input [7:0] input_bus;
assign odd_bit = ^ input_bus; //產生奇校驗位
assign even_bit = ~odd_bit; //產生偶校驗位
endmodule
【例9.11】用if-else 語句描述的4
選 1 MUX
module
mux_if(out,in0,in1,in2,in3,sel);
output out;
input
in0,in1,in2,in3;
input [1:0] sel;
reg out;
always @(in0 or in1
or in2 or in3 or sel)
begin
if (sel==2'b00) out=in0;
else if (sel==2'b01) out=in1;
else if (sel==2'b10) out=in2;
else out=in3;
end
endmodule
【例9.12】用case 語句描述的4 選 1 MUX
module
mux_case(out,in0,in1,in2,in3,sel);
output out;
input
in0,in1,in2,in3;
input [1:0] sel;
reg out;
always @(in0 or in1
or in2 or in3 or sel)
begin
case (sel)
2'b00: out=in0;
2'b01: out=in1;
2'b10: out=in2;
default: out=in3;
endcase
end
endmodule
【例9.13】用組合電路實現的ROM
module rom(addr,data);
input [3:0] addr;
output [7:0] data;
function[7:0] romout;
input [3:0] addr;
case (addr)
0 : romout = 0;
1 : romout = 1;
2 : romout = 4;
3 : romout = 9;
4 : romout = 16;
5 : romout = 25;
6 : romout = 36;
7 : romout = 49;
8 : romout = 64;
9 : romout = 81;
10 : romout = 100;
11 : romout = 121;
12 : romout = 144;
13 : romout = 169;
14 : romout = 196;
15 : romout = 225;
default : romout = 8'hxx;
endcase
endfunction
assign data = romout(addr);
endmodule
【例9.14】基本D 觸發器
module DFF
(Q,D,CLK);
output Q;
input D,CLK;
reg Q;
always @(posedge
CLK)
begin
Q <= D;
end
endmodule
【例9.15】帶非同步清0、非同步置1 的D 觸發器
module DFF1
(q,qn,d,clk,set,reset);
input
d,clk,set,reset;
output q,qn;
reg q,qn;
always @(posedge
clk or negedge set or negedge reset)
begin
if (!reset) begin
q <= 0; //非同步清0,低電平有效
qn <= 1;
end
else if (!set) begin
q <= 1; //非同步置1,低電平有效
qn <= 0;
end
else
begin
q <= d;
qn <= ~d;
end
end
endmodule
【例9.16】帶同步清0、同步置1 的D 觸發器
module
DFF2(q,qn,d,clk,set,reset);
input
d,clk,set,reset;
output q,qn;
reg q,qn;
always @(posedge
clk)
begin
if
(reset) begin
q <= 0; qn <= 1; //同步清0,高電平有效
end
else if (set) begin
q <=1; qn <=0; //同步置1,高電平有效
end
else
begin
q <= d; qn <= ~d;
end
end
endmodule
【例9.17】帶非同步清0、非同步置1 的JK 觸發器
module JK_FF(CLK,J,K,Q,RS,SET);
input CLK,J,K,SET,RS;
output Q;
reg Q;
always @(posedge CLK or negedge RS or
negedge SET)
begin
if (!RS) Q <= 1'b0;
else if (!SET) Q <= 1'b1;
else case ({J,K})
2'b00 : Q <= Q;
2'b01 : Q <= 1'b0;
2'b10 : Q <= 1'b1;
2'b11 : Q <= ~Q;
default: Q<= 1'bx;
endcase
end
endmodule
【例9.18】電平敏感的1 位元資料鎖存器
module latch_1(q,d,clk);
output q;
input d,clk;
assign q = clk ? d : q; //時鐘信號為高電平時,將輸入端資料鎖存
endmodule
【例9.19】帶置位和復位端的1 位元數據鎖存器
module
latch_2(q,d,clk,set,reset);
output q;
input
d,clk,set,reset;
assign q = reset ?
0 : (set ? 1 : (clk ? d : q));
endmodule
【例9.20 】8 位元數據鎖存器
module
latch_8(qout,data,clk);
output [7:0] qout;
input [7:0] data;
input clk;
reg [7:0] qout;
always @(clk or
data)
begin
if (clk) qout<=data;
end
endmodule
【例9.21 】8 位元資料寄存器
module
reg8(out_data,in_data,clk,clr);
output[7:0] out_data;
input [7:0]
in_data;
input clk,clr;
reg [7:0] out_data;
always @(posedge
clk or posedge clr)
begin
if (clr)
out_data <=0;
else
out_data <=in_data;
end
endmodule
【例9.22 】8 位移位寄存器
module
shifter(din,clk,clr,dout);
input din,clk,clr;
output [7:0] dout;
reg [7:0] dout;
always @(posedge
clk)
begin
if (clr)
dout<= 8'b0; //同步清0,高電平有效
else
begin
dout <= dout << 1; //輸出信號左移一位元
dout[0] <= din; //輸入信號補充到輸出信號的最低位元
end
end
endmodule
【例9.23 】可變模加法/減法計數器
module updown_count(d,clk,clear,load,up_down,qd);
input [7:0] d;
input clk,clear,load;
input up_down;
output [7:0] qd;
reg [7:0] cnt;
assign qd = cnt;
always @(posedge clk)
begin
if
(!clear) cnt = 8'h00; //同步清0,低電平有效
else
if (load) cnt = d;
//同步預置
else
if (up_down) cnt = cnt + 1; //加法計數
else cnt = cnt - 1; //減法計數
end
endmodule
【例9.24 】4 位元Johnson 計數器(非同步重定)
module johnson(clk,clr,out);
input clk,clr;
output [3:0] out;
reg [3:0] out;
always @(posedge clk or posedge clr)
begin
if (clr) out<= 4'h0;
else
begin out<= out<< 1;
out[0]<= ~out[3];
end
end
endmodule
【例9.25 】256 ×8 RAM 模組
module
ram256x8(data,address,we,inclock,outclock,q);
input
[7:0] data;
input [7:0] address;
input we,inclock,outclock;
output [7:0] q;
lpm_ram_dq myram (.q(q),.data(data),.address(address),
.we(we),.inclock(inclock),.outclock(outclock));
defparam myram.lpm_width=8; //定義資料寬度
defparam myram.lpm_widthad=8; //定義地址寬度
endmodule
【例9.26 】256 ×16 RAM 塊
module
map_lpm_ram(dataout,datain,addr,we,inclk,outclk);
input [15:0] datain; //埠定義
input [7:0] addr;
input we,inclk,outclk;
output [15:0] dataout;
//lpm_ram_dq 元件例化
lpm_ram_dq ram(.data(datain),.address(addr),.we(we),.inclock(inclk),
.outclock(outclk),.q(dataout));
defparam ram.lpm_width=16; //參數賦值
defparam ram.lpm_widthad=8;
defparam ram.lpm_indata="REGISTERED";
defparam
ram.lpm_outdata="REGISTERED";
defparam
ram.lpm_file="map_lpm_ram.mif"; //RAM塊中的內容取自該檔
endmodule
【例9.27 】4 位串並轉換器
module serial_pal(clk,reset,en,in,out);
input clk,reset,en,in;
output [3:0] out;
reg
[3:0] out;
always @ (posedge clk)
begin
if (reset) out<=4'h0;
else if (en) out<={out,in}; //使用連接運算符
end
endmodule
【例9.28 】用函數實現簡單的處理器
module mpc(instr,out);
input [17:0] instr; //instr 為輸入的指令
output[8:0] out; //輸出結果
reg [8:0] out;
reg func;
reg [7:0] op1,op2; //從指令中提取的兩個運算元
function[16:0] code_add; //函數的定義
input [17:0] instr;
reg add_func;
reg [7:0] code,opr1,opr2;
begin
code=instr[17:16]; //輸入指令instr 的高2位元是操作碼
opr1=instr[7:0]; //輸入指令instr 的低8位元是運算元opr1
case (code)
2'b00:
begin
add_func=1;
opr2=instr[15:8]; //從instr 中取第二個運算元
end
2'b01:
begin
add_func=0;
opr2=instr[15:8]; //從instr 中取第二個運算元
end
2'b10:
begin
add_func=1;
opr2=8'd1; //第二個運算元取為1,實現+1操作
end
default:
begin
add_func=0;
opr2=8'd1; //實現-1操作
end
endcase
code_add={add_func,opr2,opr1};
end
endfunction
always @(instr)
begin
{func,op2,op1}=code_add(instr); //調用函數
if (func==1) out=op1+op2;
//實現兩數相加、運算元1加 1操作
else
out=op1-op2; //實現兩數相減、運算元1減1操作
end
endmodule
【例9.29 】微處理器的測試代碼
`timescale 10ns/1ns
`include "mpc.v"
module mpc_tp;
reg [17:0] instr;
wire [8:0] out;
parameter DELY=10;
mpc m1(instr,out); //調用待測試模組
initial begin
instr=18'd0;
#DELY
instr=18'b00_01001101_00101111;
#DELY instr=18'b00_11001101_11101111;
#DELY
instr=18'b01_01001101_11101111;
#DELY
instr=18'b01_01001101_00101111;
#DELY
instr=18'b10_01001101_00101111;
#DELY
instr=18'b11_01001101_00101111;
#DELY
instr=18'b00_01001101_00101111;
#DELY $finish;
end
initial
$monitor($time,,,"instr=%b out=%b",instr,out);
endmodule
【例9.30 】乘累加器(MAC )代碼
module
MAC(out,opa,opb,clk,clr);
output [15:0] out;
input [7:0]
opa,opb;
input clk,clr;
wire [15:0] sum;
reg [15:0] out;
function[15:0]
mult; //函數定義,mult 函數完成乘法操作
input [7:0]
opa,opb; //函數只能定義輸入端,輸出埠為函數名本身
reg [15:0] result;
integer i;
begin
result = opa[0]? opb : 0;
for (i= 1; i <= 7; i = i+1)
begin
if (opa[i]==1) result=result+(opb<<(i-1));
end
mult=result;
end
endfunction
assign sum=mult(opa,opb)+out;
always @(posedge clk or posedge clr)
begin
if (clr) out<=0;
else out<=sum;
end
endmodule
【例9.31 】乘累加器的測試代碼
'timescale 1ns/1ns
'include "mac.v"
module mac_tp;
reg [7:0] opa,opb; //測試輸入信號用reg 型變數
reg clr,clk;
wire [15:0] out; //測試輸出信號用wire 型變數
parameter DELY = 100;
//測試物件調用
MAC m1(out,opa,opb,clk,clr);
always #(DELY) clk = ~clk; //產生時鐘波形
initial begin //激勵波形定義
clr=1;clk=0;opa=8'd0; opb=8'd0;
#DELY clr=0;opa=8'd1; opb=8'd10;
#DELY opa=8'd2; opb=8'd10;
#DELY opa=8'd3; opb=8'd10;
#DELY opa=8'd4; opb=8'd10;
#DELY
opa=8'd5; opb=8'd10;
#DELY opa=8'd6; opb=8'd10;
#DELY opa=8'd7; opb=8'd10;
#DELY opa=8'd8; opb=8'd10;
#DELY opa=8'd9; opb=8'd10;
#DELY opa=8'd10; opb=8'd10;
#DELY $finish;
end
//結果顯示
initial
$monitor($time,,,"clr=%b opa=%d opb=%d out=%d",clr,opa,opb,out);
endmodule
沒有留言:
張貼留言