verilog事始め(sample#4 @Gowin RUNBER board)
2021/12/13
初版
verilog事始め(sample#4 @Gowin RUNBER board)
verilog事始め(sample#4 @Gowin RUNBER board)
概要
本記事は「verilog事始め(Gowin RUNBER board で始める)」の続きとしてverilogの追加サンプルを紹介したものである。
sample#4(stopwatch)
例として、sample#3をベースに以下を追加して、stopwatchを実現する。
(一部、インタフェースの付録のものを参考にした)
top_stopwatch.v
module top_stopwatch (
input clk,
input [7:0] sw,
input [7:0] btn,
output [7:0] seg,
output [3:0] seg_dig,
output [7:0] led
);
wire rst, key1, key2;
wire tgl, zrst;
// all LEDs off
// assign led = 8'b0000_0000;
// for binary to BCD convert
reg [3:0] ones, tens, huns, thous;
integer i;
wire [7:0] seg_a, seg_b, seg_c, seg_d;
wire [3:0] a, b, c, d;
reg [3:0] tim_a, tim_b, tim_c, tim_d;
reg [15:0] timer_count;
assign a = {sw[0],sw[1],sw[2],sw[3]};
assign b = {sw[4],sw[5],sw[6],sw[7]};
assign c = ~{btn[0],btn[1],btn[2],btn[3]};
assign d = ~{btn[4],btn[5],btn[6],btn[7]};
wire clk0_1s;
clkdiv(.clk(clk), .rst(1'b0), .max(24'd119999_99), .tc(clk0_1s));
debounce dbnc_1 (.clk(clk), .rst(rst), .key_in(btn[0]), .key_out(key1));
debounce dbnc_2 (.clk(clk), .rst(rst), .key_in(btn[7]), .key_out(key2));
toggle tgl_2 (.clk(clk), .rst(rst), .in(key2), .out(tgl));
assign led[3] = ~key1; // for debug
assign zrst = ~key1;
assign led[7] = ~tgl; // for debug
always @ (posedge(clk0_1s))
begin
if (tgl == 1'b1) begin
timer_count = timer_count + 1;
end else begin
if (zrst == 1'b1) begin
timer_count = 16'd00;
end
end
//<<---------------------------------------------------
// binary to BCD convert
// algorithm reference:
// https://bravo-fpga.blogspot.com/2010/10/bin2bcd_29.html
//reg [3:0] ones, tens, huns, thous;
//integer i;
thous = 0;
huns = 0;
tens = 0;
ones = 0;
for(i=15; i>=0; i=i-1) begin
{thous, huns, tens, ones} = {thous[2:0],huns,tens,ones,timer_count[i]};
if(ones >= 5 && i > 0) ones = ones + 3;
if(tens >= 5 && i > 0) tens = tens + 3;
if(huns >= 5 && i > 0) huns = huns + 3;
if(thous >= 5 && i > 0) thous = thous + 3;
end
//>>---------------------------------------------------
// case1: binary to BCD
tim_a <= thous;
tim_b <= huns;
tim_c <= tens;
tim_d <= ones;
// case2: hex counter
/*
tim_a <= timer_count[15:12];
tim_b <= timer_count[11:8];
tim_c <= timer_count[7:4];
tim_d <= timer_count[3:0];
*/
end /* always */
drv7seg seg_1 (.in(tim_a), .dp(1'b0), .seg(seg_a)); // leftmost digit
drv7seg seg_2 (.in(tim_b), .dp(1'b0), .seg(seg_b));
drv7seg seg_3 (.in(tim_c), .dp(1'b1), .seg(seg_c));
drv7seg seg_4 (.in(tim_d), .dp(1'b0), .seg(seg_d));
mux7seg mux7seg_1 (
.clk(clk),
.seg_a(seg_a),
.seg_b(seg_b),
.seg_c(seg_c),
.seg_d(seg_d),
.seg(seg),
.seg_dig(seg_dig)
);
endmodule
debounce.v
module debounce (
input clk,
input rst,
input key_in,
output key_out
);
//reg [3:0] key_n;
reg [7:0] key_n;
wire clk400Hz;
clkdiv clkdiv_1 (.clk(clk), .rst(rst), .max(2999), .tc(clk400Hz));
always @(posedge(clk400Hz) or posedge(rst))
begin
if (rst == 1'b1) begin
key_n = 4'd0;
end else begin
key_n[7] <= key_n[6];
key_n[6] <= key_n[5];
key_n[5] <= key_n[4];
key_n[4] <= key_n[3];
//
key_n[3] <= key_n[2];
key_n[2] <= key_n[1];
key_n[1] <= key_n[0];
key_n[0] <= key_in;
end
end
assign key_out = & key_n; // key_n[1] | key_n[2] | key_n[3]
endmodule
toggle.v
module toggle (
input clk, rst, in,
output reg out
);
reg prev_in;
always @(posedge rst or posedge clk)
begin
if (rst == 1'b1) begin
out <= 1'b0;
prev_in <= 1'b0;
end else begin
prev_in <= in;
if ({prev_in, in} == 2'b10)
out <= ~out;
else
out <= out;
end
end /* always */
endmodule
仕様:
stopwatch
(1)最右端のボタンは、start/stopになっており、トグルになっている。
(2)最左端のボタンは、resetになっており、stop状態で押すと、カウンターがゼロになる。
(3)7セグメントLEDの最右端は、0.1秒のカウンターになっている。
課題:
・7セグメント表示のリフレッシュタイミングが不適切なようで、
最右端の7セグメントLEDは、スムーズに表示できていない。
・タイマー精度は、あまり高くない。
・bib2bcdは、moduleのままでは、文法エラーで組み込むことができなかったので、
top_stopwatch.vの本体に組み込んだ。
参照情報
verilog samples:
神のBIN2BCD
【問題1】 Verilog HDLをマスターしよう!!
【問題2】 4ビット加算器をVerilog HDLで記述しよう
【問題11】 パラメタライズによる回路の記述
Verilog Full Adder
ボード関係:
Gowin RUNBER FPGA Development Board
RUNBER Development Board - Hardware Instructions
RUNBER Development Board - Instructions for Experiments
Gowin_device&Software User Guide
Gowin_RUNBER_BOARD Source Code
Runber_Development_Board_Schematics
GOWIN RUMBERのLチカを階層に分割してみる
linuxツール関係:
GOWIN GW1N-UV4LQ144C6/I5を動かす
verilog関係:
Verilog-HDL入門
Verilog入門(alwaysなど)
Getting Started with a free Verilog Simulator
Icarus Verilog - Getting Started
Icarus Verilogの導入とAND回路のシミュレーション
Icarus Verilogコンパイラを使う
Tools関連:
Analyzer Oscilloscopeの使い方
Tang Nanoで内部信号のモニタリング
以上
| 固定リンク
「verilog」カテゴリの記事
- verilog事始め(sample#4 @Gowin RUNBER board)(2021.12.13)
- Gowin Analyzer Oscilloscope の使い方(2021.12.01)
- verilog事始め(Gowin RUNBER board で始める)(2021.11.24)
- verilog事始め(Tang Primer board で始める)(2021.11.14)
この記事へのコメントは終了しました。
コメント