FPGA Prototyping By Verilog Examples第四章 常用时序电路设计

通用移位寄存器

通用移位寄存器可以载入并行数据,左移,右移,保持;它能够实现并-串功能(先载入并行数据后移位),也可实现串并功能(先移位后并行输出)。

  
  
// Listing 4.8
module univ_shift_reg
#(
parameter N = 8 )
(
input wire clk, reset,
input wire [ 1 : 0 ] ctrl,
input wire [N - 1 : 0 ] d,
output wire [N - 1 : 0 ] q
);

// signal declaration
reg [N - 1 : 0 ] r_reg, r_next;

// body
// register
always @( posedge clk, posedge reset)
if (reset)
r_reg
<= 0 ;
else
r_reg
<= r_next;

// next-state logic
always @ *
case (ctrl)
2 ' b00: r_next = r_reg; // no op
2 ' b01: r_next = {r_reg[N-2:0], d[0]}; // shift left
2 ' b10: r_next = {d[N-1], r_reg[N-1:1]}; // shift right
default : r_next = d; // load
endcase
// output logic
assign q = r_reg;

endmodule

通用二进制计数器

FPGA Prototyping By Verilog Examples第四章 常用时序电路设计_第1张图片

  
  
module univ_bin_counter
#(
parameter N = 8 )
(
input wire clk, reset,
input wire syn_clr, load, en, up,
input wire [N - 1 : 0 ] d,
output wire max_tick, min_tick,
output wire [N - 1 : 0 ] q
);

// signal declaration
reg [N - 1 : 0 ] r_reg, r_next;

// body
// register
always @( posedge clk, posedge reset)
if (reset)
r_reg
<= 0 ; //
else
r_reg
<= r_next;

