FPGA Cyclone IV - Receptor infrarojo
Indice
Introducci贸nCrear un nuevo proyecto - Paso 1
Nuevo archivo - Paso 2
Asignaci贸n de pines - Paso 3
Programar - Paso 4
Introducci贸n
Ya sabemos como programar nuestra FPGA, ahora es momento de continuar jugando con los perif茅ricos de nuestra tarjeta de desarrollo.
Aqu铆 te ense帽amos c贸mo usar el receptor infrarojo de tu FPGA en Windows, f谩cil y en menos de 15 minutos.
Prerrequisitos
鈥僛+] Intel Quartus Prime Lite Edition. 鈥僛+] FPGA Cyclone IV. 鈥僛+] USB-Blaster.
Paso 1: Crear un nuevo proyecto
Lo primero ser谩 abrir Quartus
En la parte superior izquierda vamos a dar clic en File > New Project Wizard.
En el asistente para creaci贸n de proyectos vamos a indicar el directorio donde deseamos guardar nuestro proyecto, seleccionar en Project Type proyecto vac铆o Empty project. A continuaci贸n clic en Next.
鈥僐ecuerda en la pesta帽a Family, Device & Board Settings seleccionar la referencia de nuestra FPGA EP4CE6E22C8
En la siguiente ventana vamos a desactivar el simulador, clic en Next y en la 煤ltima pesta帽a Summary clic en Finish y listo, se crear谩 nuestro proyecto.
* Si te aparece una ventana de advertencia como la siguiente, marca el check en Don't show this message again y clic en Yes.
Paso 2: Nuevo archivo
Ahora vamos a crear el archivo donde podemos comenzar a escribir el c贸digo para nuestro hardware, sea Verilog o VHDL.
Lo primero ser谩 ir a File > New.
En la ventana que nos aparece vamos a seleccionar el tipo de archivo que queremos crear, en nuestro caso usaremos Verilog HDL.
El archivo se crear谩 y podemos comenzar a escribir nuestro c贸digo Verilog.
// Shows the key pressed on the 4-digit display
module IR(clk,rst_n,IR,led_cs,led_db);
input clk; input rst_n; input IR; output [3:0] led_cs; output [7:0] led_db;
reg [3:0] led_cs; reg [7:0] led_db;
reg [7:0] led1,led2,led3,led4; reg [15:0] irda_data; // save irda data,than send to 7 segment led reg [31:0] get_data; // use for saving 32 bytes irda data reg [5:0] data_cnt; // 32 bytes irda data counter reg [2:0] cs,ns; reg error_flag; // 32 bytes data error indicator
//----------------------------------------------------------------------------
reg irda_reg0; // To avoid destabilisation and to avoid driving multiple registers, this one is not used. reg irda_reg1; // This is the only one that can be used, and represents the state of irda in the following programme reg irda_reg2; // To determine the edge of irda, hit the register again, the previous state of irda is represented in the following program wire irda_neg_pulse; // Determine the falling edge of irda wire irda_pos_pulse; // Determine the rising edge of irda wire irda_chang; // Determine the jumping edge of rda.
reg[15:0] cnt_scan; // Scanning Frequency Counter
always @ (posedge clk) // Follow registers are used here if(!rst_n) begin irda_reg0 <= 1'b0; irda_reg1 <= 1'b0; irda_reg2 <= 1'b0; end else begin led_cs <= 4'b0000; // The bit selection of the digital tube is on. irda_reg0 <= IR; irda_reg1 <= irda_reg0; irda_reg2 <= irda_reg1; end
assign irda_chang = irda_neg_pulse | irda_pos_pulse; // Change of IR receive signal, up or down assign irda_neg_pulse = irda_reg2 & (~irda_reg1); // IR receive signal irda falling edge assign irda_pos_pulse = (~irda_reg2) & irda_reg1; // IR receive signal irda rising edge
reg [10:0] counter; // Crossover frequency 1750 times reg [8:0] counter2; // Counting points after frequency division wire check_9ms; // check leader 9ms time wire check_4ms; // check leader 4.5ms time wire low; // check data="0" time wire high; // check data="1" time
//----------------------------------------------------------------------------
// Crossover 1750 count always @ (posedge clk) if (!rst_n) counter <= 11'd0; else if (irda_chang) // If the irda level jumps, start counting again. counter <= 11'd0; else if (counter == 11'd1750) counter <= 11'd0; else counter <= counter + 1'b1;
//----------------------------------------------------------------------------
always @ (posedge clk) if (!rst_n) counter2 <= 9'd0; else if (irda_chang) // If the irda level jumps, start counting again. counter2 <= 9'd0; else if (counter == 11'd1750) counter2 <= counter2 +1'b1;
assign check_9ms = ((217 < counter2) & (counter2 < 297)); // 257 To increase stability, take a range assign check_4ms = ((88 < counter2) & (counter2 < 168)); //128 assign low = ((6 < counter2) & (counter2 < 26)); // 16 assign high = ((38 < counter2) & (counter2 < 58)); // 48
//----------------------------------------------------------------------------
// generate state machine parameter IDLE = 3'b000, // initial state LEADER_9 = 3'b001, // 9ms LEADER_4 = 3'b010, // 4ms DATA_STATE = 3'b100; // transmission data
always @ (posedge clk) if (!rst_n) cs <= IDLE; else cs <= ns; // status bit
always @ ( * ) case (cs) IDLE: if (~irda_reg1) ns = LEADER_9; else ns = IDLE;
LEADER_9: if (irda_pos_pulse) //leader 9ms check begin if (check_9ms) ns = LEADER_4; else ns = IDLE; end else // Complete if---else--- ;prevents generation of latch ns =LEADER_9;
LEADER_4: if (irda_neg_pulse) // leader 4.5ms check begin if (check_4ms) ns = DATA_STATE; else ns = IDLE; end else ns = LEADER_4;
DATA_STATE: if ((data_cnt == 6'd32) & irda_reg2 & irda_reg1) ns = IDLE; else if (error_flag) ns = IDLE; else ns = DATA_STATE; default: ns = IDLE; endcase
// Outputs in a state machine, described by timing circuits always @ (posedge clk) if (!rst_n) begin data_cnt <= 6'd0; get_data <= 32'd0; error_flag <= 1'b0; end
else if (cs == IDLE) begin data_cnt <= 6'd0; get_data <= 32'd0; error_flag <= 1'b0; end
else if (cs == DATA_STATE) begin if (irda_pos_pulse) // low 0.56ms check begin if (!low) //error error_flag <= 1'b1; end else if (irda_neg_pulse) //check 0.56ms/1.68ms data 0/1 begin if (low) get_data[0] <= 1'b0; else if (high) get_data[0] <= 1'b1; else error_flag <= 1'b1;
get_data[31:1] <= get_data[30:0]; data_cnt <= data_cnt + 1'b1; end end
always @ (posedge clk) if (!rst_n) irda_data <= 16'd0; else if ((data_cnt ==6'd32) & irda_reg1) begin led1 <= get_data[7:0]; // data inverse code led2 <= get_data[15:8]; // data code led3 <= get_data[23:16]; // user code led4 <= get_data[31:24]; end
// The keys pressed by the remote control are displayed on the 4-digit display. always@(led2) begin case(led2)
// Display 0 to 9 on the 4-digit display. 8'b01101000: // Code value for remote board 0 led_db=8'b1100_0000; // Display 0
8'b00110000: // Code value for remote control board 1 led_db=8'b1111_1001; // Display 1
8'b00011000: // Code value for remote control board 2 led_db=8'b1010_0100; // Display 2
8'b01111010: // Code value for remote control board 3 led_db=8'b1011_0000; // Display 3
8'b00010000: // Code value for remote control board 4 led_db=8'b1001_1001; // Display 4
8'b00111000: // Code value for remote control board 5 led_db=8'b1001_0010; // Display 5
8'b01011010: // Code value for remote control board 6 led_db=8'b1000_0010; // Display 6
8'b01000010: // Code value for remote control board 7 led_db=8'b1111_1000; // Display 7
8'b01001010: // Code value for remote control board 8 led_db=8'b1000_0000; // Display 8
8'b01010010: // Code value for remote control board 9 led_db=8'b1001_0000; // Display 9
// When no key is pressed, the display F default: led_db=8'b1000_1110;
endcase end
endmodule
Cuando ya tengamos escrito nuestro c贸digo debemos compilarlo, para esto debemos hacer clic en la flecha azul del panel superior.
Esperamos a que termine el proceso de compilaci贸n y que el Flow Status diga Successful. Si el proceso no es exitoso recuerda revisar la pesta帽a Messages all铆 encontrar谩s informaci贸n 煤til para solucionar el error.
Paso 3: Asignaci贸n de pines
Vamos a la barra de men煤s para abrir la ventana de asignaci贸n de pines Assignments > Pin planner .
De acuerdo con nuestro c贸digo tenemos tres se帽ales de entrada y dos buses de salida; la se帽al del sensor infrarojo, la se帽al de reloj, el boton de reset, los comunes y los segmentos del display.
| Node Name | Direction | Location |
|---|---|---|
| IR | Input | PIN_100 |
| clk | Input | PIN_23 |
| led_cs[3] | Output | PIN_137 |
| led_cs[2] | Output | PIN_136 |
| led_cs[1] | Output | PIN_135 |
| led_cs[0] | Output | PIN_133 |
| led_db[7] | Output | PIN_127 |
| led_db[6] | Output | PIN_124 |
| led_db[5] | Output | PIN_126 |
| led_db[4] | Output | PIN_132 |
| led_db[3] | Output | PIN_129 |
| led_db[2] | Output | PIN_125 |
| led_db[1] | Output | PIN_121 |
| led_db[0] | Output | PIN_128 |
| rst_n | Input | PIN_25 |
Paso 4: Programar
El 煤ltimo paso ser谩 enviar nuestro dise帽o al FPGA. Vamos a ir a la barra de men煤s Tools > Programmer.
* En este punto aseg煤rate de tener todo conectado, la alimentaci贸n de la FPGA y el USB-Blaster a tu computador y FPGA.
鈥傾ntes de hacer clic en Start aseg煤rate de que el Hardware setup detecte correctamente el USB-Blaster.
Se inicia el proceso de programaci贸n de nuestra FPGA y estar谩 listo cuando la barra de progreso llegue al 100%.
Y listo, 隆Felicitaciones!
Ya sabes c贸mo usar el receptor infrarojo en tu FPGA Cyclone IV.
Autor:
M. Sneider M. Cortes
脷ltima actualizaci贸n: 19/07/2024
