`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Engineer: GPH // // Description: This demo programs takes data from the ADXL362 and displays // the X,Y data in sign magnitude format on the hex display // // The SPI interface with the ADXL362 control is from Digilent // ////////////////////////////////////////////////////////////////////////////////// module labkit( input clk_100mhz, input[15:0] sw, input btnc, btnu, btnl, btnr, btnd, input [7:0] jb, output logic led16_b, led16_g, led16_r, output logic led17_b, led17_g, led17_r, output logic [15:0] led, output logic ca, cb, cc, cd, ce, cf, cg, dp, // segments a-g, dp output logic[7:0] an, // Display location 0-7 output acl_sclk, output acl_mosi, input acl_miso, output acl_csn ); logic [31:0] data; // instantiate 7-segment display; display (8) 4-bit hex logic [6:0] segments; logic dp; assign {cg, cf, ce, cd, cc, cb, ca} = segments[6:0]; display_8hex_accel display(.clk_in(clk_100mhz),.data_in(data), .seg_out(segments), .strobe_out(an), .dp(dp)); assign led = sw; // turn leds on // ------------------------------------------------------------------------------------- // Process data from the ADXL // logic [11:0] accel_x, accel_y, accel_z, accel_temp; logic [11:0] accel_x_latch, accel_y_latch; logic [11:0] x_mag, x_mag_filtered, y_mag, y_mag_filtered; logic [3:0] x_sign, y_sign; logic data_ready; always_ff @(posedge clk_100mhz) begin accel_x_latch <= data_ready ? accel_x : accel_x_latch; accel_y_latch <= data_ready ? accel_y : accel_y_latch; end // this section displays twos complement in + - format assign x_mag = accel_x_latch[11] ? (~accel_x_latch +1) : accel_x_latch; assign y_mag = accel_y_latch[11] ? (~accel_y_latch +1) : accel_y_latch; assign x_sign = accel_x_latch[11] ? 4'hF : 4'h0; assign y_sign = accel_y_latch[11] ? 4'hF : 4'h0; // average samples iir_filter x_filter(.clk(clk_100mhz), .data_ready(data_ready), .data_in(x_mag), .data_filtered(x_mag_filtered)); iir_filter y_filter(.clk(clk_100mhz), .data_ready(data_ready), .data_in(y_mag), .data_filtered(y_mag_filtered)); assign data = {x_sign, x_mag_filtered, y_sign, y_mag_filtered}; // acl_miso acl_mosi acl_sclk acl_csn ADXL362Ctrl my_accel( .SYSCLK (clk_100mhz), // in .RESET (reset), // in .ACCEL_X (accel_x), // out STD_LOGIC_VECTOR (11 downto 0); .ACCEL_Y (accel_y), // out STD_LOGIC_VECTOR (11 downto 0); .ACCEL_Z (accel_z), // out STD_LOGIC_VECTOR (11 downto 0); .ACCEL_TMP (accel_temp), // out STD_LOGIC_VECTOR (11 downto 0); .Data_Ready (data_ready), // out STD_LOGIC; .SCLK (acl_sclk), // out .MOSI (acl_mosi), // out .MISO (acl_miso), // in .SS (acl_csn) // out STD_LOGIC ); //---------------------------------------------------------------------------------------------------------------------- assign led16_r = btnl; // left button -> red led assign led16_g = btnc; // center button -> green led assign led16_b = btnr; // right button -> blue led assign led17_r = btnl; assign led17_g = btnc; assign led17_b = btnr; // btnc button is user reset logic reset; debounce db1(.reset_in(reset),.clock_in(clk_100mhz),.noisy_in(btnc),.clean_out(reset)); // UP and DOWN buttons for pong paddle logic up,down; debounce db2(.reset_in(reset),.clock_in(clk_100mhz),.noisy_in(btnu),.clean_out(up)); debounce db3(.reset_in(reset),.clock_in(clk_100mhz),.noisy_in(btnd),.clean_out(down)); endmodule module synchronize #(parameter NSYNC = 3) // number of sync flops. must be >= 2 (input clk,in, output logic out); logic [NSYNC-2:0] sync; always_ff @ (posedge clk) begin {out,sync} <= {sync[NSYNC-2:0],in}; end endmodule /////////////////////////////////////////////////////////////////////////////// // // Pushbutton Debounce Module (video version - 24 bits) // /////////////////////////////////////////////////////////////////////////////// module debounce (input reset_in, clock_in, noisy_in, output logic clean_out); logic [19:0] count; logic new_input; always_ff @(posedge clock_in) if (reset_in) begin new_input <= noisy_in; clean_out <= noisy_in; count <= 0; end else if (noisy_in != new_input) begin new_input<=noisy_in; count <= 0; end else if (count == 1000000) clean_out <= new_input; else count <= count+1; endmodule ////////////////////////////////////////////////////////////////////////////////// // Engineer: g.p.hom // // Create Date: 18:18:59 04/21/2013 // Module Name: display_8hex // Description: Display 8 hex numbers on 7 segment display // ////////////////////////////////////////////////////////////////////////////////// module display_8hex_accel( input clk_in, // system clock input [31:0] data_in, // 8 hex numbers, msb first output logic [6:0] seg_out, // seven segment display output output logic [7:0] strobe_out, // digit strobe output logic dp ); localparam bits = 13; logic [bits:0] counter = 0; // clear on power up logic [6:0] segments[15:0]; // 16 7 bit memorys assign segments[0] = 7'b100_0000; // inverted logic assign segments[1] = 7'b111_1001; // gfedcba assign segments[2] = 7'b010_0100; assign segments[3] = 7'b011_0000; assign segments[4] = 7'b001_1001; assign segments[5] = 7'b001_0010; assign segments[6] = 7'b000_0010; assign segments[7] = 7'b111_1000; assign segments[8] = 7'b000_0000; assign segments[9] = 7'b001_1000; assign segments[10] = 7'b000_1000; assign segments[11] = 7'b000_0011; assign segments[12] = 7'b010_0111; assign segments[13] = 7'b010_0001; assign segments[14] = 7'b000_0110; assign segments[15] = 7'b000_1110; always_ff @(posedge clk_in) begin // Here I am using a counter and select 3 bits which provides // a reasonable refresh rate starting the left most digit // and moving left. counter <= counter + 1; // dp <= !(counter[bits:bits-2]==6); // turn on dp on the second digit dp <= 1; // dp off case (counter[bits:bits-2]) 3'b000: begin // use the MSB 4 bits seg_out <= (data_in[31:28] == 15) ? 7'b011_1111 : 7'b111_1111;; strobe_out <= 8'b0111_1111 ; end 3'b001: begin seg_out <= segments[data_in[27:24]]; strobe_out <= 8'b1011_1111 ; end 3'b010: begin seg_out <= segments[data_in[23:20]]; strobe_out <= 8'b1101_1111 ; end 3'b011: begin seg_out <= segments[data_in[19:16]]; strobe_out <= 8'b1110_1111; end 3'b100: begin seg_out <= (data_in[15:12] == 15) ? 7'b011_1111 : 7'b111_1111; strobe_out <= 8'b1111_0111; end 3'b101: begin seg_out <= segments[data_in[11:8]]; strobe_out <= 8'b1111_1011; end 3'b110: begin seg_out <= segments[data_in[7:4]]; strobe_out <= 8'b1111_1101; end 3'b111: begin seg_out <= segments[data_in[3:0]]; strobe_out <= 8'b1111_1110; end endcase end endmodule module iir_filter( input clk, data_ready, input[11:0] data_in, output [11:0] data_filtered ); logic old_ready; logic [14:0] data_average; assign data_filtered = data_average[12:1]; // scale it always_ff @(posedge clk) begin old_ready <= data_ready; data_average <= !(old_ready && data_ready) ? ((data_in >> 3) + ((7*data_average)>>3)) : data_average; end endmodule