diff --git a/LCD_controle2.v b/LCD_controle2.v new file mode 100644 index 0000000..f6abefe --- /dev/null +++ b/LCD_controle2.v @@ -0,0 +1,122 @@ +module LCD_INIT( + input clk, // Clock do sistema + input rst, // Reset assíncrono ativo em nível baixo + input init_start, // Sinal para iniciar a sequência de inicialização + output reg [7:0] lcd_data, // Barramento de dados para o LCD + output reg lcd_rs, // Registro/Comando + output reg lcd_rw, // Read/Write + output reg lcd_e, // Enable + output reg done // Indica que a sequência terminou +); + + // Inicialização das saídas do LCD + initial begin + lcd_data = 0; + lcd_e = 0; // Enable + lcd_rw = 0; // Read/Write + lcd_rs = 0; // Registro/Comando + done = 0; // Sequência ainda não concluída + end + + // Contador para criar delays entre instruções + reg [31:0] counter = 0; + parameter MS = 50_000; // Delay de exemplo (aprox 1ms com clock 50MHz) + parameter WRITE = 0, WAIT = 1; // Estados da FSM + reg [1:0] state = WRITE; + + // Contador de instruções + reg [7:0] instructions = 0; + + // Sequência de escrita no LCD + always @(posedge clk or negedge rst) begin + if (~rst) begin + counter <= 0; + state <= WRITE; + instructions <= 0; + done <= 0; + end else if (init_start) begin // Só funciona se init_start estiver ativo + case (state) + WRITE: begin + if(counter == MS) begin + state <= WAIT; + counter <= 0; + end else begin + counter <= counter + 1; + end + end + WAIT: begin + if(counter == MS - 1) begin + state <= WRITE; + counter <= 0; + if(instructions < 37) instructions <= instructions + 1; + else done <= 1; // Sequência concluída + end else begin + counter <= counter + 1; + end + end + default: begin end + endcase + end else begin + // Se init_start não estiver ativo, mantém tudo zerado + lcd_data <= 0; + lcd_rs <= 0; + lcd_rw <= 0; + lcd_e <= 0; + done <= 0; + counter <= 0; + state <= WRITE; + instructions <= 0; + end + end + + // Lógica combinacional para definir dados e sinais do LCD + always @(*) begin + // RW sempre em 0 para escrita + lcd_rw = 0; + + // Pulso de enable: WRITE = 1, WAIT = 0 + case (state) + WRITE: lcd_e = 1; + WAIT: lcd_e = 0; + default: lcd_e = lcd_e; + endcase + + // Sequência de instruções e dados + case (instructions) + 0: lcd_data = 8'h38; lcd_rs = 0; // Habilita o modo de 8 bits, 2 linhas + 1: lcd_data = 8'h0E; lcd_rs = 0; // Display ON, Cursor ON, Blink OFF + 2: lcd_data = 8'h01; lcd_rs = 0; // Clear display + 3: lcd_data = 8'h02; lcd_rs = 0; // Cursor Home + 4: lcd_data = 8'h06; lcd_rs = 0; // Incrementa cursor + + // Primeira linha: "---- [- - - -]" + 5: lcd_data = 8'h2D; lcd_rs = 1; // - + 6: lcd_data = 8'h2D; lcd_rs = 1; // - + 7: lcd_data = 8'h2D; lcd_rs = 1; // - + 8: lcd_data = 8'h2D; lcd_rs = 1; // - + 9: lcd_data = 8'h20; lcd_rs = 1; // Espaço + 10: lcd_data = 8'h20; lcd_rs = 1; // Espaço + 11: lcd_data = 8'h20; lcd_rs = 1; // Espaço + 12: lcd_data = 8'h20; lcd_rs = 1; // Espaço + 13: lcd_data = 8'h5B; lcd_rs = 1; // [ + 14: lcd_data = 8'h2D; lcd_rs = 1; // - + 15: lcd_data = 8'h2D; lcd_rs = 1; // - + 16: lcd_data = 8'h2D; lcd_rs = 1; // - + 17: lcd_data = 8'h2D; lcd_rs = 1; // - + 18: lcd_data = 8'h5D; lcd_rs = 1; // ] + + // Segunda linha: move cursor e escreve "+00000" + 19: lcd_data = 8'hC0; lcd_rs = 0; // Cursor para segunda linha + 20: lcd_data = 8'h2B; lcd_rs = 1; // + + 21: lcd_data = 8'h30; lcd_rs = 1; // 0 + 22: lcd_data = 8'h30; lcd_rs = 1; // 0 + 23: lcd_data = 8'h30; lcd_rs = 1; // 0 + 24: lcd_data = 8'h30; lcd_rs = 1; // 0 + 25: lcd_data = 8'h30; lcd_rs = 1; // 0 + + default: begin + lcd_data = 8'h02; lcd_rs = 0; // Default: cursor home + end + endcase + end +endmodule diff --git a/LCD_controller.v b/LCD_controller.v new file mode 100644 index 0000000..f5b4f12 --- /dev/null +++ b/LCD_controller.v @@ -0,0 +1,111 @@ +module LCD_INIT( + output reg[7:0] data, + output reg EN, RW, RS, + + input clk +); + +initial begin + data = 0; + EN = 0; //Enable + RW = 0; //Read/Write + RS = 0;// +end + +reg [31:0] counter = 0; +parameter MS = 50_000; +parameter WRITE = 0, WAIT = 1; // estados da fsm +reg [3:0] state = WRITE; + +reg [7:0] instructions = 0; + +always @(posedge clk, negedge rst) begin + case (state) + WRITE: begin + if(counter == MS) begin + state = WAIT; + counter = 0; + end else begin + counter = counter + 1; + end + end + WAIT: begin + if(counter == MS - 1) begin + state = WRITE; + counter = 0; + if(instructions < 38) instructions = instructions + 1; + end else begin + counter = counter + 1; + end + + end + default : begin end + endcase +end + + + +always @(*) begin + case (state) + WRITE: EN <= 1; + WAIT: EN <= 0; + default: EN <= EN; + endcase + + case (instructions) + 0: begin data <= 8'h38; RS <= 0; end //Habilita o modo de 8 bits, adiciona a segunda linha + 1: begin data <= 8'h0E; RS <= 0; end //Display ON, Cursos ON, Blink OFF + 2: begin data <= 8'h01; RS <= 0; end //Clear + 3: begin data <= 8'h02; RS <= 0; end //Cursor Home // POSSO MUDAR A ODEM DO 06 E 02 + 4: begin data <= 8'h06; RS <= 0; end // Pula o cursor quando printa + + 5: begin data <= 8'h2D; RS <= 1; end //- + 6: begin data <= 8'h2D; RS <= 1; end //- + 7: begin data <= 8'h2D; RS <= 1; end //- + 8: begin data <= 8'h2D; RS <= 1; end //- + + + + 9: begin data <= 8'h20; RS <= 1; end //ESPAÇO + 10:begin data <= 8'h20; RS <= 1; end //ESPAÇO + 11: begin data <= 8'h20; RS <= 1; end //ESPAÇO + 12: begin data <= 8'h20; RS <= 1; end //ESPAÇO + 13: begin data <= 8'h20; RS <= 1; end //ESPAÇO + 14: begin data <= 8'h20; RS <= 1; end //ESPAÇO + + 15: begin data <= 8'h5B; RS <= 1; end // [ + 16: begin data <= 8'h2D; RS <= 1; end //- + 17: begin data <= 8'h2D; RS <= 1; end //- + 18: begin data <= 8'h2D; RS <= 1; end //- + 19: begin data <= 8'h2D; RS <= 1; end //- + 20 : begin data <= 8'h5D; RS <= 1; end //] + + 21: begin data <= 8'hC0; RS <= 0; end // PASSA O CURSOR PARA SEGUNDA LINHA + 22: begin data <= 8'h20; RS <= 1; end //ESPAÇO + 23: begin data <= 8'h20; RS <= 1; end //ESPAÇO + 24: begin data <= 8'h20; RS <= 1; end //ESPAÇO + 25: begin data <= 8'h20; RS <= 1; end //ESPAÇO + 26: begin data <= 8'h20; RS <= 1; end //ESPAÇO + 27: begin data <= 8'h20; RS <= 1; end //ESPAÇO + 28: begin data <= 8'h20; RS <= 1; end //ESPAÇO + 29: begin data <= 8'h20; RS <= 1; end //ESPAÇO + 30: begin data <= 8'h20; RS <= 1; end //ESPAÇO + 31: begin data <= 8'h20; RS <= 1; end //ESPAÇO + + 32: begin data <= 8'h2B; RS <= 1; end //+ + 33 : begin data <= 8'h30; RS <= 1; end //0 + 34: begin data <= 8'h30; RS <= 1; end //0 + 35: begin data <= 8'h30; RS <= 1; end //0 + 36: begin data <= 8'h30; RS <= 1; end //0 + 37: begin data <= 8'h30; RS <= 1; end //0 + + + + + + + default: begin data <= 8'h02; RS <= 0; end + endcase +end + +endmodule \ No newline at end of file diff --git a/UC.v b/UC.v new file mode 100644 index 0000000..84e9ecc --- /dev/null +++ b/UC.v @@ -0,0 +1,213 @@ +module Unidade_Controle( + // Saídas para a interface inicial na placa(opcional) + output reg LED_vermelho, + output reg LED_verde, + + // Saidas para o Banco de Registradores (memoria.v) + output reg reg_write, // sinal de controle( habilita ou nao a escrita no banco de registradores ) + output reg [3:0] reg_dest, // ira indicar em que local(indice) eu vou escrever o resultado final da minha operacao no banco de registradores + output reg [3:0] reg_src1, //(se reg_src1 == 1100(no meu switch) -> eu irei ver o valor que esta armazenado na posicao 12 no meu banco de registradores de 16 bits) + output reg [3:0] reg_src2, // tambem sera um dos operandos da minha ula + output reg [15:0] reg_data_in, // dado em 16 bits que sera escrito(especificado pelo registrador de destino) no campo de registradores(o conteudo que sera escrito posicao do red_dest) + + // Saidas para a nossa ULA (ULA.v) + output reg [2:0] alu_op, + output reg [15:0] alu_op_a, + output reg [15:0] alu_op_b, + + // Saidas para o LCD + output reg [7:0] lcd_data_bus, + output reg lcd_rs, + output reg lcd_rw, + output reg lcd_e, + + // Entradas do meu modulo + input key_ligar, + input key_enviar, + input clk, + input reset, + input [17:0] instruction_input, + input [15:0] reg_data_out_a, + input [15:0] reg_data_out_b, + input [15:0] alu_result +); + + // Estados da minha Maquina de Estados Finitos: + parameter State_off = 4'b0000; + parameter Init = 4'b0001; + parameter Fetch = 4'b0010; + parameter Decode = 4'b0011; + parameter Execute = 4'b0100; + parameter Writeback = 4'b0101; + parameter Special_Op = 4'b0110; + + reg [3:0] estado_atual; + + // Logica para pressionar e soltar o botao + reg key_ligar_prev; + reg key_enviar_prev; + wire key_ligar_negedge = key_ligar_prev & ~key_ligar; + wire key_enviar_negedge = key_enviar_prev & ~key_enviar; + + // Contador de estados para operações multiciclo (LCD) + reg [15:0] counter; + parameter DELAY = 50_000; + + // Registradores para decodificação da instrucao (locais, não são saídas) + reg [2:0] opcode; + reg [3:0] reg_dest_inst; + reg [3:0] reg_src1_inst; + reg [3:0] reg_src2_inst; + reg [6:0] immediato; + reg immediato_sinal; + + // Parte Sequencial: Lógica de Transição de Estados/mantimento: + always @(posedge clk or posedge reset) begin + if (reset) begin + estado_atual <= State_off; + key_ligar_prev <= 1'b1; + key_enviar_prev <= 1'b1; + counter <= 16'd0; + end + else begin + key_ligar_prev <= key_ligar; + key_enviar_prev <= key_enviar; + + case (estado_atual) + State_off: if (key_ligar_negedge) begin estado_atual <= Init; end + else estado_atual <= State_off; + Init: begin + if (counter >= DELAY) begin estado_atual <= Fetch; end + else begin estado_atual <= Init; counter <= counter + 1; end + end + Fetch: begin + if (key_ligar_negedge) estado_atual <= State_off; + else if (key_enviar_negedge) estado_atual <= Decode; + else estado_atual <= Fetch; + end + Decode: begin + if (opcode == 3'b000) begin estado_atual <= Writeback; end // LOAD -> pula Execute + else if (opcode == 3'b110 || opcode == 3'b111) begin estado_atual <= Special_Op; end // lcd + else if (1'b1) begin estado_atual <= Execute; end // Executa na ula + else begin estado_atual <= Decode; end + end + Execute: estado_atual <= Writeback; // sempre vai para o prox + Writeback: estado_atual <= Fetch; // sempre vai para o prox + Special_Op: begin + if (counter >= DELAY) begin estado_atual <= Fetch; end + else begin estado_atual <= Special_Op; counter <= counter + 1; end + end + default: estado_atual <= State_off; + endcase + end + end + + // Parte Combinacional: Logica das Saidas + always @(*) begin + // Define um valor padrao (0) para todas as saidas, explicitamente. + LED_vermelho = 1'b0; + LED_verde = 1'b0; + reg_write = 1'b0; + reg_dest = 4'b0; + reg_src1 = 4'b0; + reg_src2 = 4'b0; + alu_op = 3'b000; + alu_op_a = 16'h0000; + alu_op_b = 16'h0000; + reg_data_in = 16'h0000; + lcd_data_bus = 8'h00; + lcd_rs = 1'b0; + lcd_rw = 1'b0; + lcd_e = 1'b0; + + // Decodificacao da instrucao + opcode = instruction_input[17:15]; + + // Atribuições de campos da instrucao + if (opcode == 3'b010 || opcode == 3'b100 || opcode == 3'b101 || opcode == 3'b000) begin + reg_dest_inst = instruction_input[14:11]; + reg_src1_inst = instruction_input[10:7]; + immediato_sinal = instruction_input[6]; + immediato = instruction_input[5:0]; + end else if (opcode == 3'b001 || opcode == 3'b011) begin + reg_dest_inst = instruction_input[11:8]; + reg_src1_inst = instruction_input[7:4]; + reg_src2_inst = instruction_input[3:0]; + end else if (opcode == 3'b110 || opcode == 3'b111) begin + reg_src1_inst = instruction_input[3:0]; + end + + // Lógica de controle principal baseada no estado atual + case (estado_atual) + State_off: begin + LED_vermelho = 1'b1; + end + + Init: begin + lcd_data_bus = 8'h38; + lcd_e = 1'b1; + if (counter >= DELAY) begin + lcd_e = 1'b0; + end + end + + Fetch: begin + LED_verde = 1'b1; + end + + Decode: begin + reg_dest = reg_dest_inst; + reg_src1 = reg_src1_inst; + reg_src2 = reg_src2_inst; + end + + Execute: begin + reg_src1 = reg_src1_inst; + reg_src2 = reg_src2_inst; + + // Define as operacoes da ULA + if (opcode == 3'b001 || opcode == 3'b010) + alu_op = 3'b000; // ADD, ADDI + else if (opcode == 3'b011 || opcode == 3'b100) + alu_op = 3'b001; // SUB, SUBI + else if (opcode == 3'b101) + alu_op = 3'b010; // MUL + + alu_op_a = reg_data_out_a; + if (opcode == 3'b001 || opcode == 3'b011) + alu_op_b = reg_data_out_b; + else + alu_op_b = {immediato_sinal, immediato}; + end + + Writeback: begin + reg_write = 1'b1; + reg_dest = reg_dest_inst; + if (opcode == 3'b000) + reg_data_in = { {9{immediato_sinal}}, immediato }; // Extensão de sinal para 16 bits + else + reg_data_in = alu_result; + end + + Special_Op: begin + if (opcode == 3'b111) begin // DISPLAY + lcd_data_bus = 8'h0C; + lcd_e = 1'b1; + if (counter >= DELAY) begin + lcd_e = 1'b0; + lcd_data_bus = reg_data_out_a[7:0]; // Exibe apenas os 8 bits menos significativos + lcd_rs = 1'b1; + lcd_e = 1'b1; + end + end else if (opcode == 3'b110) begin // CLEAR + reg_write = 1'b1; + reg_data_in = 16'h0000; + end + end + + default: begin + LED_vermelho = 1'b1; + end + endcase + end +endmodule diff --git a/UC_version2.v b/UC_version2.v new file mode 100644 index 0000000..20ba388 --- /dev/null +++ b/UC_version2.v @@ -0,0 +1,200 @@ +module Unidade_Controle( + // Saídas para a interface inicial na placa(opcional) + output reg LED_vermelho, + output reg LED_verde, + + // Saidas para o Banco de Registradores (memoria.v) + output reg reg_write, // sinal de controle( habilita ou nao a escrita no banco de registradores ) + output reg [3:0] reg_dest, // ira indicar em que local(indice) eu vou escrever o resultado final da minha operacao no banco de registradores + output reg [3:0] reg_src1, //(se reg_src1 == 1100(no meu switch) -> eu irei ver o valor que esta armazenado na posicao 12 no meu banco de registradores de 16 bits) + output reg [3:0] reg_src2, // tambem sera um dos operandos da minha ula + output reg signed [15:0] reg_data_in, // dado em 16 bits que sera escrito(especificado pelo registrador de destino) no campo de registradores(o conteudo que sera escrito posicao do red_dest) + + // Saidas para a nossa ULA (ULA.v) + output reg [2:0] alu_op, + output reg signed [15:0] alu_op_a, + output reg signed [15:0] alu_op_b, + + // Saidas para o LCD + output reg [7:0] lcd_data_bus, + output reg lcd_rs, + output reg lcd_rw, + output reg lcd_e, + + // Entradas do meu modulo + input key_ligar, + input key_enviar, + input clk, + input reset, + input [17:0] instruction_input, + input signed [15:0] reg_data_out_a, + input signed [15:0] reg_data_out_b, + input signed [15:0] alu_result +); + + // Estados da minha Maquina de Estados Finitos: + parameter State_off = 4'b0000; + parameter Init = 4'b0001; + parameter Fetch = 4'b0010; + parameter Decode = 4'b0011; + parameter Execute = 4'b0100; + parameter Writeback = 4'b0101; + parameter Special_Op = 4'b0110; + + reg [3:0] estado_atual; + + // Logica para pressionar e soltar o botao + reg key_ligar_prev; + reg key_enviar_prev; + wire key_ligar_negedge = key_ligar_prev & ~key_ligar; + wire key_enviar_negedge = key_enviar_prev & ~key_enviar; + + // Contador de estados para operações multiciclo (LCD) + reg [15:0] counter; + parameter DELAY = 50_000; + + // Registradores para decodificação da instrucao (locais, não são saídas) + reg [2:0] opcode; + reg [3:0] reg_dest_inst; + reg [3:0] reg_src1_inst; + reg [3:0] reg_src2_inst; + reg [5:0] immediato; + reg immediato_sinal; + + // Wires para conectar o LCD_INIT + wire lcd_done; + + // Parte Sequencial: Lógica de Transição de Estados/mantimento: + always @(posedge clk or negedge reset) begin + if (~reset) begin + estado_atual <= State_off; + key_ligar_prev <= 1'b1; + key_enviar_prev <= 1'b1; + counter <= 16'd0; + end + else begin + key_ligar_prev <= key_ligar; + key_enviar_prev <= key_enviar; + + case (estado_atual) + State_off: + if (key_ligar_negedge) begin estado_atual <= Init; counter <= 16'd0; end + else estado_atual <= State_off; + + Init: begin + // Aguarda a sequência do LCD terminar + if (lcd_done) begin estado_atual <= Fetch; counter <= 16'd0; end + else begin estado_atual <= Init; counter <= counter + 1; end + end + + Fetch: begin + if (key_ligar_negedge) estado_atual <= State_off; + else if (key_enviar_negedge) estado_atual <= Decode; + else estado_atual <= Fetch; + end + + Decode: begin + // Decodificacao da instrucao + opcode = instruction_input[17:15]; + + // Atribuições de campos da instrucao + // ADDI, SUBI, MUL + if (opcode == 3'b010 || opcode == 3'b100 || opcode == 3'b101) begin + reg_dest_inst = instruction_input[14:11]; + reg_src1_inst = instruction_input[10:7]; + immediato_sinal = instruction_input[6]; + immediato = instruction_input[5:0]; + // ADD, SUB + end else if (opcode == 3'b001 || opcode == 3'b011) begin + reg_dest_inst = instruction_input[14:11]; + reg_src1_inst = instruction_input[10:7]; + reg_src2_inst = instruction_input[6:3]; + // LOAD + end else if (opcode == 3'b000) begin + reg_dest_inst = instruction_input[14:11]; + immediato_sinal = instruction_input[10]; + immediato = instruction_input[9:4]; + // CLEAR, DISPLAY + end else if (opcode == 3'b110 || opcode == 3'b111) begin + reg_src1_inst = instruction_input[14:11]; + end + + // Lógica de controle principal baseada no estado atual + if (opcode == 3'b000) estado_atual <= Writeback; // LOAD -> pula Execute + else if (opcode == 3'b110 || opcode == 3'b111) begin + estado_atual <= Special_Op; counter <= 16'd0; // lcd + end else estado_atual <= Execute; // Executa na ula + end + + Execute: begin + reg_src1 = reg_src1_inst; + reg_src2 = reg_src2_inst; + + alu_op = opcode; + alu_op_a = reg_data_out_a; + if (opcode == 3'b001 || opcode == 3'b011) + alu_op_b = reg_data_out_b; + else + alu_op_b = {10{immediato_sinal}, immediato}; // Extensão de sinal para 16 bits + + estado_atual <= Writeback; // sempre vai para o prox + end + + Writeback: begin + reg_write = 1'b1; + reg_dest = reg_dest_inst; + if (opcode == 3'b000) + reg_data_in = {10{immediato_sinal}, immediato}; // Extensão de sinal para 16 bits + else + reg_data_in = alu_result; + + estado_atual <= Fetch; // sempre vai para o prox + end + + Special_Op: begin + if (opcode == 3'b111) begin // DISPLAY + if (counter >= DELAY) begin + lcd_data_bus = reg_data_out_a[7:0]; // Exibe apenas os 8 bits menos significativos + lcd_rs = 1'b1; + lcd_e = 1'b1; // pulso único + end else begin + lcd_data_bus = 8'h0C; + lcd_e = 1'b1; + end + end else if (opcode == 3'b110) begin // CLEAR + reg_write = 1'b1; + reg_data_in = 16'h0000; + end + + if (counter >= DELAY) counter <= 16'd0; + else counter <= counter + 1; + end + + default: estado_atual <= State_off; + endcase + end + end + + // Parte Combinacional: Logica das Saidas + always @(*) begin + // Define um valor padrao (0) para todas as saidas, explicitamente. + LED_vermelho = 1'b0; + LED_verde = 1'b0; + reg_write = 1'b0; + reg_dest = 4'b0; + reg_src1 = 4'b0; + reg_src2 = 4'b0; + alu_op = 3'b000; + alu_op_a = 16'h0000; + alu_op_b = 16'h0000; + reg_data_in = 16'h0000; + lcd_data_bus = lcd_data_bus; // agora controlado pelo LCD_INIT + lcd_rs = lcd_rs; + lcd_rw = 1'b0; // sempre escrita + lcd_e = lcd_e; + + // Indicação de LEDs + if (estado_atual == State_off) LED_vermelho = 1'b1; + else if (estado_atual == Fetch) LED_verde = 1'b1; + end +endmodule