mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-28 07:02:55 +08:00
295 lines
7.4 KiB
Verilog
295 lines
7.4 KiB
Verilog
// Copyright 2007 Altera Corporation. All rights reserved.
|
|
// Altera products are protected under numerous U.S. and foreign patents,
|
|
// maskwork rights, copyrights and other intellectual property laws.
|
|
//
|
|
// This reference design file, and your use thereof, is subject to and governed
|
|
// by the terms and conditions of the applicable Altera Reference Design
|
|
// License Agreement (either as signed by you or found at www.altera.com). By
|
|
// using this reference design file, you indicate your acceptance of such terms
|
|
// and conditions between you and Altera Corporation. In the event that you do
|
|
// not agree with such terms and conditions, you may not use the reference
|
|
// design file and please promptly destroy any copies you have made.
|
|
//
|
|
// This reference design file is being provided on an "as-is" basis and as an
|
|
// accommodation and therefore all warranties, representations or guarantees of
|
|
// any kind (whether express, implied or statutory) including, without
|
|
// limitation, warranties of merchantability, non-infringement, or fitness for
|
|
// a particular purpose, are specifically disclaimed. By making this reference
|
|
// design file available, Altera expressly does not recommend, suggest or
|
|
// require that this reference design file be used in combination with any
|
|
// other product not provided by Altera.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// baeckler - 06-30-2006
|
|
|
|
////////////////////////////////////////////
|
|
// Register with ENA and SCLR
|
|
////////////////////////////////////////////
|
|
module sclr_ena_reg (
|
|
clk,
|
|
rst,
|
|
d,
|
|
ena,
|
|
sclr,
|
|
q
|
|
);
|
|
|
|
parameter METHOD = 1;
|
|
|
|
input clk,rst,d,ena,sclr;
|
|
output q;
|
|
reg q;
|
|
|
|
generate
|
|
if (METHOD == 0)
|
|
begin
|
|
//////////////////////
|
|
// soft register
|
|
//////////////////////
|
|
always @(posedge clk or posedge rst) begin
|
|
if (rst) q <= 0;
|
|
else begin
|
|
if (ena) begin
|
|
if (sclr) q <= 0;
|
|
else q <= d;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
//////////////////////
|
|
// WYSIWYG register
|
|
//////////////////////
|
|
wire q_internal;
|
|
stratixii_lcell_ff r (
|
|
.clk(clk),
|
|
.ena(ena),
|
|
.datain (d),
|
|
.sload (1'b0),
|
|
.adatasdata (1'b1),
|
|
.sclr (sclr),
|
|
.aload(1'b0),
|
|
.aclr(rst),
|
|
// These are simulation-only chipwide
|
|
// reset signals. Both active low.
|
|
// synthesis translate_off
|
|
.devpor(1'b1),
|
|
.devclrn(1'b1),
|
|
// synthesis translate on
|
|
.regout (q_internal)
|
|
);
|
|
always @(q_internal) q = q_internal;
|
|
end
|
|
endgenerate
|
|
endmodule
|
|
|
|
|
|
////////////////////////////////////////////
|
|
// Gray counter register block
|
|
////////////////////////////////////////////
|
|
module gray_cntr_la_reg (
|
|
clk,
|
|
rst,
|
|
ena,
|
|
adv_lower, // count the LSB
|
|
adv_upper, // count bits 1..n
|
|
sclr,
|
|
q
|
|
);
|
|
|
|
parameter METHOD = 1;
|
|
|
|
input clk,rst,ena,adv_lower,adv_upper,sclr;
|
|
output [4:0] q;
|
|
wire [4:0] q;
|
|
reg [4:0] d;
|
|
|
|
// do the D logic for a basic gray counter
|
|
always @(*) begin
|
|
d[0] = q[0] ^ adv_lower;
|
|
d[1] = q[1] ^ (adv_upper & q[0]);
|
|
d[2] = q[2] ^ (adv_upper & !q[0] & q[1]);
|
|
d[3] = q[3] ^ (adv_upper & !q[0] & !q[1] & q[2]);
|
|
d[4] = q[4] ^ (adv_upper & !q[0] & !q[1] & !q[2] & q[3]);
|
|
end
|
|
|
|
// install a register array
|
|
genvar i;
|
|
generate
|
|
for (i=0; i<5; i=i+1)
|
|
begin : rg
|
|
sclr_ena_reg r (
|
|
.clk(clk),.rst(rst),.d(d[i]),.ena(ena),.sclr(sclr),
|
|
.q(q[i])
|
|
);
|
|
defparam r .METHOD = METHOD;
|
|
end
|
|
endgenerate
|
|
|
|
endmodule
|
|
|
|
////////////////////////////////////////////
|
|
// Gray counter using lookahead to get
|
|
// 1 LUT depth
|
|
////////////////////////////////////////////
|
|
module gray_cntr_la (
|
|
clk,
|
|
rst,
|
|
ena,
|
|
sclr,
|
|
q
|
|
);
|
|
|
|
// method 0 - for simulation / portability
|
|
// method 1 - make the register secondarys very explicit
|
|
parameter METHOD = 1;
|
|
|
|
// width of the output in bits
|
|
// must be 6 or higher
|
|
parameter WIDTH = 6;
|
|
|
|
// number of 5 bit blocks of counter width, round up to next size
|
|
localparam BLOCKS = ((WIDTH % 5) != 0) ? (WIDTH / 5) + 1 : (WIDTH / 5);
|
|
|
|
// number of bits not used at the MSB end of the top block
|
|
localparam SHORT_BITS = ((WIDTH % 5) != 0) ? 5-(WIDTH % 5) : 0;
|
|
|
|
input clk,rst,ena,sclr;
|
|
output [BLOCKS*5-1:0] q;
|
|
|
|
initial begin
|
|
if (WIDTH < 6) begin
|
|
$display ("WIDTH less than 6 requires modification of wrap circuitry");
|
|
$stop();
|
|
end
|
|
end
|
|
|
|
// internal use sclr signal, to add the wrapping condition
|
|
wire sclr_int /* synthesis keep */;
|
|
|
|
wire [5*BLOCKS-1:0] q;
|
|
wire [BLOCKS-1:0] block_zero; // q = 00000
|
|
wire [BLOCKS-1:0] block_max; // q = 10000
|
|
wire [BLOCKS-1:0] adv_lower; // count the LSB
|
|
wire [BLOCKS-1:0] adv_upper; // count the other bits
|
|
|
|
// set up an alternation between LSB increments
|
|
// and the higher bits
|
|
sclr_ena_reg ping_r (
|
|
.clk(clk),.rst(rst),
|
|
.d(!ping),
|
|
.ena(ena),.sclr(sclr_int),
|
|
.q(ping));
|
|
defparam ping_r .METHOD = METHOD;
|
|
|
|
// the main counter register blocks
|
|
genvar i;
|
|
generate
|
|
for (i=0; i<BLOCKS; i=i+1)
|
|
begin : gryrg
|
|
wire [4:0] block_q;
|
|
gray_cntr_la_reg r (
|
|
.clk(clk),
|
|
.rst(rst),
|
|
.ena(ena),
|
|
.adv_lower(adv_lower[i]),
|
|
.adv_upper(adv_upper[i]),
|
|
.sclr(sclr_int),
|
|
.q(block_q)
|
|
);
|
|
defparam r .METHOD = METHOD;
|
|
|
|
assign q[(i+1)*5-1:i*5] = block_q;
|
|
|
|
// registered comparators
|
|
// for == 0 and == MAX value (10000)
|
|
if (i != 0) begin
|
|
sclr_ena_reg cmp_z (
|
|
.clk(clk),.rst(rst),
|
|
.d(~| block_q),
|
|
.ena(ena),.sclr(sclr_int),
|
|
.q(block_zero[i]));
|
|
defparam cmp_z .METHOD = METHOD;
|
|
|
|
// trim down the MAX number on the
|
|
// highest block if not all of the bits are
|
|
// used.
|
|
sclr_ena_reg cmp_m (
|
|
.clk(clk),.rst(rst),
|
|
.d( (i != (BLOCKS-1)) ?
|
|
(block_q == 5'b10000) :
|
|
(((block_q << SHORT_BITS) & 5'b11111)
|
|
== 5'b10000)),
|
|
.ena(ena),.sclr(sclr_int),
|
|
.q(block_max[i]));
|
|
defparam cmp_m .METHOD = METHOD;
|
|
end
|
|
end
|
|
endgenerate
|
|
|
|
// block_zero and block_max [0] aren't actually used, force them to VCC
|
|
// so that the advance logic looks better
|
|
assign block_zero[0] = 1'b1;
|
|
assign block_max[0] = 1'b1;
|
|
|
|
// block 0 advance signals are easy
|
|
assign adv_lower[0] = !ping;
|
|
assign adv_upper[0] = ping;
|
|
|
|
// block 1 advance signals need to be available 1 cycle
|
|
// ahead of time for blocks 2...
|
|
// compare lowest block to 00011
|
|
wire leading_adv_upper1;
|
|
sclr_ena_reg lead_r (
|
|
.clk(clk),.rst(rst),
|
|
.d(ping & !q[4] & !q[3] & !q[2] & q[1] & q[0]),
|
|
.ena(ena),.sclr(sclr_int),
|
|
.q(leading_adv_upper1));
|
|
defparam lead_r .METHOD = METHOD;
|
|
|
|
// compare lowest block to 00001
|
|
sclr_ena_reg up1_r (
|
|
.clk(clk),.rst(rst),
|
|
.d(!ping & !q[4] & !q[3] & !q[2] & !q[1] & q[0]),
|
|
.ena(ena),.sclr(sclr_int),
|
|
.q(adv_upper[1]));
|
|
defparam up1_r .METHOD = METHOD;
|
|
|
|
// compare lowest block to 10001
|
|
sclr_ena_reg lo1_r (
|
|
.clk(clk),.rst(rst),
|
|
.d(!ping & q[4] & !q[3] & !q[2] & !q[1] & q[0]),
|
|
.ena(ena),.sclr(sclr_int),
|
|
.q(adv_lower[1]));
|
|
defparam lo1_r .METHOD = METHOD;
|
|
|
|
// blocks 2 and up are repeats
|
|
generate
|
|
for (i=2; i<BLOCKS; i=i+1)
|
|
begin : adv
|
|
// when to advance the lower portion
|
|
sclr_ena_reg advl_r (
|
|
.clk(clk),.rst(rst),
|
|
.d(leading_adv_upper1 & block_max[i-1] & (&block_zero[i-2:0])),
|
|
.ena(ena),.sclr(sclr_int),
|
|
.q(adv_lower[i]));
|
|
defparam advl_r .METHOD = METHOD;
|
|
|
|
// when to advance the upper portion
|
|
sclr_ena_reg advu_r (
|
|
.clk(clk),.rst(rst),
|
|
.d(leading_adv_upper1 & block_zero[i-1] & (&block_zero[i-2:0])),
|
|
.ena(ena),.sclr(sclr_int),
|
|
.q(adv_upper[i]));
|
|
defparam advu_r .METHOD = METHOD;
|
|
end
|
|
endgenerate
|
|
|
|
// additional SCLR condition when the counter is
|
|
// completely maxed. Otherwise it would wait one cycle too
|
|
// long to wrap.
|
|
assign sclr_int = sclr | (adv_upper[BLOCKS-1] & block_max[BLOCKS-1]);
|
|
|
|
endmodule
|
|
|