今天看看了Quatus II里面自带的Verilog写的一些基本模块的模板,感觉很受启发,觉得比任何一本书上讲的都要好,所以现在整理了一下常用的贴出来,需要查看完成的template,可以在Quartus的文件编辑窗口单击右键选择“insert template”。
l 单口RAM<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
// Quartus II Verilog Template
// Single port RAM with single read/write address
module single_port_ram
(
input [(DATA_WIDTH-1):0] data,
input [(ADDR_WIDTH-1):0] addr,
input we, clk,
output reg [(DATA_WIDTH-1):0] q
);
parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 6;
// Declare the RAM variable
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
always @ (posedge clk)
begin
// Write
if (we)
ram[addr] = data;
// Read returns NEW data at addr if we == 1'b1. This is the
// natural behavior of TriMatrix memory blocks in <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />SinglePort
// mode
q <= ram[addr];
end
endmodule
l 简单双口RAM单时钟
// Quartus II Verilog Template
// Simple Dual Port RAM with separate read/write addresses and
// single read/write clock
module simple_dual_port_ram_single_clock
(
input [(DATA_WIDTH-1):0] data,
input [(ADDR_WIDTH-1):0] read_addr, write_addr,
input we, clk,
output reg [(DATA_WIDTH-1):0] q
);
parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 6;
// Declare the RAM variable
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
always @ (posedge clk)
begin
// Write
if (we)
ram[write_addr] <= data;
// Read (if read_addr == write_addr, return OLD data). To return
// NEW data, use = (blocking write) rather than <= (non-blocking write)
// in the write assignment. NOTE: NEW data may require extra bypass
// logic around the RAM.
q <= ram[read_addr];
end
endmodule
l 简单双口RAM(双时钟)
// Quartus II Verilog Template
// Simple Dual Port RAM with separate read/write addresses and
// separate read/write clocks
module simple_dual_port_ram_dual_clock
(
input [(DATA_WIDTH-1):0] data,
input [(ADDR_WIDTH-1):0] read_addr, write_addr,
input we, read_clock, write_clock,
output reg [(DATA_WIDTH-1):0] q
);
parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 6;
// Declare the RAM variable
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
always @ (posedge write_clock)
begin
// Write
if (we)
ram[write_addr] <= data;
end
always @ (posedge read_clock)
begin
// Read
q <= ram[read_addr];
end
endmodule
l 完整的双口RAM(单时钟)
// Quartus II Verilog Template
// Simple Dual Port RAM with separate read/write addresses and
// separate read/write clocks
module simple_dual_port_ram_dual_clock
(
input [(DATA_WIDTH-1):0] data,
input [(ADDR_WIDTH-1):0] read_addr, write_addr,
input we, read_clock, write_clock,
output reg [(DATA_WIDTH-1):0] q
);
parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 6;
// Declare the RAM variable
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
always @ (posedge write_clock)
begin
// Write
if (we)
ram[write_addr] <= data;
end
always @ (posedge read_clock)
begin
// Read
q <= ram[read_addr];
end
endmodule
l 完整的双口RAM(双时钟)
// Quartus II Verilog Template
// True Dual Port RAM with dual clocks
module true_dual_port_ram_dual_clock
(
input [(DATA_WIDTH-1):0] data_a, data_b,
input [(ADDR_WIDTH-1):0] addr_a, addr_b,
input we_a, we_b, clk_a, clk_b,
output reg [(DATA_WIDTH-1):0] q_a, q_b
);
parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 6;
// Declare the RAM variable
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
always @ (posedge clk_a)
begin
// Port A
if (we_a)
begin
ram[addr_a] <= data_a;
q_a <= data_a;
end
else
begin
q_a <= ram[addr_a];
end
end
always @ (posedge clk_b)
begin
// Port B
if (we_b)
begin
ram[addr_b] <= data_b;
q_b <= data_b;
end
else
begin
q_b <= ram[addr_b];
end
end
endmodule
l 单口ROM
// Quartus II Verilog Template
// Single Port ROM
module single_port_rom
(
input [(ADDR_WIDTH-1):0] addr,
input clk,
output reg [(DATA_WIDTH-1):0] q
);
parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 6;
// Declare the ROM variable
reg [DATA_WIDTH-1:0] rom[2**ADDR_WIDTH-1:0];
// Initialize the ROM with $readmemb. Put the memory contents
// in the file single_port_rom_init.txt. Without this file,
// this design will not compile.
// See Verilog LRM 1364-2001 Section 17.2.8 for details on the
// format of this file.
initial
begin
$readmemb("single_port_rom_init.txt", rom);
end
always @ (posedge clk)
begin
q <= rom[addr];
end
endmodule
l 双口ROM
// Quartus II Verilog Template
// Dual Port ROM
module dual_port_rom
(
input [(ADDR_WIDTH-1):0] addr_a, addr_b,
input clk,
output reg [(DATA_WIDTH-1):0] q_a, q_b
);
parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 6;
// Declare the ROM variable
reg [DATA_WIDTH-1:0] rom[2**ADDR_WIDTH-1:0];
// Initialize the ROM with $readmemb. Put the memory contents
// in the file dual_port_rom_init.txt. Without this file,
// this design will not compile.
// See Verilog LRM 1364-2001 Section 17.2.8 for details on the
// format of this file.
initial
begin
$readmemb("dual_port_rom_init.txt", rom);
end
always @ (posedge clk)
begin
q_a <= rom[addr_a];
q_b <= rom[addr_b];
end
endmodule
l 无符号加法器
// Quartus II Verilog Template
// Unsigned Adder
module unsigned_adder
(
input [WIDTH-1:0] dataa,
input [WIDTH-1:0] datab,
input cin,
output [WIDTH:0] result
);
parameter WIDTH = 16;
assign result = dataa + datab + cin;
endmodule
l 有符号加法器
// Quartus II Verilog Template
// Signed adder
module signed_adder
(
input signed [WIDTH-1:0] dataa,
input signed [WIDTH-1:0] datab,
input cin,
output [WIDTH:0] result
);
parameter WIDTH = 16;
assign result = dataa + datab + cin;
endmodule
l 无符号乘法器
// Quartus II Verilog Template
// Unsigned multiply
module unsigned_multiply
(
input [WIDTH-1:0] dataa,
input [WIDTH-1:0] datab,
output [2*WIDTH-1:0] dataout
);
parameter WIDTH = 8;
assign dataout = dataa * datab;
endmodule
l 有符号乘法器
// Quartus II Verilog Template
// Signed multiply
module signed_multiply
(
input signed [WIDTH-1:0] dataa,
input signed [WIDTH-1:0] datab,
output [2*WIDTH-1:0] dataout
);
parameter WIDTH = 8;
assign dataout = dataa * datab;
endmodule
l 带输入输出寄存器的无符号乘法器
// Quartus II Verilog Template
// Unsigned multiply with input and output registers
module unsigned_multiply_with_input_and_output_registers
(
input clk,
input [WIDTH-1:0] dataa,
input [WIDTH-1:0] datab,
output reg [2*WIDTH-1:0] dataout
);
parameter WIDTH = 8;
// Declare input and output registers
reg [WIDTH-1:0] dataa_reg;
reg [WIDTH-1:0] datab_reg;
wire [2*WIDTH-1:0] mult_out;
// Store the result of the multiply
assign mult_out = dataa_reg * datab_reg;
// Update data
always @ (posedge clk)
begin
dataa_reg <= dataa;
datab_reg <= datab;
dataout <= mult_out;
end
endmodule
l 带输入输出的有符号乘法器
// Quartus II Verilog Template
// Signed multiply with input and output registers
module signed_multiply_with_input_and_output_registers
(
input clk,
input signed [WIDTH-1:0] dataa,
input signed [WIDTH-1:0] datab,
output reg signed [2*WIDTH-1:0] dataout
);
parameter WIDTH = 8;
// Declare input and output registers
reg signed [WIDTH-1:0] dataa_reg;
reg signed [WIDTH-1:0] datab_reg;
wire signed [2*WIDTH-1:0] mult_out;
// Store the result of the multiply
assign mult_out = dataa_reg * datab_reg;
// Update data
always @ (posedge clk)
begin
dataa_reg <= dataa;
datab_reg <= datab;
dataout <= mult_out;
end
endmodule
l 无符号乘加器
// Quartus II Verilog Template
// Unsigned multiply-accumulate
module unsigned_multiply_accumulate
(
input clk, aclr, clken, sload,
input [WIDTH-1:0] dataa,
input [WIDTH-1:0] datab,
output reg [4*WIDTH-1:0] adder_out
);
parameter WIDTH = 8;
// Declare registers and wires
reg [4*WIDTH-1:0] old_result;
wire [2*WIDTH-1:0] multa;
// Store the results of the operations on the current data
assign multa = dataa * datab;
// Store the value of the accumulation (or clear it)
always @ (adder_out, sload)
begin
if (sload)
old_result <= 0;
else
old_result <= adder_out;
end
// Clear or update data, as appropriate
always @ (posedge clk or posedge aclr)
begin
if (aclr)
begin
adder_out <= 0;
end
else if (clken)
begin
adder_out <= old_result + multa;
end
end
endmodule
l 有符号乘加器
(略)
l 基本移位寄存器
// Quartus II Verilog Template
// One-bit wide, N-bit long shift register
module basic_shift_register
(
input clk, enable,
input sr_in,
output sr_out
);
parameter N = 64;
// Declare the shift register
reg [N-1:0] sr;
// Shift everything over, load the incoming bit
always @ (posedge clk)
begin
if (enable == 1'b1)
begin
sr[N-1:1] <= sr[N-2:0];
sr[0] <= sr_in;
end
end
// Catch the outgoing bit
assign sr_out = sr[N-1];
endmodule
l Mealy状态机
// Quartus II Verilog Template
// 4-State Mealy state machine
// A Mealy machine has outputs that depend on both the state and
// the inputs. When the inputs change, the outputs are updated
// immediately, without waiting for a clock edge. The outputs
// can be written more than once per state or per clock cycle.
module four_state_mealy_state_machine
(
input clk, in, reset,
output reg [1:0] out
);
// Declare state register
reg [1:0]state;
// Declare states
parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3;
// Determine the next state synchronously, based on the
// current state and the input
always @ (posedge clk or posedge reset) begin
if (reset)
state <= S0;
else
case (state)
S0:
if (in)
begin
state <= S1;
end
else
begin
state <= S1;
end
S1:
if (in)
begin
state <= S2;
end
else
begin
state <= S1;
end
S2:
if (in)
begin
state <= S3;
end
else
begin
state <= S1;
end
S3:
if (in)
begin
state <= S2;
end
else
begin
state <= S3;
end
endcase
end
// Determine the output based only on the current state
// and the input (do not wait for a clock edge).
always @ (state or in)
begin
case (state)
S0:
if (in)
begin
out = 2'b00;
end
else
begin
out = 2'b10;
end
S1:
if (in)
begin
out = 2'b01;
end
else
begin
out = 2'b00;
end
S2:
if (in)
begin
out = 2'b10;
end
else
begin
out = 2'b01;
end
S3:
if (in)
begin
out = 2'b11;
end
else
begin
out = 2'b00;
end
endcase
end
endmodule
l Moor状态机
// Quartus II Verilog Template
// 4-State Moore state machine
// A Moore machine's outputs are dependent only on the current state.
// The output is written only when the state changes. (State
// transitions are synchronous.)
module four_state_moore_state_machine
(
input clk, in, reset,
output reg [1:0] out
);
// Declare state register
reg [1:0]state;
// Declare states
parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3;
// Output depends only on the state
always @ (state) begin
case (state)
S0:
out = 2'b01;
S1:
out = 2'b10;
S2:
out = 2'b11;
S3:
out = 2'b00;
default:
out = 2'b00;
endcase
end
// Determine the next state
always @ (posedge clk or posedge reset) begin
if (reset)
state <= S0;
else
case (state)
S0:
state <= S1;
S1:
if (in)
state <= S2;
else
state <= S1;
S2:
if (in)
state <= S3;
else
state <= S1;
S3:
if (in)
state <= S2;
else
state <= S3;
endcase
end
endmodule
l 流水线加法树
// Quartus II Verilog Template
// Pipelined binary adder tree
module pipelined_binary_adder_tree
(
input [WIDTH-1:0] A, B, C, D, E,
input clk,
output [WIDTH-1:0] out
);
parameter WIDTH = 16;
wire [WIDTH-1:0] sum1, sum2, sum3, sum4;
reg [WIDTH-1:0] sumreg1, sumreg2, sumreg3, sumreg4;
always @ (posedge clk)
begin
sumreg1 <= sum1;
sumreg2 <= sum2;
sumreg3 <= sum3;
sumreg4 <= sum4;
end
// 2-bit additions
assign sum1 = A + B;
assign sum2 = C + D;
assign sum3 = sumreg1 + sumreg2;
assign sum4 = sumreg3 + E;
assign out = sumreg4;
endmodule
l 三态缓冲器(完成双向口的输入输出)
// When tri-state buffers are output enabled, they output a value.
// Otherwise their "output" is set to high-impedence.
inout <bidir_variable>;
assign <bidir_variable> = (<output_enable> ? <data> : 1'bZ);
l 三态寄存器
// Tri-state registers are registers on inout ports. As with any
// registers, their output can be updated synchronously or asynchronously.
inout reg <bidir_variable>;
always @ (posedge <clock_signal> or negedge <asynch_output_enable>)
begin
if (!<asynch_output_enable>)
begin
<bidir_variable> <= 1'bZ;
end
else
begin
<bidir_variable> <= (<output_enable>) ? <data> : 1'bZ;
end
end
l 双向I/O
module bidirectional_io (input <output_enable>, input [WIDTH-1:0] <data>, inout [WIDTH-1:0] <bidir_variable>, output [WIDTH-1:0] <read_buffer>);
parameter WIDTH = 4;
// If we are using the bidir as an output, assign it an output value,
// otherwise assign it high-impedence
assign <bidir_variable> = (<output_enable> ? <data> : {WIDTH{1'bz}});
// Read in the current value of the bidir port, which comes either
// from the input or from the previous assignment.
assign <read_buffer> = <bidir_variable>;
endmodule
l 综合属性
1. 保持属性
// Prevents Quartus II from minimizing or removing a particular
// signal net during combinational logic optimization. Apply
// the attribute to a net or variable declaration.
(* keep *) wire <net_name>;
(* keep *) reg <variable_name>;
2. 保护属性
// Prevents Quartus II from optimizing away a register. Apply
// the attribute to the variable declaration for an object that infers
// a register.
(* preserve *) <variable_declaration>;
(* preserve *) module <module_name>(...);
l ALTERA原语
1. 缓冲器
u LCELL LCELL <instance_name> (.in(<data_in>), .out(<data_out>));
文章评论(0条评论)
登录后参与讨论