// next-state logic
always @ *
if (syn_clr)
r_next
= 0 ;
else if (load)
r_next
= d;
else if (en & up)
r_next
= r_reg + {{(N-1){1'b0}},1'b1};
else if (en & ~ up)
r_next
= r_reg - {{(N-1){1'b0}},1'b1};
else
r_next
= r_reg;

// output logic
assign q = r_reg;
assign max_tick = (r_reg == {N{ 1 ' b1}}) ? 1 ' b1 : 1 ' b0;
assign min_tick = (r_reg == {N{ 1 ' b0}}) ? 1 ' b1 : 1 ' b0;

endmodule

测试文件

  
  
`timescale 1 ns / 10 ps

// The `timescale directive specifies that
// the simulation time unit is 1 ns and
// the simulator timestep is 10 ps

module bin_counter_tb();

// declaration
localparam T = 20 ; // clock period
reg clk, reset;
reg syn_clr, load, en, up;
reg [ 2 : 0 ] d;
wire max_tick, min_tick;
wire [ 2 : 0 ] q;

// uut instantiation
univ_bin_counter #(.N( 3 )) uut
(.clk(clk), .reset(reset), .syn_clr(syn_clr),
.load(load), .en(en), .up(up), .d(d),
.max_tick(max_tick), .min_tick(min_tick), .q(q));

// clock
// 20 ns clock running forever
always
begin
clk
= 1 ' b1;
#(T / 2 );
clk
= 1 ' b0;
#(T / 2 );
end

// reset for the first half cycle
initial
begin
reset
= 1 ' b1;
#(T / 2 );
reset
= 1 ' b0;
end

// other stimulus
initial
begin
// ==== initial input =====
syn_clr = 1 ' b0;
load = 1 ' b0;
en = 1 ' b0;
up = 1 ' b1; // count up
d = 3 ' b000;
@( negedge reset); // wait reset to deassert
@( negedge clk); // wait for one clock
// ==== test load =====
load = 1 ' b1;
d = 3 ' b011;
@( negedge clk); // wait for one clock
load = 1 ' b0;
repeat ( 2 ) @( negedge clk);
// ==== test syn_clear ====
syn_clr = 1 ' b1; // assert clear
@( negedge clk);
syn_clr
= 1 ' b0;
// ==== test up counter and pause ====
en = 1 ' b1; // count
up = 1 ' b1;
repeat ( 10 ) @( negedge clk);
en
= 1 ' b0; // pause
repeat ( 2 ) @( negedge clk);
en
= 1 ' b1;
repeat ( 2 ) @( negedge clk);
// ==== test down counter ====
up = 1 ' b0;
repeat ( 10 ) @( negedge clk);
// ==== wait statement ====
// continue until q=2
wait (q == 2 );
@(
negedge clk);
up
= 1 ' b1;
// continue until min_tick becomes 1
@( negedge clk);
wait (min_tick);
@(
negedge clk);
up
= 1 ' b0;
// ==== absolute delay ====
#( 4 * T); // wait for 80 ns
en = 1 ' b0; // pause
#( 4 * T); // wait for 80 ns
// ==== stop simulation ====
// return to interactive simulation mode
$stop;
end
endmodule

FPGA Prototyping By Verilog Examples第四章 常用时序电路设计_第2张图片

通用模m计数器

相似命题讨论:

http://www.cnblogs.com/yuphone/archive/2010/12/26/1917395.html

  
  
module mod_m_counter
#(
parameter N = 4 , // number of bits in counter
M = 10 // mod-M
)
(
input wire clk, reset,
output wire max_tick,
output wire [N - 1 : 0 ] q
);

// signal declaration
reg [N - 1 : 0 ] r_reg;
wire [N - 1 : 0 ] r_next;

// body
// register
always @( posedge clk, posedge reset)
if (reset)
r_reg
<= 0 ;
else
r_reg
<= r_next;

// next-state logic
assign r_next = (r_reg == (M - 1 )) ? 0 : r_reg + 1 ;
// output logic
assign q = r_reg;
assign max_tick = (r_reg == (M - 1 )) ? 1 ' b1 : 1 ' b0;

endmodule

一种自动计算N的实现:

  
  
module mod_m_counter_fc
#(
parameter M = 10 ) // mod-M
(
input wire clk, reset,
output wire max_tick,
output wire [log2(M) - 1 : 0 ] q
);

// signal declaration
localparam N = log2(M); // number of bits for M
reg [N - 1 : 0 ] r_reg;
wire [N - 1 : 0 ] r_next;

// body
// register
always @( posedge clk, posedge reset)
if (reset)
r_reg
<= 0 ;
else
r_reg
<= r_next;

// next-state logic
assign r_next = (r_reg == (M - 1 )) ? 0 : r_reg + 1 ;
// output logic
assign q = r_reg;
assign max_tick = (r_reg == (M - 1 )) ? 1 ' b1 : 1 ' b0;

// log2 constant function
function integer log2( input integer n);
integer i;
begin
log2
= 1 ;
for (i = 0 ; 2 ** i < n; i = i + 1 )
log2
= i + 1 ;
end
endfunction

endmodule

基于循环队列的FIFO设计

http://www.cnblogs.com/yuphone/archive/2010/12/22/1913500.html

  
  
module fifo
#(
parameter B = 8 , // number of bits in a word
W = 3 // number of address bits
)
(
// global clock and aysn reset
input clk,
input rst_n,
// fifo interface
// fifo control signnal
input rd,
input wr,
// fifo status signal
output empty,
output full,
// fifo data bus
input [B - 1 : 0 ] w_data,
output reg [B - 1 : 0 ] r_data,
output reg [W: 0 ] cnt
);

// signal declaration
reg [B - 1 : 0 ] array_reg [ 2 ** W - 1 : 0 ]; // register array
reg [W - 1 : 0 ] w_ptr_reg, w_ptr_next, w_ptr_succ;
reg [W - 1 : 0 ] r_ptr_reg, r_ptr_next, r_ptr_succ;
reg full_reg, empty_reg, full_next, empty_next;
wire wr_en,rd_en;

// body
// register file write operation
// register file read operation
always @( posedge clk)
if (wr_en)
begin
array_reg[w_ptr_reg]
<= w_data;
cnt
<= cnt + 1 ' b1;
end
else if (rd_en)
begin
r_data
<= array_reg[r_ptr_reg];
cnt
<= cnt - 1 ' b1;
end
// write enabled only when FIFO is not full
assign wr_en = wr & ~ full_reg;
// write enabled only when FIFO is not empty
assign rd_en = rd & ~ empty_reg;
// fifo control logic
// register for read and write pointers
always @( posedge clk, negedge rst_n)
if ( ! rst_n)
begin
cnt
<= 0 ;
w_ptr_reg
<= 0 ;
r_ptr_reg
<= 0 ;
full_reg
<= 1 ' b0;
empty_reg <= 1 ' b1;
end
else
begin
w_ptr_reg
<= w_ptr_next;
r_ptr_reg
<= r_ptr_next;
full_reg
<= full_next;
empty_reg
<= empty_next;
end

// next-state logic for read and write pointers
always @ *
begin
// successive pointer values
w_ptr_succ = w_ptr_reg + 1 ;
r_ptr_succ
= r_ptr_reg + 1 ;
// default: keep old values
w_ptr_next = w_ptr_reg;
r_ptr_next
= r_ptr_reg;
full_next
= full_reg;
empty_next
= empty_reg;
case ({wr, rd})
// 2'b00: no op
2 ' b01: // read
if ( ~ empty_reg) // not empty
begin
r_ptr_next
= r_ptr_succ;
full_next
= 1 ' b0;
if (r_ptr_succ == w_ptr_reg)
empty_next
= 1 ' b1;
end
2 ' b10: // write
if ( ~ full_reg) // not full
begin
w_ptr_next
= w_ptr_succ;
empty_next
= 1 ' b0;
if (w_ptr_succ == r_ptr_reg)
full_next
= 1 ' b1;
end
2 ' b11: // write and read
begin
w_ptr_next
= w_ptr_succ;
r_ptr_next
= r_ptr_succ;
end
endcase
end

// output
assign full = full_reg;
assign empty = empty_reg;

endmodule

测试文件:

  
  
`timescale 1ns / 1ns

module fifo_tb;
localparam T = 20 ; // clock period
// global clock and asyn reset
reg clk, rst_n;
// fifo interface
reg rd, wr;
wire empty, full;
reg [ 7 : 0 ] w_data;
wire [ 7 : 0 ] r_data;
wire [ 3 : 0 ] cnt;
// fifo instantiation
fifo #(.B( 8 ), .W( 3 )) fifo_inst
(
.clk(clk), .rst_n(rst_n),
.rd(rd), .wr(wr),
.empty(empty), .full(full),
.w_data(w_data), .r_data(r_data),
.cnt(cnt)
);


// clcok
always
begin
clk
= 1 ' b0;
#(T / 2 );
clk
= 1 ' b1;
#(T / 2 );
end


// reset
initial
begin
rst_n
= 1 ' b0;
#(T / 2 )
rst_n
= 1 ' b1;
end


// stimulus body
initial
begin
// initial input; empty
rd = 0 ; wr = 0 ; w_data = 8 ' h00;
@( posedge rst_n); // wait to deassert rst_n
@( negedge clk); // wait for a clock
// 1 write
wr = 1 ; w_data = 8 ' h11;
@( negedge clk); // wait to assert wr
wr = 0 ;
@(
negedge clk); // wait to deassert wr
// 3 writes
wr = 1 ;
repeat ( 3 )
begin
w_data
= w_data + 8 ' h11;
@( negedge clk);
end
wr
= 0 ;
@(
negedge clk);
// 1 read
rd = 1 ;
@(
negedge clk); // wait to assert rd
rd = 0 ;
@(
negedge clk) // wait to deassert rd
// 4 writes
wr = 1 ;
repeat ( 4 )
begin
w_data
= w_data + 8 ' h11;
@( negedge clk);
end
wr
= 0 ;
@(
negedge clk);
// 1 write; full
wr = 1 ; w_data = 8 ' hAA;
@( negedge clk);
wr
= 0 ;
@(
negedge clk);
// 2 reads
rd = 1 ;
repeat ( 2 ) @( negedge clk);
rd
= 0 ;
@(
negedge clk);
// 5 reads
rd = 1 ;
repeat ( 5 ) @( negedge clk);
rd
= 0 ;
@(
negedge clk);
// 1 read; empty
rd = 1 ;
@(
negedge clk);
rd
= 0 ;
@(
negedge clk);
$stop;
end

endmodule

FPGA Prototyping By Verilog Examples第四章 常用时序电路设计_第3张图片

FIFO的另一种实现方式:

  
  
module fifo
#(
parameter stack_width = 8 , // 位宽
stack_height = 8 , // 深度,即数据总量
stack_ptr_width = 4 , // 指针宽度
AE_level = 2 ,
AF_level
= 6 ,
HF_level
= 4
)
(
output reg [stack_width - 1 : 0 ] Data_out,
output stack_full,stack_almost_full,stack_half_full,
output stack_almost_empty,stack_empty,
input [stack_width - 1 : 0 ] Data_in,
input wr,rd,
input clk,rst
);

reg [stack_ptr_width - 1 : 0 ] rd_ptr,wr_ptr; // 指针间读写间隔的地址
reg [stack_ptr_width: 0 ] ptr_gap;
reg [stack_width - 1 : 0 ] stack[stack_height - 1 : 0 ]; // 存储器阵列

//堆栈状态信号
assign stack_full = (ptr_gap == stack_height);
assign stack_almost_full = (ptr_gap == AF_level);
assign stack_half_full = (ptr_gap == HF_level);
assign stack_almost_empty = (ptr_gap == AE_level);
assign stack_empty = (ptr_gap == 0 );

always @ ( posedge clk, negedge rst)
if ( ! rst)
begin
Data_out
<= 0 ;
rd_ptr
<= 0 ;
wr_ptr
<= 0 ;
ptr_gap
<= 0 ;
end
else if (wr && ( ! rd) && ( ! stack_full))
begin
stack[wr_ptr]
<= Data_in;
wr_ptr
<= wr_ptr + 1 ' b1;
ptr_gap <= ptr_gap + 1 ' b1;
end
else if (( ! wr) && (rd) && ( ! stack_empty))
begin
Data_out
<= stack[rd_ptr];
rd_ptr
<= rd_ptr + 1 ' b1;
ptr_gap <= ptr_gap - 1 ' b1;
end
else if ((wr) && (rd) && (stack_empty))
begin
stack[wr_ptr]
<= Data_in;
wr_ptr
<= wr_ptr + 1 ' b1;
ptr_gap <= ptr_gap + 1 ' b1;
end
else if ((wr) && (rd) && (stack_full))
begin
Data_out
<= stack[rd_ptr];
rd_ptr
<= rd_ptr + 1 ' b1;
ptr_gap <= ptr_gap - 1 ' b1;
end
else if ((wr) && (rd) && ( ! stack_full) && ( ! stack_empty))
begin
Data_out
<= stack[rd_ptr];
stack[wr_ptr]
<= Data_in;
rd_ptr
<= rd_ptr + 1 ' b1;
wr_ptr <= wr_ptr + 1 ' b1;
end
endmodule

测试文件:

  
  
`timescale 1ns / 1ns

module fifo_tb;
localparam T = 20 ; // clock period
// global clock and asyn reset
reg clk, rst_n;
// fifo interface
reg rd, wr;
wire empty, full;
reg [ 7 : 0 ] w_data;
wire [ 7 : 0 ] r_data;
wire stack_almost_full,stack_half_full,stack_almost_empty;
// fifo instantiation
fifo #(.stack_height( 8 ), .stack_ptr_width( 3 )) fifo_inst
(
.clk(clk), .rst(rst_n),
.rd(rd), .wr(wr),
.stack_empty(empty), .stack_full(full),
.stack_almost_full(stack_almost_full),
.stack_half_full(stack_half_full),
.stack_almost_empty(stack_almost_empty),
.Data_in(w_data), .Data_out(r_data)
);


// clcok
always
begin
clk
= 1 ' b0;
#(T / 2 );
clk
= 1 ' b1;
#(T / 2 );
end


// reset
initial
begin
rst_n
= 1 ' b0;
#(T / 2 )
rst_n
= 1 ' b1;
end


// stimulus body
initial
begin
// initial input; empty
rd = 0 ; wr = 0 ; w_data = 8 ' h00;
@( posedge rst_n); // wait to deassert rst_n
@( negedge clk); // wait for a clock
// 1 write
wr = 1 ; w_data = 8 ' h11;
@( negedge clk); // wait to assert wr
wr = 0 ;
@(
negedge clk); // wait to deassert wr
// 3 writes
wr = 1 ;
repeat ( 3 )
begin
w_data
= w_data + 8 ' h11;
@( negedge clk);
end
wr
= 0 ;
@(
negedge clk);
// 1 read
rd = 1 ;
@(
negedge clk); // wait to assert rd
rd = 0 ;
@(
negedge clk) // wait to deassert rd
// 4 writes
wr = 1 ;
repeat ( 4 )
begin
w_data
= w_data + 8 ' h11;
@( negedge clk);
end
wr
= 0 ;
@(
negedge clk);
// 1 write; full
wr = 1 ; w_data = 8 ' hAA;
@( negedge clk);
wr
= 0 ;
@(
negedge clk);
// 2 reads
rd = 1 ;
repeat ( 2 ) @( negedge clk);
rd
= 0 ;
@(
negedge clk);
// 5 reads
rd = 1 ;
repeat ( 5 ) @( negedge clk);
rd
= 0 ;
@(
negedge clk);
// 1 read; empty
rd = 1 ;
@(
negedge clk);
rd
= 0 ;
@(
negedge clk);
$stop;
end

endmodule

FPGA Prototyping By Verilog Examples第四章 常用时序电路设计_第4张图片

Stack的设计

module stack
#(
  parameter B=8, // number of bits in a word
            W=3  // number of address bits
)
(
  // global clock and aysn reset
  input clk, 
  input rst_n,
  // stack interface
  //  stack control signnal
  input rd, 
  input wr,
  //  stack status signal
  output empty, 
  output full,
  // stack data bus
  input [B-1:0] w_data,
  output wire [B-1:0] r_data,
  output reg [W:0] top,
  output wire wr_en,rd_en,
  output reg [W:0] rd_ptr
);

// signal declaration
reg [B-1:0] array_reg [2**W-1:0];  // register array
wire full_reg, empty_reg;
//reg rpt;

assign r_data =(rd_en&clk)?array_reg[rd_ptr-1]:r_data;
// body   
always @(posedge clk,negedge rst_n)
  if(!rst_n)
    top <= 4'd0;
  else 
  begin
      case({wr_en,rd_en})
          2'b01:  //read
          begin
            rd_ptr   <= top;  
            top    <= top -1'b1;
          end
          2'b10:  //write
          begin
             top             <= top + 1'b1; 
             array_reg[top]  <= w_data;
          end
          2'b11:
          begin
              top <=top +1'b1;
              array_reg[top]  <= w_data;
              rd_ptr    <= top;
              top <= top - 1'b1;
              
          end
          default:;
       endcase
  end
  
// write enabled only when FIFO is not full
assign wr_en = wr & ~full_reg;
// write enabled only when FIFO is not empty
assign rd_en = rd & ~empty_reg;
// stack control logic
// register for read and write pointers
assign full_reg  = (top=={1'b1,{W{1'b0}}})? 1:0;
assign empty_reg = (top=={1'b0,{W{1'b0}}})? 1:0;
// output
assign full  = full_reg;
assign empty = empty_reg;

endmodule

测试文件

`timescale 1ns/1ns

module stack_tb;
localparam T=20; // clock period
// global clock and asyn reset
reg clk, rst_n;
// fifo interface
reg rd, wr;
wire rd_en,wr_en;
wire empty, full;
reg [7:0] w_data;
wire [7:0] r_data;
wire  [3:0] top;
wire  [3:0] rd_ptr;
// stack instantiation
stack #(.B(8), .W(3)) fifo_inst
(
  .clk(clk), .rst_n(rst_n),
  .rd(rd), .wr(wr),
  .empty(empty), .full(full),
  .w_data(w_data), .r_data(r_data),
  .top(top),.rd_en(rd_en),.wr_en(wr_en),
  .rd_ptr(rd_ptr)
);


// clcok
always
begin
  clk = 1'b0; 
  #(T/2);
  clk = 1'b1;
  #(T/2);
end


// reset
initial
begin
  rst_n = 1'b0;
  #(T/2)
  rst_n = 1'b1;
end


// stimulus body
initial 
begin
  // initial input; empty
  rd=0; wr=0; w_data=8'h00;
  @(posedge rst_n); // wait to deassert rst_n
  @(negedge clk); // wait for a clock
  // 1 write
  wr=1; w_data=8'h11;
  @(negedge clk); // wait to assert wr
  wr=0;
  @(negedge clk); // wait to deassert wr
  // 3 writes
  wr=1;
  repeat(3)
  begin
    w_data=w_data+8'h11;
    @(negedge clk); 
  end
  wr=0;
  @(negedge clk);
  // 1 read
  rd=1;
  @(negedge clk); // wait to assert rd
  //@(negedge clk); // wait to assert rd
  rd=0;
  @(negedge clk) // wait to deassert rd
  // 4 writes
  wr=1;
  repeat(4)
  begin
    w_data=w_data+8'h11;
    @(negedge clk);
  end
  wr=0;
  @(negedge clk); 
  // 1 write; full
  wr=1; w_data=8'hAA;
  @(negedge clk); 
  wr=0;
  @(negedge clk);
  // 2 reads
  rd=1;
  repeat(2) @(negedge clk);
  rd=0; 
  @(negedge clk);
  // 5 reads
  rd=1;
  repeat(5) @(negedge clk);
  rd=0;
  @(negedge clk);
  // 1 read; empty
  rd=1;
  @(negedge clk);
  rd=0;
  @(negedge clk);
  $stop;
end

endmodule

FPGA Prototyping By Verilog Examples第四章 常用时序电路设计_第5张图片

代码改进如下,也可以实现同样的功能:

module stack
#(
  parameter B=8, // number of bits in a word
            W=3  // number of address bits
)
(
  // global clock and aysn reset
  input clk, 
  input rst_n,
  // stack interface
  //  stack control signnal
  input rd, 
  input wr,
  //  stack status signal
  output empty, 
  output full,
  // stack data bus
  input [B-1:0] w_data,
  output reg [B-1:0] r_data,
  output reg [W:0] top,
  output wire wr_en,rd_en
);

// signal declaration
reg [B-1:0] array_reg [2**W-1:0];  // register array
wire full_reg, empty_reg;

assign r_data =(rd_en&clk)?array_reg[top]:r_data;
// body   
always @(posedge clk,negedge rst_n)
  if(!rst_n)
    top <= 4'd0;
  else 
  begin
      case({wr_en,rd_en})
          2'b01:  //read
          begin
            top    <= top -1'b1;
          end
          2'b10:  //write
          begin
             array_reg[top]  <= w_data;
             top             <= top + 1'b1; 
          end
          2'b11:
          begin    
              array_reg[top]  <= w_data;
          end
          default:;
       endcase
  end
  
// write enabled only when FIFO is not full
assign wr_en = wr & ~full_reg;
// write enabled only when FIFO is not empty
assign rd_en = rd & ~empty_reg;
// stack control logic
// register for read and write pointers
assign full_reg  = (top=={1'b1,{W{1'b0}}})? 1:0;
assign empty_reg = (top=={1'b0,{W{1'b0}}})? 1:0;
// output
assign full  = full_reg;
assign empty = empty_reg;

endmodule

FPGA Prototyping By Verilog Examples第四章 常用时序电路设计_第6张图片

你可能感兴趣的:(example)