by yosikawa » 2011年2月12日(土) 21:08
これまで作ったものは、ボタンなどに反応するものの、動きがない。
操作しなくても動き続けるようなものを作ってみる。
top.v :
Prescaler.v :
Prescaler_Enabled.v :
操作しなくても動き続けるようなものを作ってみる。
top.v :
- コード:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 19:43:29 02/12/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);
// 1KHz の内部クロックを作成する。
// 分周比 50MHz / 50000 = 1KHz
parameter integer CLK1MS_SCALE = 50000; // 分周比
defparam prescaler1.SCALE = CLK1MS_SCALE;
wire clk1ms; // 1ms 内部クロック
Prescaler prescaler1(
clk, // 入力クロック
reset, // リセット
clk1ms // 分周結果。シングルパルス。
);
// 10Hz の内部クロックを作成する。
parameter integer CLK250MS_SCALE = 100; // 分周比
defparam prescaler2.SCALE = CLK250MS_SCALE;
wire clk100ms; // 100ms 内部クロック
Prescaler_Enabled prescaler2(clk, reset, clk1ms, clk100ms);
// ナイトライダーみたいに、左右に動く表示を作成する。
reg [7:0] led1;
reg led_dir; // 動く方向。1:右、0:左
always @(posedge clk or negedge reset) begin
if(!reset) begin
led1 <= 8'd1;
led_dir <= 0;
end else if(clk100ms) begin
if(led_dir) begin
// 右に動く
if(led1[0]) begin
led_dir <= 0;
end else begin
led1 <= { 1'b0, led1[7:1] };
end
end else begin
// 左に動く
if(led1[7]) begin
led_dir <= 1;
end else begin
led1 <= { led1[6:0], 1'b0 };
end
end
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
// ボタンが押された部分は反転する。
wire [7:0] led2 = { btn, switch };
wire [7:0] led3 = led1 ^ led2;
assign led = rotary_press ? ‾led3 : led3;
endmodule
Prescaler.v :
- コード:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 11:17:49 02/07/2011
// Design Name:
// Module Name: Prescaler
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`default_nettype none
module Prescaler(
input wire clk, // 入力クロック
input wire reset, // リセット
output reg prescaled // 分周結果。シングルパルス。
);
parameter integer SCALE = 2; // 分周比。最低2。
function integer get_width(input integer value);
integer v2;
begin
v2 = value;
for(get_width = 0; v2 > 0; get_width = get_width + 1) begin
v2 = v2 >> 1;
end
end
endfunction
parameter count_width = get_width(SCALE - 1);
reg [count_width - 1:0] count;
always @(posedge clk or negedge reset) begin
if(!reset) begin
count <= 0;
prescaled <= 0;
end else if(count == (SCALE - 1'b1)) begin
count <= 0;
prescaled <= 1;
end else begin
count <= count + 1;
prescaled <= 0;
end
end
endmodule
Prescaler_Enabled.v :
- コード:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 17:28:51 02/08/2011
// Design Name:
// Module Name: Prescaler_Enabled
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`default_nettype none
module Prescaler_Enabled(
input wire clk, // 入力クロック
input wire reset, // リセット
input wire enable, // 分周元信号。1パルスだけアクティブになる信号でなければならない。
output reg prescaled // 分周結果。シングルパルス。
);
parameter integer SCALE = 2; // 分周比。最低2。
function integer get_width(input integer value);
integer v2;
begin
v2 = value;
for(get_width = 0; v2 > 0; get_width = get_width + 1) begin
v2 = v2 >> 1;
end
end
endfunction
parameter count_width = get_width(SCALE - 1);
reg [count_width - 1:0] count;
always @(posedge clk or negedge reset) begin
if(!reset) begin
count <= 0;
prescaled <= 0;
end else if(enable) begin
if(count == (SCALE - 1'b1)) begin
count <= 0;
prescaled <= 1;
end else begin
count <= count + 1;
prescaled <= 0;
end
end else begin
prescaled <= 0;
end
end
endmodule
0 件のコメント:
コメントを投稿