Under-Construction Verilog 自習帳>代表的な回路の書き方

目次


セレクタの書き方

△目次
function [9:0]selector;
	input [1:0] sel;
  	input [9:0] in_a;
  	input [9:0] in_b;

	case ( sel )
    		2'b00 : selector = in_a;
		2'b01 : selector = in_b;
		2'b10 : selector = in_a - in_b;
		2'b11 : selector = (in_a - in_b) << 2;
  	endcase
endfunction

assign out_w = selector(SEL, out_cnt_in, out_cnt_ref);
△目次

カウンタの書き方

△目次
input CNT;
input RST;
input CLK;
output [9:0] OUT_P;

reg [1:0] cnt_1;
reg [9:0] count;

always @(posedge CLK) begin
	if (RST) begin          // sync reset
		count <= 10'b0;     // because NOT TO ASSIGNED TO GCLRn
	end else begin
		if (cnt_1 == 2'b01)  // rising edge
			count <= count + 1;
	end
end
assign OUT_P = count;
△目次

エッジ検出の方法

△目次
input CLK;
input CNT;
reg [1:0] cnt_1;
always @(posedge CLK)
	cnt_1 <= {cnt_1[0], CNT};
△目次

分周器の書き方

△目次
output OUT_CLK;
input CLK;
// normal divider
reg [10:0]regs;
always @(posedge CLK) begin
	if (regs) begin
		regs <= regs - 1;
	end
	else begin
		regs <= 1843;	
	end
end
assign OUT_CLK = regs[10];

デューティ比を希望するときは(ローカルクロックなど)は、 カウンタリセットと同時に出力するか(レジスタが1個増える)か、リセット条件をデコードしてやる(リダクション演算子が便利)必要があるでしょう。たぶん、後者がお徳です。

output OUT_CLK;
reg OUT_CLK;
always @(posedge CLK) begin
	if (regs) begin
		regs <= regs - 1;
		OUT_CLK <= 0;
	end
	else begin
		regs <= 1843;	
		OUT_CLK <= 1;
	end
end
always @(posedge CLK) begin
	if (regs) begin
		regs <= regs - 1;
	end
	else begin
		regs <= 1843;	
	end
end
assign OUT_CLK = ~|regs;
△目次

フラクショナル・デバイダ(分数比分周器)

△目次
// fractional divider
reg [17:0]regs;
wire [7:0]add;

always @(posedge CLK) begin
	if (regs > 18'b11111_11111_11111_111)
		regs <= 0;
	else
		regs <= regs + add;	
end

assign OUT_CLK = regs[17];
△目次

近藤靖浩