by yosikawa » 2011年2月12日(土) 17:09
Spartan 3E Starter Kit 最初の一歩の続き
簡単この上ない「ボタンを押したらLEDが点灯する」アプリはちゃんと動いた。
次はロータリスイッチを使ってみる。
手で回してみると、「くりっ、くりっ」という、いい感じで回る。マウスのホイールと似た感じ。
数えてみると、20段階で1回転する。つまり、1段階について18度ずつ認識する。
しかも、プッシュスイッチ機能も付いていて、つまみを押しこむとスイッチとしてOn/OFFも認識できる。
新しいプロジェクトを作成し、トップモジュールを作成する。
S3E_Rotary はロータリスイッチを処理するモジュール。
ロータリスイッチのA接点とB接点はアクティブローなので、モジュールへの入力で反転している。
このモジュールは、XilinxのサイトにあるRotary Encoder Interfaceを参考に作成した。
http://www.xilinx.com/products/boards/s3estarter/reference_designs.htm
ただし、書いてある通りに作ると左右の回転が逆になる。A接点、B接点がアクティブローであることも考慮されてないようだ。
多分、この資料が作られたときから、ハードの仕様が変更されたのだろう。間違いなので、修正した。
S3E_Rotary.v を以下のようにして作成する。
UCFファイルは、今回はいろんな接続が必要だ。以下のようにする。
完成。
今回作ったのは、最初に右端のLEDが1個だけ点灯し、
ロータリスイッチを回すと左右に動く。
8個の各スイッチを押すと対応するLEDが点灯。
ロータリスイッチを押しこむとLED全体が反転する。
簡単この上ない「ボタンを押したらLEDが点灯する」アプリはちゃんと動いた。
次はロータリスイッチを使ってみる。
手で回してみると、「くりっ、くりっ」という、いい感じで回る。マウスのホイールと似た感じ。
数えてみると、20段階で1回転する。つまり、1段階について18度ずつ認識する。
しかも、プッシュスイッチ機能も付いていて、つまみを押しこむとスイッチとしてOn/OFFも認識できる。
新しいプロジェクトを作成し、トップモジュールを作成する。
- コード:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 17:42:47 02/11/2011
// Design Name:
// Module Name: top
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`default_nettype none
module top(clk, led, switch, btn, rotary_a, rotary_b, rotary_press);
input wire clk; // グローバルクロック
input wire [3:0] switch; // スライドスイッチ
input wire [3:0] btn; // プッシュスイッチ (3:north, 2:east, 1:west, 0:south)
input wire rotary_a; // ロータリスイッチA接点(アクティブ・ロー)
input wire rotary_b; // ロータリスイッチB接点(アクティブ・ロー)
input wire rotary_press; // ロータリスイッチ・プッシュ
output wire [7:0] led; // LED
reg [1:0] reset_count;
always @(posedge clk) begin
if(&reset_count == 0)
reset_count <= reset_count + 1;
end
wire reset = reset_count[0]; // リセット信号。
wire rotary_event; // ロータリスイッチが1段階回転したとき、1パルスだけアクティブになる。
wire rotary_right; // rotary_event がアクティブのとき、回転方向を示す。ハイが右方向。
S3E_Rotary S3E_Rotary(clk, reset, ‾rotary_a, ‾rotary_b, rotary_event, rotary_right);
reg [7:0] led1;
wire [7:0] led2 = { btn, switch };
wire [7:0] led3 = led1 ^ led2;
always @(posedge clk or negedge reset) begin
if(!reset) begin
led1 <= 8'd1;
end else if(rotary_event) begin
if(rotary_right) begin
led1 <= { led1[0], led1[7:1] };
end else begin
led1 <= { led1[6:0], led1[7] };
end
end
end
assign led = rotary_press ? ‾led3 : led3;
endmodule
S3E_Rotary はロータリスイッチを処理するモジュール。
ロータリスイッチのA接点とB接点はアクティブローなので、モジュールへの入力で反転している。
このモジュールは、XilinxのサイトにあるRotary Encoder Interfaceを参考に作成した。
http://www.xilinx.com/products/boards/s3estarter/reference_designs.htm
ただし、書いてある通りに作ると左右の回転が逆になる。A接点、B接点がアクティブローであることも考慮されてないようだ。
多分、この資料が作られたときから、ハードの仕様が変更されたのだろう。間違いなので、修正した。
S3E_Rotary.v を以下のようにして作成する。
- コード:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 17:54:43 02/11/2011
// Design Name:
// Module Name: S3E_Rotary
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`default_nettype none
module S3E_Rotary(clk, reset, rotary_a, rotary_b, rotary_event, rotary_right);
input wire clk; // グローバルクロック
input wire reset; // システムリセット
input wire rotary_a; // ロータリスイッチA接点
input wire rotary_b; // ロータリスイッチB接点
output reg rotary_event; // ロータリスイッチが1段階回転したとき、1パルスだけアクティブになる。
output reg rotary_right; // rotary_event がアクティブのとき、回転方向を示す。ハイが右方向。
// rotary_q1;
// Set (‘1’) when A is High and B is High
// Reset (‘0’) when A is Low and B is Low.
// Remember current state in all other cases.
reg rotary_q1;
// rotary_q2
// Set (‘1’) when A is Low and B is High
// Reset (‘0’) when A is High and B is Low.
// Remember current state in all other cases.
reg rotary_q2;
always @(posedge clk or negedge reset) begin
if(!reset) begin
rotary_q1 <= 0;
rotary_q2 <= 0;
end else begin
case ({ rotary_a, rotary_b })
2'b00 : { rotary_q1, rotary_q2 } <= { 1'b0, rotary_q2 };
2'b01 : { rotary_q1, rotary_q2 } <= { rotary_q1, 1'b1 };
2'b10 : { rotary_q1, rotary_q2 } <= { rotary_q1, 1'b0 };
2'b11 : { rotary_q1, rotary_q2 } <= { 1'b1, rotary_q2 };
default: { rotary_q1, rotary_q2 } <= { rotary_q1, rotary_q2 };
endcase
end
end
// rotary_q1 のposedgeが、rotary_event になり、このときrotary_q2がrotary_rightになる。
reg rotary_q1_w;
always @(posedge clk or negedge reset) begin
if(!reset) begin
rotary_q1_w <= 0;
end else begin
rotary_q1_w <= rotary_q1;
end
end
always @(posedge clk or negedge reset) begin
if(!reset) begin
rotary_event <= 0;
rotary_right <= 0;
end else if(rotary_q1 & !rotary_q1_w) begin
rotary_event <= 1;
rotary_right <= rotary_q2;
end else begin
rotary_event <= 0;
rotary_right <= rotary_right;
end
end
endmodule
UCFファイルは、今回はいろんな接続が必要だ。以下のようにする。
- コード:
#
# Period constraint for 50MHz operation
#
NET "clk" PERIOD = 20.0ns HIGH 50%;
#
# soldered 50MHz Clock.
#
NET "clk" LOC = "C9" | IOSTANDARD = LVTTL;
#
#
# Simple LEDs
# Require only 3.5mA.
#
NET "led<0>" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<1>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<2>" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<3>" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<4>" LOC = "C11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<5>" LOC = "D11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<6>" LOC = "E9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<7>" LOC = "F9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
#
# Simple switches
# Pull UP resistors used to stop floating condition during switching.
#
NET "switch<0>" LOC = "L13" | IOSTANDARD = LVTTL | PULLUP;
NET "switch<1>" LOC = "L14" | IOSTANDARD = LVTTL | PULLUP;
NET "switch<2>" LOC = "H18" | IOSTANDARD = LVTTL | PULLUP;
NET "switch<3>" LOC = "N17" | IOSTANDARD = LVTTL | PULLUP;
#
#
# Press buttons
# Must have pull DOWN resistors to provide Low when not pressed.
#
# btn_north
NET "btn<3>" LOC = "V4" | IOSTANDARD = LVTTL | PULLDOWN;
# btn_west
NET "btn<2>" LOC = "D18" | IOSTANDARD = LVTTL | PULLDOWN;
# btn_south
NET "btn<1>" LOC = "K17" | IOSTANDARD = LVTTL | PULLDOWN;
# btn_east
NET "btn<0>" LOC = "H13" | IOSTANDARD = LVTTL | PULLDOWN;
#
# Rotary encoder.
# Rotation contacts require pull UP resistors to provide High level.
# Press contact requires pull DOWN resistor to provide Low when not pressed..
#
NET "rotary_a" LOC = "K18" | IOSTANDARD = LVTTL | PULLUP;
NET "rotary_b" LOC = "G18" | IOSTANDARD = LVTTL | PULLUP;
NET "rotary_press" LOC = "V16" | IOSTANDARD = LVTTL | PULLDOWN;
#
#
# End of File
#
完成。
今回作ったのは、最初に右端のLEDが1個だけ点灯し、
ロータリスイッチを回すと左右に動く。
8個の各スイッチを押すと対応するLEDが点灯。
ロータリスイッチを押しこむとLED全体が反転する。
0 件のコメント:
コメントを投稿