From eb8643ddbef43547eb7bfe58789a3908926c7258 Mon Sep 17 00:00:00 2001 From: Vaino Kauppila Date: Sun, 19 Apr 2026 12:32:58 +0300 Subject: refactor dir structure, add fib.c --- hdl/hexfile_reader.vhd | 342 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 342 insertions(+) create mode 100644 hdl/hexfile_reader.vhd (limited to 'hdl/hexfile_reader.vhd') diff --git a/hdl/hexfile_reader.vhd b/hdl/hexfile_reader.vhd new file mode 100644 index 0000000..143a264 --- /dev/null +++ b/hdl/hexfile_reader.vhd @@ -0,0 +1,342 @@ +------------------------------------------------------------------------------- +--Usage of the reader: +-- +--CONSTANT ihex_data : STRING := +--"/home/pro/autosub/erkka/digital/matlab/esim.HEX; +--VARIABLE memory : program_array := (OTHERS => (OTHERS => '0')); +-- +--read_ihex_file(ihex_data, memory); +-- +-- If some constant definitions are missing, try to figure them out. +-- If you can't contact Erkka Laulainen, elaulain@ecdl.tkk.fi, room I313A +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +--USE ieee.std_logic_arith.ALL; +USE ieee.numeric_std.ALL; +USE std.textio.ALL; +USE ieee.std_logic_textio.ALL; +USE ieee.std_logic_misc.ALL; + + +PACKAGE read_intel_hex_pack IS + CONSTANT debug : BOOLEAN := true; + + ------------------------------------------------------------------------------ + ----- Design Parameters ----------------------------------------------------- + ------------------------------------------------------------------------------ + + CONSTANT Inst_bits : INTEGER := 14; + CONSTANT data_bits : INTEGER := 8; + CONSTANT inst_mem_size : INTEGER := 1024; + TYPE program_array IS ARRAY (0 TO inst_mem_size-1) OF STD_LOGIC_VECTOR(Inst_bits-1 DOWNTO 0); + + ------------------------------------------------------------------------------ + ----- Reset Values ----------------------------------------------------------- + ------------------------------------------------------------------------------ + +-- CONSTANT W_RESET : STD_ULOGIC_VECTOR(data_bits-1 DOWNTO 0) := "XXXXXXXX"; +-- CONSTANT INDF_RESET : STD_ULOGIC_VECTOR(data_bits-1 DOWNTO 0) := "--------"; +-- CONSTANT TMR0_RESET : STD_ULOGIC_VECTOR(data_bits-1 DOWNTO 0) := "XXXXXXXX"; +-- CONSTANT PCL_RESET : STD_ULOGIC_VECTOR(data_bits-1 DOWNTO 0) := "00000000"; +-- CONSTANT STATUS_RESET : STD_ULOGIC_VECTOR(data_bits-1 DOWNTO 0) := "00011XXX"; +-- CONSTANT FSR_RESET : STD_ULOGIC_VECTOR(data_bits-1 DOWNTO 0) := "XXXXXXXX"; +-- CONSTANT PORTA_RESET : STD_ULOGIC_VECTOR(4 DOWNTO 0) := "XXXXX"; +-- CONSTANT PORTB_RESET : STD_ULOGIC_VECTOR(data_bits-1 DOWNTO 0) := "XXXXXXXX"; +-- CONSTANT EEDATA_RESET : STD_ULOGIC_VECTOR(data_bits-1 DOWNTO 0) := "XXXXXXXX"; +-- CONSTANT EEADR_RESET : STD_ULOGIC_VECTOR(data_bits-1 DOWNTO 0) := "XXXXXXXX"; +-- CONSTANT PCLATH_RESET : STD_ULOGIC_VECTOR(4 DOWNTO 0) := "00000"; +-- CONSTANT INTCON_RESET : STD_ULOGIC_VECTOR(data_bits-1 DOWNTO 0) := "0000000X"; +-- CONSTANT OPTION_REG_RESET : STD_ULOGIC_VECTOR(data_bits-1 DOWNTO 0) := "11111111"; +-- CONSTANT TRISA_RESET : STD_ULOGIC_VECTOR(4 DOWNTO 0) := "11111"; +-- CONSTANT TRISB_RESET : STD_ULOGIC_VECTOR(data_bits-1 DOWNTO 0) := "11111111"; +-- CONSTANT EECON1_RESET : STD_ULOGIC_VECTOR(4 DOWNTO 0) := "0X000"; +-- CONSTANT EECON2_RESET : STD_ULOGIC_VECTOR(data_bits-1 DOWNTO 0) := "--------"; + + ------------------------------------------------------------------------------ + ----- Operations Codes ------------------------------------------------------- + ------------------------------------------------------------------------------ + + ----- BYTE-ORIENTED FILE REGISTER OPERATIONS --------------------------------- + +-- CONSTANT ADDWF : STD_ULOGIC_VECTOR := "000111--------"; +-- CONSTANT ANDWF : STD_ULOGIC_VECTOR := "000101--------"; +-- CONSTANT CLRF : STD_ULOGIC_VECTOR := "0000011-------"; +-- CONSTANT CLRW : STD_ULOGIC_VECTOR := "0000010-------"; +-- CONSTANT COMF : STD_ULOGIC_VECTOR := "001001--------"; +-- CONSTANT DECF : STD_ULOGIC_VECTOR := "000011--------"; +-- CONSTANT DECFSZ : STD_ULOGIC_VECTOR := "001011--------"; +-- CONSTANT INCF : STD_ULOGIC_VECTOR := "001010--------"; +-- CONSTANT INCFSZ : STD_ULOGIC_VECTOR := "001111--------"; +-- CONSTANT IORWF : STD_ULOGIC_VECTOR := "000100--------"; +-- CONSTANT MOVF : STD_ULOGIC_VECTOR := "001000--------"; +-- CONSTANT MOVWF : STD_ULOGIC_VECTOR := "0000001-------"; +-- CONSTANT NOP : STD_ULOGIC_VECTOR := "0000000--00000"; +-- CONSTANT RLF : STD_ULOGIC_VECTOR := "001101--------"; +-- CONSTANT RRF : STD_ULOGIC_VECTOR := "001100--------"; +-- CONSTANT SUBWF : STD_ULOGIC_VECTOR := "000010--------"; +-- CONSTANT SWAPF : STD_ULOGIC_VECTOR := "001110--------"; +-- CONSTANT XORWF : STD_ULOGIC_VECTOR := "000110--------"; + + ----- BIT-ORIENTED FILE REGISTER OPERATIONS ---------------------------------- + +-- CONSTANT BCF : STD_ULOGIC_VECTOR := "0100----------"; +-- CONSTANT BSF : STD_ULOGIC_VECTOR := "0101----------"; +-- CONSTANT BTFSC : STD_ULOGIC_VECTOR := "0110----------"; +-- CONSTANT BTFSS : STD_ULOGIC_VECTOR := "0111----------"; + + ----- LITERAL AND CONTROL OPERATIONS ----------------------------------------- + +-- CONSTANT ADDLW : STD_ULOGIC_VECTOR := "11111---------"; +-- CONSTANT ANDLW : STD_ULOGIC_VECTOR := "111001--------"; +-- CONSTANT CALL : STD_ULOGIC_VECTOR := "100-----------"; +-- CONSTANT CLRWDT : STD_ULOGIC_VECTOR := "00000001100100"; +-- CONSTANT GOTO : STD_ULOGIC_VECTOR := "101-----------"; +-- CONSTANT IORLW : STD_ULOGIC_VECTOR := "111000--------"; +-- CONSTANT MOVLW : STD_ULOGIC_VECTOR := "1100----------"; +-- CONSTANT RETFIE : STD_ULOGIC_VECTOR := "00000000001001"; +-- CONSTANT RETLW : STD_ULOGIC_VECTOR := "1101----------"; +-- CONSTANT RET : STD_ULOGIC_VECTOR := "00000000001000"; +-- CONSTANT SLEEP : STD_ULOGIC_VECTOR := "00000001100011"; +-- CONSTANT SUBLW : STD_ULOGIC_VECTOR := "11110---------"; +-- CONSTANT XORLW : STD_ULOGIC_VECTOR := "111010--------"; + + ------------------------------------------------------------------------------ + ----- Special Function Register Address -------------------------------------- + ------------------------------------------------------------------------------ + +-- CONSTANT INDF_ADR : STD_ULOGIC_VECTOR := "-0000000"; +-- CONSTANT TMR0_ADR : STD_ULOGIC_VECTOR := "00000001"; +-- CONSTANT PCL_ADR : STD_ULOGIC_VECTOR := "-0000010"; +-- CONSTANT STATUS_ADR : STD_ULOGIC_VECTOR := "-0000011"; +-- CONSTANT FSR_ADR : STD_ULOGIC_VECTOR := "-0000100"; +-- CONSTANT PORTA_ADR : STD_ULOGIC_VECTOR := "00000101"; +-- CONSTANT PORTB_ADR : STD_ULOGIC_VECTOR := "00000110"; +-- CONSTANT EEDATA_ADR : STD_ULOGIC_VECTOR := "00001000"; +-- CONSTANT EEARD_ADR : STD_ULOGIC_VECTOR := "00001001"; +-- CONSTANT PCLATH_ADR : STD_ULOGIC_VECTOR := "-0001010"; +-- CONSTANT INTCON_ADR : STD_ULOGIC_VECTOR := "-0001011"; +-- CONSTANT OPTION_ADR : STD_ULOGIC_VECTOR := "10000001"; +-- CONSTANT TRISA_ADR : STD_ULOGIC_VECTOR := "10000101"; +-- CONSTANT TRISB_ADR : STD_ULOGIC_VECTOR := "10000110"; +-- CONSTANT EECON1_ADR : STD_ULOGIC_VECTOR := "10001000"; +-- CONSTANT EECON2_ADR : STD_ULOGIC_VECTOR := "10001001"; + + ------------------------------------------------------------------------------ + ----- STATUS Register Constants ---------------------------------------------- + ------------------------------------------------------------------------------ + +-- CONSTANT RP0_BIT : INTEGER := 5; +-- CONSTANT TO_BIT : INTEGER := 4; +-- CONSTANT PD_BIT : INTEGER := 3; +-- CONSTANT Z_BIT : INTEGER := 2; +-- CONSTANT DC_BIT : INTEGER := 1; +-- CONSTANT CARRY_BIT : INTEGER := 0; + + ------------------------------------------------------------------------------ + ----- INTCON Register Constants ---------------------------------------------- + ------------------------------------------------------------------------------ + +-- CONSTANT GIE_BIT : INTEGER := 7; +-- CONSTANT EEIE_BIT : INTEGER := 6; +-- CONSTANT T0IE_BIT : INTEGER := 5; +-- CONSTANT INTE_BIT : INTEGER := 4; +-- CONSTANT RBIE_BIT : INTEGER := 3; +-- CONSTANT T0IF_BIT : INTEGER := 2; +-- CONSTANT INTF_BIT : INTEGER := 1; +-- CONSTANT RBIF_BIT : INTEGER := 0; + + ------------------------------------------------------------------------------ + ----- OPTION Register Constants ---------------------------------------------- + ------------------------------------------------------------------------------ + +-- CONSTANT RBPU_BIT : INTEGER := 7; +-- CONSTANT INTEDG_BIT : INTEGER := 6; +-- CONSTANT T0CS_BIT : INTEGER := 5; +-- CONSTANT T0SE_BIT : INTEGER := 4; +-- CONSTANT PSA_BIT : INTEGER := 3; +-- CONSTANT PS2_BIT : INTEGER := 2; +-- CONSTANT PS1_BIT : INTEGER := 1; +-- CONSTANT PS0_BIT : INTEGER := 0; + + PROCEDURE read_ihex_file (program_name : IN STRING; memory : OUT program_array); + +END PACKAGE read_intel_hex_pack; + +PACKAGE BODY read_intel_hex_pack IS + + PROCEDURE str_to_hex (str : IN STRING; result : INOUT NATURAL) IS + VARIABLE ch : CHARACTER; + BEGIN + result := 0; + FOR i IN 1 TO str'LENGTH LOOP + ch := str(i); + IF '0' <= ch and ch <= '9' THEN + result := result*16 + character'pos(ch) - character'pos('0'); + ELSIF 'A' <= ch and ch <= 'F' THEN + result := result*16 + character'pos(ch) - character'pos('A') + 10; + ELSIF 'a' <= ch and ch <= 'f' THEN + result := result*16 + character'pos(ch) - character'pos('a') + 10; + ELSE + -- ASSERT 1; REPORT "FAILURE: str_to_hex: Non-hex character encountered!"; SEVERITY FAILURE; + END IF; + END LOOP; + END str_to_hex; + + PROCEDURE read_line_header (L : INOUT LINE; byte_count : INOUT INTEGER; address : INOUT INTEGER; record_type : INOUT INTEGER) IS + VARIABLE byte_count_str : STRING(1 to 2); + VARIABLE address_str : STRING(1 to 4); + VARIABLE record_type_str : STRING(1 to 2); + BEGIN + -- Read byte count + FOR i IN 1 TO 2 LOOP + READ(L, byte_count_str(i)); + END LOOP; + str_to_hex(byte_count_str, byte_count); + -- ASSERT debug; REPORT "DEBUG read_line_header: byte count is" & byte_count; SEVERITY NOTE; + -- Read address + FOR i IN 1 TO 4 LOOP + READ(L, address_str(i)); + END LOOP; + str_to_hex(address_str, address); + -- ASSERT debug; REPORT "DEBUG read_line_header: address is" & address; SEVERITY NOTE; + -- Read record type + FOR i IN 1 TO 2 LOOP + READ(L, record_type_str(i)); + END LOOP; + str_to_hex(record_type_str, record_type); + -- ASSERT debug; REPORT "DEBUG read_line_header: record type is" & recod_type; SEVERITY NOTE; + END read_line_header; + + + PROCEDURE read_instruction (L : INOUT LINE; instruction_hex : INOUT INTEGER) IS + VARIABLE instruction_str : STRING(1 TO 4); + VARIABLE instruction_str_tmp : STRING(1 TO 4); + VARIABLE ch : CHARACTER; + BEGIN + -- L pointer is pointing to the instruction we want to read + -- Thus, no need to update pointer + + -- Read instruction + FOR i IN 1 TO 4 LOOP + READ(L, instruction_str(i)); + END LOOP; + + -- Swap 2 lower and 2 higher byte: 1234 -> 3412 + instruction_str_tmp(1 TO 2) := instruction_str(1 to 2); + instruction_str(1 TO 2) := instruction_str(3 to 4); + instruction_str(3 TO 4) := instruction_str_tmp(1 TO 2); + str_to_hex(instruction_str, instruction_hex); + -- ASSERT debug; REPORT "DEBUG read_instruction: instruction " & instruction_no & "is " & instruction_hex; SEVERITY NOTE; + END read_instruction; + + + PROCEDURE read_ihex_file (program_name : IN STRING; memory : OUT program_array) IS + FILE program : TEXT open READ_MODE is program_name; + VARIABLE L : LINE; + VARIABLE byte_count : INTEGER := 0; + VARIABLE address : NATURAL := 0; + VARIABLE record_type : INTEGER := 0; + -- VARIABLE base_address : INTEGER := 0; + -- VARIABLE current_address : INTEGER := 0; + VARIABLE instruction : INTEGER := 0; + VARIABLE ch : CHARACTER; + BEGIN + WHILE NOT ENDFILE(program) LOOP + byte_count := 0; + address := 0; + record_type := 0; + + READLINE(program, L); + + -- Move line pointer over semicolon + READ(L, ch); + -- Read first byte count, address and record type on the line + read_line_header(L, byte_count, address, record_type); + + CASE record_type IS + + WHEN 0 => -- Data record + FOR i IN 1 TO byte_count/2 LOOP -- toimiiko jos byte count == 1? + read_instruction(L, instruction); + memory(address/2+i-1) := STD_LOGIC_VECTOR(to_unsigned(instruction, Inst_bits)); -- XXX + END LOOP; + + WHEN 1 => -- EOF record + NULL; + + WHEN 2 => -- Extended Segment Address Record + -- ASSERT 1; REPORT "Extended Segment Address record type 0x02 not implemented"; SEVERITY FAILURE; + + WHEN 3 => -- Start Segment Address Record + -- ASSERT 1; REPORT "Start Segment Address record type 0x03 not implemented"; SEVERITY FAILURE; + + WHEN 4 => -- + -- FOR i IN 0 TO 1 LOOP + read_instruction(L, instruction); + -- ASSERT (instruction /= 0); REPORT "Extended Linear Address Record not zero";SEVERITY FAILURE; + -- END LOOP; + + WHEN 5 => -- Start Linear Address Record + -- ASSERT 1; REPORT "Start Linear Address record type 0x05 not implemented"; SEVERITY FAILURE; + + WHEN OTHERS => + -- ASSERT 1; REPORT "Invalid Intel HEX format record type"; SEVERITY FAILURE; + + END CASE; + + END LOOP; -- Read file + END PROCEDURE read_ihex_file; + +END PACKAGE BODY read_intel_hex_pack; + +--PROCEDURE read_ihex_file (program_name : IN STRING; memory : OUT program_array) IS -- pitaako maaritella tyyppi muualla?? +-- FILE program : TEXT IS IN "/home/pro/autosub/erkka/digital/modelsim/" & program_name; -- saako program namen? +-- TYPE program_array IS ARRAY (0 TO inst_mem_size-1) OF STD_LOGIC_VECTOR(Inst_bits-1 DOWNTO 0); +-- VARIABLE L : LINE; +-- VARIABLE byte_count : INTEGER := 0; +-- VARIABLE address : INTEGER := 0; +-- VARIABLE record_type : INTEGER := 0; +-- VARIABLE base_address : INTEGER := 0; +-- -- VARIABLE current_address : INTEGER := 0; +-- VARIABLE instruction : INTEGER := 0; +--BEGIN +-- WHILE NOT ENDFILE(program) LOOP +-- READLINE(program, L); +-- read_line_header(L, byte_count, address, record_type); +-- +-- CASE record_type IS +-- +-- WHEN X"00" => -- Data record +-- FOR i IN 0 TO byte_count-1 LOOP -- toimiiko jos byte count == 1? +-- read_instruction(L, i, instruction); +-- program_array(address/2 + i) := instruction; -- tsekkaa +-- END LOOP; +-- +-- WHEN X"01" => -- EOF record +-- NULL; +-- +-- WHEN X"02" => -- Extended Segment Address Record +-- ASSERT 1; REPORT "Extended Segment Address record type 0x02 not implemented"; SEVERITY FAILURE; +-- +-- WHEN X"03" => -- Start Segment Address Record +-- ASSERT 1; REPORT "Start Segment Address record type 0x03 not implemented"; SEVERITY FAILURE; +-- +-- WHEN X"04" => -- +-- FOR i IN 0 TO 1 LOOP +-- read_instruction(L, i, instruction); +-- ASSERT (instruction /= 0); REPORT "Extended Linear Address Record not zero";SEVERITY FAILURE; +-- END LOOP; +-- +-- WHEN X"05" => -- Start Linear Address Record +-- ASSERT 1; REPORT "Start Linear Address record type 0x05 not implemented"; SEVERITY FAILURE; +-- +-- WHEN OTHERS => +-- ASSERT 1; REPORT "Invalid Intel HEX format record type"; SEVERITY FAILURE; +-- +-- END CASE; +-- +-- END LOOP; -- Read file +--END PROCESS read_ihex_file; +-- -- cgit v1.3