From e272019a2ef5a0b6c3a90c07db478be819421273 Mon Sep 17 00:00:00 2001 From: RobertPeip <53250236+RobertPeip@users.noreply.github.com> Date: Sat, 8 Aug 2020 16:53:38 +0200 Subject: [PATCH] add reset to cpu added more regs to reset for other modules added simulation some changes to be standard conform, mostly reordering of wire/reg defines --- rtl/amber/a23_cache.v | 8 +- rtl/amber/a23_coprocessor.v | 12 +- rtl/amber/a23_core.v | 5 + rtl/amber/a23_decode.v | 122 +++++----- rtl/amber/a23_execute.v | 76 ++++--- rtl/amber/a23_fetch.v | 8 +- rtl/amber/a23_register_bank.v | 58 ++++- rtl/amber/a23_wishbone.v | 21 +- rtl/archimedes_top.v | 1 + rtl/bram.vhd | 122 +++++----- rtl/fdc1772.v | 96 ++++---- rtl/floppy.v | 87 +++---- rtl/ioc.v | 62 +++-- rtl/ioc_irq.v | 22 +- rtl/memc.v | 70 +++--- rtl/vidc.v | 2 +- rtl/vidc_audio.v | 4 +- rtl/vidc_dmachannel.v | 2 +- rtl/vidc_fifo.v | 8 +- sim/cpu_export.vhd | 144 ++++++++++++ sim/globals.vhd | 13 ++ sim/lua_tests/run.lua | 40 ++++ sim/lualib/vsim_comm.lua | 418 ++++++++++++++++++++++++++++++++++ sim/readme.txt | 16 ++ sim/stringprocessor.vhd | 389 +++++++++++++++++++++++++++++++ sim/tb.vhd | 294 ++++++++++++++++++++++++ sim/vcom_all.bat | 50 ++++ sim/vsim_start.bat | 1 + 28 files changed, 1786 insertions(+), 365 deletions(-) create mode 100644 sim/cpu_export.vhd create mode 100644 sim/globals.vhd create mode 100644 sim/lua_tests/run.lua create mode 100644 sim/lualib/vsim_comm.lua create mode 100644 sim/readme.txt create mode 100644 sim/stringprocessor.vhd create mode 100644 sim/tb.vhd create mode 100644 sim/vcom_all.bat create mode 100644 sim/vsim_start.bat diff --git a/rtl/amber/a23_cache.v b/rtl/amber/a23_cache.v index d61b51b..170707d 100644 --- a/rtl/amber/a23_cache.v +++ b/rtl/amber/a23_cache.v @@ -82,6 +82,7 @@ parameter WORD_SEL_LSB = 2 // = ( input i_clk, +input i_reset, // Read / Write requests from core input i_select, @@ -210,19 +211,14 @@ assign o_stall = read_stall || write_stall || cache_busy_stall || ex_re assign o_wb_req = (( read_miss || write_miss ) && c_state == CS_IDLE ) || c_state == CS_WRITE_HIT1; -initial begin - c_state = CS_IDLE; - -end - // ====================================== // Cache State Machine // ====================================== // Little State Machine to Flush Tag RAMS always @ ( posedge i_clk ) - if ( i_cache_flush ) + if ( i_reset || i_cache_flush ) begin c_state <= CS_INIT; source_sel <= 1'd1 << C_INIT; diff --git a/rtl/amber/a23_coprocessor.v b/rtl/amber/a23_coprocessor.v index 39d434d..ea80cb4 100644 --- a/rtl/amber/a23_coprocessor.v +++ b/rtl/amber/a23_coprocessor.v @@ -41,6 +41,7 @@ module a23_coprocessor ( input i_clk, +input i_reset, input i_fetch_stall, // stall all stages of the cpu at the same time input [2:0] i_copro_opcode1, input [2:0] i_copro_opcode2, @@ -98,7 +99,10 @@ assign o_cacheable_area = cacheable_area; // Capture an access fault address and status // --------------------------- always @ ( posedge i_clk ) - if ( !i_fetch_stall ) + if (i_reset) begin + fault_status <= 'd0; + fault_address <= 'd0; + end else if ( !i_fetch_stall ) begin if ( i_fault ) begin @@ -117,6 +121,12 @@ always @ ( posedge i_clk ) // Register Writes // --------------------------- always @ ( posedge i_clk ) + if (i_reset) begin + cache_control <= 3'b000; + cacheable_area <= 32'h0; + updateable_area <= 32'h0; + disruptive_area <= 32'h0; + end else if ( !i_fetch_stall ) begin if ( i_copro_operation == 2'd2 ) diff --git a/rtl/amber/a23_core.v b/rtl/amber/a23_core.v index 415dac5..6cd8648 100644 --- a/rtl/amber/a23_core.v +++ b/rtl/amber/a23_core.v @@ -43,6 +43,7 @@ module a23_core ( input i_clk, + input i_reset, input i_irq, // Interrupt request, active high input i_firq, // Fast Interrupt request, active high @@ -162,6 +163,7 @@ assign decode_fault = dabt_trigger | iabt_trigger; a23_fetch u_fetch ( .i_clk ( i_clk ), + .i_reset ( i_reset ), .i_address ( execute_address[31:0] ), .i_address_valid ( execute_address_valid ), @@ -197,6 +199,7 @@ a23_fetch u_fetch ( a23_decode u_decode ( .i_clk ( i_clk ), + .i_reset ( i_reset ), // Instruction fetch or data read signals .i_read_data ( read_data ), @@ -276,6 +279,7 @@ a23_decode u_decode ( a23_execute u_execute ( .i_clk ( i_clk ), + .i_reset ( i_reset ), .i_read_data ( read_data_s2 ), .i_read_data_alignment ( read_data_alignment ), @@ -345,6 +349,7 @@ a23_execute u_execute ( a23_coprocessor u_coprocessor ( .i_clk ( i_clk ), + .i_reset ( i_reset ), .i_fetch_stall ( fetch_stall ), .i_copro_opcode1 ( copro_opcode1 ), diff --git a/rtl/amber/a23_decode.v b/rtl/amber/a23_decode.v index f4d8380..355b9a3 100644 --- a/rtl/amber/a23_decode.v +++ b/rtl/amber/a23_decode.v @@ -44,6 +44,7 @@ module a23_decode ( input i_clk, +input i_reset, input [31:0] i_read_data, input i_fetch_stall, // stall all stages of the cpu at the same time input i_fetch_abort, // abort the data transfer (instruction or data). @@ -1541,7 +1542,52 @@ assign instruction_valid = (control_state == EXECUTE || control_state == PRE_FET // Register Update // ======================================================== always @ ( posedge i_clk ) - if (!i_fetch_stall | i_fetch_abort) + if (i_reset) begin + control_state <= RST_WAIT1; + + o_read_data <= 1'd0; + o_read_data_alignment <= 1'd0; // 2 LSBs of read address used for calculating shift in LDRB ops + o_imm32 <= 32'd0; + o_imm_shift_amount <= 5'd0; + o_shift_imm_zero <= 1'd0; + o_condition <= 4'he; // 4'he = al + o_exclusive_exec <= 1'd0; // exclusive access request ( swap instruction ) + o_data_access_exec <= 1'd0; // high means the memory access is a read + o_status_bits_mode <= 2'b11; // SVC + o_status_bits_irq_mask <= 1'd1; + o_status_bits_firq_mask <= 1'd1; + o_rm_sel <= 4'd0; + o_rds_sel <= 4'd0; + o_rn_sel <= 4'd0; + o_barrel_shift_amount_sel <= 2'd0; + o_barrel_shift_data_sel <= 2'd0; + o_barrel_shift_function <= 2'd0; + o_alu_function <= 9'd0; + o_use_carry_in <= 1'd0; + o_multiply_function <= 2'd0; + o_interrupt_vector_sel <= 3'd0; + o_address_sel <= 4'd2; + o_pc_sel <= 2'd2; + o_byte_enable_sel <= 2'd0; // byte; halfword or word write + o_status_bits_sel <= 3'd0; + o_write_data_wen <= 1'd0; + o_base_address_wen <= 1'd0; // save LDM base address register + o_pc_wen <= 1'd0; + o_writeback_sel <= 1'd0; // force supervisor mode off for the memory cycle. + o_reg_bank_wen <= 15'd0; + o_reg_bank_wsel <= 4'd0; + o_status_bits_flags_wen <= 1'd0; + o_status_bits_mode_wen <= 1'd0; + o_status_bits_irq_mask_wen <= 1'd0; + o_status_bits_firq_mask_wen <= 1'd0; + o_copro_opcode1 <= 3'd0; + o_copro_opcode2 <= 3'd0; + o_copro_crn <= 4'd0; + o_copro_crm <= 4'd0; + o_copro_num <= 4'd0; + o_copro_operation <= 2'd0; // 0 = no operation; + o_copro_write_data_wen <= 1'd0; + end else if (!i_fetch_stall | i_fetch_abort) begin o_read_data <= i_read_data; o_read_data_alignment <= {i_execute_address[1:0], 3'd0}; @@ -1674,19 +1720,19 @@ assign dabt = dabt_reg || i_dabt; `include "debug_functions.v" -a23_decompile u_decompile ( - .i_clk ( i_clk ), - .i_fetch_stall ( i_fetch_stall ), - .i_instruction ( instruction ), - .i_instruction_valid ( instruction_valid ), - .i_instruction_execute ( instruction_execute ), - .i_instruction_address ( instruction_address ), - .i_interrupt ( {3{interrupt}} & next_interrupt ), - .i_interrupt_state ( control_state == INT_WAIT2 ), - .i_instruction_undefined ( und_request ), - .i_pc_sel ( o_pc_sel ), - .i_pc_wen ( o_pc_wen ) -); +//a23_decompile u_decompile ( +// .i_clk ( i_clk ), +// .i_fetch_stall ( i_fetch_stall ), +// .i_instruction ( instruction ), +// .i_instruction_valid ( instruction_valid ), +// .i_instruction_execute ( instruction_execute ), +// .i_instruction_address ( instruction_address ), +// .i_interrupt ( {3{interrupt}} & next_interrupt ), +// .i_interrupt_state ( control_state == INT_WAIT2 ), +// .i_instruction_undefined ( und_request ), +// .i_pc_sel ( o_pc_sel ), +// .i_pc_wen ( o_pc_wen ) +//); wire [(15*8)-1:0] xCONTROL_STATE; @@ -1731,52 +1777,4 @@ always @( posedge i_clk ) end //synopsys translate_on -initial begin - - o_read_data = 1'd0; - o_read_data_alignment = 1'd0; // 2 LSBs of read address used for calculating shift in LDRB ops - o_imm32 = 32'd0; - o_imm_shift_amount = 5'd0; - o_shift_imm_zero = 1'd0; - o_condition = 4'he; // 4'he = al - o_exclusive_exec = 1'd0; // exclusive access request ( swap instruction ) - o_data_access_exec = 1'd0; // high means the memory access is a read - o_status_bits_mode = 2'b11; // SVC - o_status_bits_irq_mask = 1'd1; - o_status_bits_firq_mask = 1'd1; - o_rm_sel = 4'd0; - o_rds_sel = 4'd0; - o_rn_sel = 4'd0; - o_barrel_shift_amount_sel = 2'd0; - o_barrel_shift_data_sel = 2'd0; - o_barrel_shift_function = 2'd0; - o_alu_function = 9'd0; - o_use_carry_in = 1'd0; - o_multiply_function = 2'd0; - o_interrupt_vector_sel = 3'd0; - o_address_sel = 4'd2; - o_pc_sel = 2'd2; - o_byte_enable_sel = 2'd0; // byte; halfword or word write - o_status_bits_sel = 3'd0; - o_write_data_wen = 1'd0; - o_base_address_wen = 1'd0; // save LDM base address register - o_pc_wen = 1'd1; - o_writeback_sel = 1'd0; // force supervisor mode off for the memory cycle. - o_reg_bank_wen = 15'd0; - o_reg_bank_wsel = 4'd0; - o_status_bits_flags_wen = 1'd0; - o_status_bits_mode_wen = 1'd0; - o_status_bits_irq_mask_wen = 1'd0; - o_status_bits_firq_mask_wen = 1'd0; - o_copro_opcode1 = 3'd0; - o_copro_opcode2 = 3'd0; - o_copro_crn = 4'd0; - o_copro_crm = 4'd0; - o_copro_num = 4'd0; - o_copro_operation = 2'd0; // 0 = no operation; - o_copro_write_data_wen = 1'd0; - -end endmodule - - diff --git a/rtl/amber/a23_execute.v b/rtl/amber/a23_execute.v index 6e67cc3..6cae3bc 100644 --- a/rtl/amber/a23_execute.v +++ b/rtl/amber/a23_execute.v @@ -46,6 +46,7 @@ module a23_execute ( input i_clk, +input i_reset, input [31:0] i_read_data, input [4:0] i_read_data_alignment, // 2 LSBs of address in [4:3], appended // with 3 zeros @@ -452,28 +453,43 @@ assign status_bits_mode_nr = status_bits_mode_update ? statu status_bits_mode ; always @( posedge i_clk ) - begin - o_priviledged <= priviledged_update ? priviledged_nxt : o_priviledged; - o_exclusive <= exclusive_update ? i_exclusive_exec : o_exclusive; - o_data_access <= data_access_update ? i_data_access_exec : o_data_access; - o_write_enable <= write_enable_update ? write_enable_nxt : o_write_enable; - o_write_data <= write_data_update ? write_data_nxt : o_write_data; - o_address <= address_update ? o_address_nxt : o_address; - o_adex <= address_update ? adex_nxt : o_adex; - o_address_valid <= address_update ? 1'd1 : o_address_valid; - o_translate <= translate_update ? ~i_writeback_sel & (status_bits_mode != USR) : o_translate; - o_byte_enable <= byte_enable_update ? byte_enable_nxt : o_byte_enable; - o_copro_write_data <= copro_write_data_update ? write_data_nxt : o_copro_write_data; - - base_address <= base_address_update ? rn : base_address; - - status_bits_flags <= status_bits_flags_update ? status_bits_flags_nxt : status_bits_flags; - status_bits_mode <= status_bits_mode_nr; - status_bits_mode_rds_oh <= status_bits_mode_rds_oh_update ? status_bits_mode_rds_oh_nxt : status_bits_mode_rds_oh; - status_bits_mode_rds <= status_bits_mode_rds_nr; - status_bits_irq_mask <= status_bits_irq_mask_update ? status_bits_irq_mask_nxt : status_bits_irq_mask; - status_bits_firq_mask <= status_bits_firq_mask_update ? status_bits_firq_mask_nxt : status_bits_firq_mask; +begin + + if (i_reset) begin + o_copro_write_data <= 32'd0; + o_write_data <= 32'd0; + o_address <= 32'hdead_dead; + o_adex <= 1'd0; // Address Exception + o_address_valid <= 1'd0; // Prevents the reset address value being a + o_priviledged <= 1'd0; // Priviledged access + o_exclusive <= 1'd0; // swap access + o_write_enable <= 1'd0; + o_translate <= 1'd0; + o_byte_enable <= 4'd0; + o_data_access <= 1'd0; // To Fetch stage. high = data fetch; + end else begin + o_priviledged <= priviledged_update ? priviledged_nxt : o_priviledged; + o_exclusive <= exclusive_update ? i_exclusive_exec : o_exclusive; + o_data_access <= data_access_update ? i_data_access_exec : o_data_access; + o_write_enable <= write_enable_update ? write_enable_nxt : o_write_enable; + o_write_data <= write_data_update ? write_data_nxt : o_write_data; + o_address <= address_update ? o_address_nxt : o_address; + o_adex <= address_update ? adex_nxt : o_adex; + o_address_valid <= address_update ? 1'd1 : o_address_valid; + o_translate <= translate_update ? ~i_writeback_sel & (status_bits_mode != USR) : o_translate; + o_byte_enable <= byte_enable_update ? byte_enable_nxt : o_byte_enable; + o_copro_write_data <= copro_write_data_update ? write_data_nxt : o_copro_write_data; + + base_address <= base_address_update ? rn : base_address; + + status_bits_flags <= status_bits_flags_update ? status_bits_flags_nxt : status_bits_flags; + status_bits_mode <= status_bits_mode_nr; + status_bits_mode_rds_oh <= status_bits_mode_rds_oh_update ? status_bits_mode_rds_oh_nxt : status_bits_mode_rds_oh; + status_bits_mode_rds <= status_bits_mode_rds_nr; + status_bits_irq_mask <= status_bits_irq_mask_update ? status_bits_irq_mask_nxt : status_bits_irq_mask; + status_bits_firq_mask <= status_bits_firq_mask_update ? status_bits_firq_mask_nxt : status_bits_firq_mask; end +end // ======================================================== @@ -536,7 +552,8 @@ a23_multiply u_multiply ( `ifndef A23_RAM_REGISTER_BANK a23_register_bank u_register_bank( .i_clk ( i_clk ), - .i_fetch_stall ( fetch_stall ), + .i_reset ( i_reset ), + .i_fetch_stall ( fetch_stall ), .i_rm_sel ( i_rm_sel ), .i_rds_sel ( i_rds_sel ), .i_rn_sel ( i_rn_sel ), @@ -627,21 +644,6 @@ assign xMODE = status_bits_mode == SVC ? "SVC" : //synopsys translate_on -initial begin - - o_copro_write_data = 32'd0; - o_write_data = 32'd0; - o_address = 32'hdead_dead; - o_adex = 1'd0; // Address Exception - o_address_valid = 1'd0; // Prevents the reset address value being a - o_priviledged = 1'd0; // Priviledged access - o_exclusive = 1'd0; // swap access - o_write_enable = 1'd0; - o_translate = 1'd0; - o_byte_enable = 4'd0; - o_data_access = 1'd0; // To Fetch stage. high = data fetch; - -end endmodule diff --git a/rtl/amber/a23_fetch.v b/rtl/amber/a23_fetch.v index ad15f5c..872edc7 100644 --- a/rtl/amber/a23_fetch.v +++ b/rtl/amber/a23_fetch.v @@ -45,6 +45,7 @@ module a23_fetch ( input i_clk, +input i_reset, input [31:0] i_address, input i_address_valid, @@ -90,6 +91,8 @@ wire sel_wb; wire cache_wb_req; wire address_cachable; +wire wb_abort; + // ====================================== // Memory Decode // ====================================== @@ -117,6 +120,7 @@ assign o_fetch_abort = wb_abort; // ====================================== a23_cache u_cache ( .i_clk ( i_clk ), + .i_reset ( i_reset ), .i_select ( sel_cache ), .i_exclusive ( i_exclusive ), @@ -137,15 +141,13 @@ a23_cache u_cache ( .i_wb_stall ( o_wb_stb & ~i_wb_ack ) ); - -wire wb_abort; - // ====================================== // Wishbone Master I/F // ====================================== a23_wishbone u_wishbone ( // CPU Side .i_clk ( i_clk ), + .i_reset ( i_reset ), // Core Accesses to Wishbone bus .i_select ( sel_wb ), diff --git a/rtl/amber/a23_register_bank.v b/rtl/amber/a23_register_bank.v index bf70724..39f593c 100644 --- a/rtl/amber/a23_register_bank.v +++ b/rtl/amber/a23_register_bank.v @@ -44,6 +44,7 @@ module a23_register_bank ( input i_clk, +input i_reset, input i_fetch_stall, input [1:0] i_mode_idec, // user, supervisor, irq_idec, firq_idec etc. @@ -171,7 +172,36 @@ assign firq_exec = i_mode_exec == FIRQ; // Register Update // ======================================================== always @ ( posedge i_clk ) - if (!i_fetch_stall) + if (i_reset) begin + r0 <= 32'hdead_beef; + r1 <= 32'hdead_beef; + r2 <= 32'hdead_beef; + r3 <= 32'hdead_beef; + r4 <= 32'hdead_beef; + r5 <= 32'hdead_beef; + r6 <= 32'hdead_beef; + r7 <= 32'hdead_beef; + r8 <= 32'hdead_beef; + r9 <= 32'hdead_beef; + r10 <= 32'hdead_beef; + r11 <= 32'hdead_beef; + r12 <= 32'hdead_beef; + r8_firq <= 32'hdead_beef; + r9_firq <= 32'hdead_beef; + r10_firq <= 32'hdead_beef; + r11_firq <= 32'hdead_beef; + r12_firq <= 32'hdead_beef; + r13 <= 32'hdead_beef; + r14 <= 32'hdead_beef; + r13_svc <= 32'hdead_beef; + r14_svc <= 32'hdead_beef; + r13_irq <= 32'hdead_beef; + r14_irq <= 32'hdead_beef; + r13_firq <= 32'hdead_beef; + r14_firq <= 32'hdead_beef; + r15 <= 24'h00_0000; + + end else if (!i_fetch_stall) begin r0 <= i_reg_bank_wen[0 ] ? i_reg : r0; r1 <= i_reg_bank_wen[1 ] ? i_reg : r1; @@ -369,6 +399,32 @@ assign o_rn = i_rn_sel == 4'd0 ? r0_out : r15_out_rn ; +// synthesis translate_off +cpu_export cpu_export_inst( + .clk (i_clk), + .rst (i_reset), + .new_export (1'b1), + //.commandcount (), + + .R0 (r0 ), + .R1 (r1 ), + .R2 (r2 ), + .R3 (r3 ), + .R4 (r4 ), + .R5 (r5 ), + .R6 (r6 ), + .R7 (r7 ), + .R8 (r8 ), + .R9 (r9 ), + .R10 (r10), + .R11 (r11), + .R12 (r12), + .R13 (r13), + .R14 (r14), + .R15 ({ 8'd0 , r15 }) +); +// synthesis translate_on + endmodule diff --git a/rtl/amber/a23_wishbone.v b/rtl/amber/a23_wishbone.v index 8467bb1..01b06e0 100644 --- a/rtl/amber/a23_wishbone.v +++ b/rtl/amber/a23_wishbone.v @@ -58,6 +58,7 @@ module a23_wishbone ( input i_clk, +input i_reset, // Core Accesses to Wishbone bus input i_select, @@ -171,6 +172,15 @@ assign wait_write_ack = o_wb_stb && o_wb_we && !i_wb_ack; always @( posedge i_clk ) + if (i_reset) begin + wishbone_st <= WB_IDLE; + o_wb_adr <= 32'd0; + o_wb_sel <= 4'd0; + o_wb_we <= 1'd0; + o_wb_cyc <= 1'd0; + o_wb_stb <= 1'd0; + o_wb_tga <= 1'b0; + end else case ( wishbone_st ) WB_IDLE : begin @@ -306,16 +316,5 @@ assign xAS_STATE = wishbone_st == WB_IDLE ? "WB_IDLE" : //synopsys translate_on -initial begin - - o_wb_adr = 32'd0; - o_wb_sel = 4'd0; - o_wb_we = 1'd0; - o_wb_dat = 32'd0; - o_wb_cyc = 1'd0; - o_wb_stb = 1'd0; - o_wb_tga = 1'b0; - -end endmodule diff --git a/rtl/archimedes_top.v b/rtl/archimedes_top.v index 4b32556..b61b031 100644 --- a/rtl/archimedes_top.v +++ b/rtl/archimedes_top.v @@ -133,6 +133,7 @@ wire [5:0] ioc_cin, ioc_cout; a23_core ARM( .i_clk ( CLKCPU_I ), + .i_reset ( RESET_I ), .o_wb_cyc ( cpu_cyc ), .o_wb_stb ( cpu_stb ), diff --git a/rtl/bram.vhd b/rtl/bram.vhd index e24bbd9..e1b1d6a 100644 --- a/rtl/bram.vhd +++ b/rtl/bram.vhd @@ -1,41 +1,3 @@ --------------------------------------------------------------- --- Single port Block RAM --------------------------------------------------------------- - -LIBRARY ieee; -USE ieee.std_logic_1164.all; - -LIBRARY altera_mf; -USE altera_mf.altera_mf_components.all; - -ENTITY spram IS - generic ( - addr_width : integer := 8; - data_width : integer := 8; - mem_init_file : string := " "; - mem_name : string := "MEM" -- for InSystem Memory content editor. - ); - PORT - ( - clock : in STD_LOGIC; - address : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0); - data : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0'); - enable : in STD_LOGIC := '1'; - wren : in STD_LOGIC := '0'; - q : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0); - cs : in std_logic := '1' - ); -END spram; - - -ARCHITECTURE SYN OF spram IS -BEGIN - spram_sz : work.spram_sz - generic map(addr_width, data_width, 2**addr_width, mem_init_file, mem_name) - port map(clock,address,data,enable,wren,q,cs); -END SYN; - - -------------------------------------------------------------- -- Single port Block RAM with specific size -------------------------------------------------------------- @@ -51,7 +13,7 @@ ENTITY spram_sz IS addr_width : integer := 8; data_width : integer := 8; numwords : integer := 2**8; - mem_init_file : string := " "; + mem_init_file : string := "UNUSED"; mem_name : string := "MEM" -- for InSystem Memory content editor. ); PORT @@ -100,45 +62,40 @@ BEGIN END SYN; -------------------------------------------------------------- --- Dual port Block RAM same parameters on both ports +-- Single port Block RAM -------------------------------------------------------------- + LIBRARY ieee; USE ieee.std_logic_1164.all; LIBRARY altera_mf; USE altera_mf.altera_mf_components.all; -entity dpram is +ENTITY spram IS generic ( addr_width : integer := 8; data_width : integer := 8; - mem_init_file : string := " " + mem_init_file : string := "UNUSED"; + mem_name : string := "MEM" -- for InSystem Memory content editor. ); PORT ( - clock : in STD_LOGIC; - - address_a : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0); - data_a : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0'); - enable_a : in STD_LOGIC := '1'; - wren_a : in STD_LOGIC := '0'; - q_a : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0); - cs_a : in std_logic := '1'; - - address_b : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0) := (others => '0'); - data_b : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0'); - enable_b : in STD_LOGIC := '1'; - wren_b : in STD_LOGIC := '0'; - q_b : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0); - cs_b : in std_logic := '1' + clock : in STD_LOGIC; + address : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0); + data : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0'); + enable : in STD_LOGIC := '1'; + wren : in STD_LOGIC := '0'; + q : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0); + cs : in std_logic := '1' ); -end entity; +END spram; -ARCHITECTURE SYN OF dpram IS +ARCHITECTURE SYN OF spram IS BEGIN - ram : work.dpram_dif generic map(addr_width,data_width,addr_width,data_width,mem_init_file) - port map(clock,address_a,data_a,enable_a,wren_a,q_a,cs_a,address_b,data_b,enable_b,wren_b,q_b,cs_b); + spram_sz : entity work.spram_sz + generic map(addr_width, data_width, 2**addr_width, mem_init_file, mem_name) + port map(clock,address,data,enable,wren,q,cs); END SYN; -------------------------------------------------------------- @@ -156,7 +113,7 @@ entity dpram_dif is data_width_a : integer := 8; addr_width_b : integer := 8; data_width_b : integer := 8; - mem_init_file : string := " " + mem_init_file : string := "UNUSED" ); PORT ( @@ -234,3 +191,44 @@ BEGIN END SYN; +-------------------------------------------------------------- +-- Dual port Block RAM same parameters on both ports +-------------------------------------------------------------- +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.altera_mf_components.all; + +entity dpram is + generic ( + addr_width : integer := 8; + data_width : integer := 8; + mem_init_file : string := "UNUSED" + ); + PORT + ( + clock : in STD_LOGIC; + + address_a : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0); + data_a : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0'); + enable_a : in STD_LOGIC := '1'; + wren_a : in STD_LOGIC := '0'; + q_a : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0); + cs_a : in std_logic := '1'; + + address_b : in STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0) := (others => '0'); + data_b : in STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0'); + enable_b : in STD_LOGIC := '1'; + wren_b : in STD_LOGIC := '0'; + q_b : out STD_LOGIC_VECTOR (data_width-1 DOWNTO 0); + cs_b : in std_logic := '1' + ); +end entity; + + +ARCHITECTURE SYN OF dpram IS +BEGIN + ram : entity work.dpram_dif generic map(addr_width,data_width,addr_width,data_width,mem_init_file) + port map(clock,address_a,data_a,enable_a,wren_a,q_a,cs_a,address_b,data_b,enable_b,wren_b,q_b,cs_b); +END SYN; diff --git a/rtl/fdc1772.v b/rtl/fdc1772.v index f523a0f..824b97c 100644 --- a/rtl/fdc1772.v +++ b/rtl/fdc1772.v @@ -52,7 +52,7 @@ module fdc1772 #(parameter CLK) input [1:0] img_mounted, // signaling that new image has been mounted input img_wp, // write protect. latched at img_mounted input [31:0] img_size, // size of image in bytes - output reg[31:0] sd_lba, + output reg[31:0] sd_lba = 32'd0, output reg [1:0] sd_rd, output reg [1:0] sd_wr, input sd_ack, @@ -64,6 +64,48 @@ module fdc1772 #(parameter CLK) localparam CLK_EN = 8000000; +localparam FDC_REG_CMDSTATUS = 0; +localparam FDC_REG_TRACK = 1; +localparam FDC_REG_SECTOR = 2; +localparam FDC_REG_DATA = 3; + +reg step_in, step_out; +reg [7:0] cmd; + +reg [1:0] sd_state; +reg sd_card_write; +reg sd_card_read; +reg sd_card_done; + +// floppy delivers data at a floppy generated rate (usually 250kbit/s), so the start and stop +// signals need to be passed forth and back from cpu clock domain to floppy data clock domain +reg data_transfer_start; +reg data_transfer_done; + +// cpu register write +reg cmd_rx; +reg cmd_rx_i; +reg last_stb; +reg data_in_strobe; + +wire cmd_type_1 = (cmd[7] == 1'b0); +wire cmd_type_2 = (cmd[7:6] == 2'b10); +wire cmd_type_3 = (cmd[7:5] == 3'b111) || (cmd[7:4] == 4'b1100); +//wire cmd_type_4 = (cmd[7:4] == 4'b1101); + +// 1 kB buffer used to receive a sector as fast as possible from from the io +// controller. The internal transfer afterwards then runs at 250000 Bit/s +reg [10:0] fifo_cpuptr = 11'd0; +wire [7:0] fifo_q; + +reg [7:0] track; +reg [7:0] sector; +reg [7:0] data_in = 8'd0; +reg [7:0] data_out; + +reg step_dir; +reg motor_on; + // ------------------------------------------------------------------------- // --------------------- IO controller status handling --------------------- // ------------------------------------------------------------------------- @@ -77,7 +119,7 @@ wire floppy_present = (floppy_drive == 4'b1110)?floppy_ready[0]: wire floppy_write_protected = (floppy_drive == 4'b1110)?floppy_wp[0]: (floppy_drive == 4'b1101)?floppy_wp[1]:1'd1; -always @(posedge clkcpu) begin +always @(posedge clkcpu) begin : block reg [1:0] img_mountedD; img_mountedD <= img_mounted; @@ -105,7 +147,7 @@ always @(posedge clkcpu) wire irq_clr = !floppy_reset || cpu_read_status; -always @(posedge clkcpu or posedge irq_clr) begin +always @(posedge clkcpu or posedge irq_clr) begin : block2 reg irq_setD; if(irq_clr) irq <= 1'b0; @@ -321,7 +363,6 @@ localparam [3:0] MOTOR_IDLE_COUNTER = 10; reg [3:0] motor_timeout_index; reg indexD; reg busy; -reg step_in, step_out; reg [3:0] motor_spin_up_sequence; // consider spin up done either if the motor is not supposed to spin at all or @@ -347,7 +388,7 @@ reg [15:0] step_rate_cnt; wire step_busy = (step_rate_cnt != 0); reg [7:0] step_to; -always @(posedge clkcpu) begin +always @(posedge clkcpu) begin : block3 reg data_transfer_can_start; if(!floppy_reset) begin @@ -500,18 +541,8 @@ always @(posedge clkcpu) begin end end -// floppy delivers data at a floppy generated rate (usually 250kbit/s), so the start and stop -// signals need to be passed forth and back from cpu clock domain to floppy data clock domain -reg data_transfer_start; -reg data_transfer_done; - // ==================================== FIFO ================================== -// 1 kB buffer used to receive a sector as fast as possible from from the io -// controller. The internal transfer afterwards then runs at 250000 Bit/s -reg [10:0] fifo_cpuptr; -wire [7:0] fifo_q; - dpram_dif #(9,16,10,8) fifo ( .clock(clkcpu), @@ -521,7 +552,7 @@ dpram_dif #(9,16,10,8) fifo .wren_a(sd_buff_wr & sd_ack), .q_a(sd_buff_din), - .address_b(fifo_cpuptr), + .address_b(fifo_cpuptr[9:0]), .data_b(data_in), .wren_b(data_in_strobe), .q_b(fifo_q) @@ -532,12 +563,7 @@ localparam SD_IDLE = 0; localparam SD_READ = 1; localparam SD_WRITE = 2; -reg [1:0] sd_state; -reg sd_card_write; -reg sd_card_read; -reg sd_card_done; - -always @(posedge clkcpu) begin +always @(posedge clkcpu) begin : block4 reg sd_ackD; reg sd_card_readD; reg sd_card_writeD; @@ -599,7 +625,7 @@ end // -------------------- CPU data read/write ----------------------- -always @(posedge clkcpu) begin +always @(posedge clkcpu) begin : block5 reg data_transfer_startD; reg [10:0] data_transfer_cnt; @@ -669,25 +695,7 @@ wire [7:0] status = { motor_on, cmd_type_1?~fd_index:floppy_drq, busy } /* synthesis keep */; -reg [7:0] track; -reg [7:0] sector; -reg [7:0] data_in; -reg [7:0] data_out; - -reg step_dir; -reg motor_on; - // ---------------------------- command register ----------------------- -reg [7:0] cmd; -wire cmd_type_1 = (cmd[7] == 1'b0); -wire cmd_type_2 = (cmd[7:6] == 2'b10); -wire cmd_type_3 = (cmd[7:5] == 3'b111) || (cmd[7:4] == 4'b1100); -//wire cmd_type_4 = (cmd[7:4] == 4'b1101); - -localparam FDC_REG_CMDSTATUS = 0; -localparam FDC_REG_TRACK = 1; -localparam FDC_REG_SECTOR = 2; -localparam FDC_REG_DATA = 3; // CPU register read always @(*) begin @@ -703,12 +711,6 @@ always @(*) begin end end -// cpu register write -reg cmd_rx; -reg cmd_rx_i; -reg last_stb; -reg data_in_strobe; - always @(posedge clkcpu) begin if(!floppy_reset) begin // clear internal registers diff --git a/rtl/floppy.v b/rtl/floppy.v index 8ad5005..a74e202 100644 --- a/rtl/floppy.v +++ b/rtl/floppy.v @@ -39,9 +39,6 @@ module floppy ( // Default: 8 MHz parameter SYS_CLK = 8000000; -assign sector_hdr = (sec_state == SECTOR_STATE_HDR); -assign sector_data = (sec_state == SECTOR_STATE_DATA); - // a standard DD floppy has a data rate of 250kBit/s and rotates at 300RPM localparam RATE = 250000; localparam RPM = 300; @@ -56,12 +53,56 @@ localparam TRACKS = 85; // max allowed track localparam SECTOR_LEN = 1024; // Default sector size is 1k on Archie ... localparam SPT = 5; // ... with 5 sectors per track localparam SECTOR_BASE = 0; // number of first sector on track (archie 0, dos 1) - + // number of physical bytes per track localparam BPT = RATE*60/(8*RPM); +// track has BPT bytes +// SPT sectors are stored on the track +localparam SECTOR_GAP_LEN = BPT/SPT - (SECTOR_LEN + SECTOR_HDR_LEN); + +reg [1:0] sec_state; +reg [9:0] sec_byte_cnt; // counting bytes within sectors +reg [3:0] current_sector = SECTOR_BASE[3:0]; + +assign sector = current_sector; + +localparam SECTOR_STATE_GAP = 2'd0; +localparam SECTOR_STATE_HDR = 2'd1; +localparam SECTOR_STATE_DATA = 2'd2; + +// we simulate an interleave of 1 +reg [3:0] start_sector = SECTOR_BASE[3:0]; + +assign sector_hdr = (sec_state == SECTOR_STATE_HDR); +assign sector_data = (sec_state == SECTOR_STATE_DATA); + +// data rate determines rotation speed +reg [31:0] rate = 0; +reg motor_onD; + +localparam STEP_BUSY_CLKS = (SYS_CLK/1000)*STEPBUSY; // steprate is in ms + +reg [6:0] current_track = 7'd0; +assign track = current_track; + +reg step_inD; +reg step_outD; +reg [19:0] step_busy; + // report disk ready if it spins at full speed and head is not moving assign ready = select && (rate == RATE) && (step_busy == 0); + +reg data_clk; +reg data_clk_en; +reg [31:0] clk_cnt; + +// byte clock +reg [14:0] byte_cnt; +reg index_pulse_start; +reg byte_clk_en; +assign dclk_en = byte_clk_en; +reg [2:0] clk_cnt2; // ================================================================ // ========================= INDEX PULSE ========================== @@ -84,15 +125,6 @@ end // ================================================================ // ======================= track handling ========================= // ================================================================ - -localparam STEP_BUSY_CLKS = (SYS_CLK/1000)*STEPBUSY; // steprate is in ms - -assign track = current_track; -reg [6:0] current_track = 7'd0; - -reg step_inD; -reg step_outD; -reg [19:0] step_busy; always @(posedge clk) begin step_inD <= step_in; @@ -118,23 +150,6 @@ end // ================================================================ // ====================== sector handling ========================= // ================================================================ - -// track has BPT bytes -// SPT sectors are stored on the track -localparam SECTOR_GAP_LEN = BPT/SPT - (SECTOR_LEN + SECTOR_HDR_LEN); - -assign sector = current_sector; - -localparam SECTOR_STATE_GAP = 2'd0; -localparam SECTOR_STATE_HDR = 2'd1; -localparam SECTOR_STATE_DATA = 2'd2; - -// we simulate an interleave of 1 -reg [3:0] start_sector = SECTOR_BASE[3:0]; - -reg [1:0] sec_state; -reg [9:0] sec_byte_cnt; // counting bytes within sectors -reg [3:0] current_sector = SECTOR_BASE[3:0]; always @(posedge clk) begin if (byte_clk_en) begin @@ -181,8 +196,6 @@ end // An ed floppy at 300rpm with 1MBit/s has max 31.250 bytes/track // thus we need to support up to 31250 events -reg [14:0] byte_cnt; -reg index_pulse_start; always @(posedge clk) begin if (byte_clk_en) begin index_pulse_start <= 1'b0; @@ -197,9 +210,6 @@ end // Make byte clock from bit clock. // When a DD disk spins at 300RPM every 32us a byte passes the disk head -assign dclk_en = byte_clk_en; -reg byte_clk_en; -reg [2:0] clk_cnt2; always @(posedge clk) begin byte_clk_en <= 0; if (data_clk_en) begin @@ -220,10 +230,6 @@ reg [31:0] spin_up_counter; // internal motor on signal that is only true if the drive is selected wire motor_on_sel = motor_on && select; - -// data rate determines rotation speed -reg [31:0] rate = 0; -reg motor_onD; always @(posedge clk) begin motor_onD <= motor_on_sel; @@ -255,9 +261,6 @@ end // Generate a data clock from the system clock. This depends on motor // speed and reaches the full rate when the disk rotates at 300RPM. No // valid data can be read until the disk has reached it's full speed. -reg data_clk; -reg data_clk_en; -reg [31:0] clk_cnt; always @(posedge clk) begin data_clk_en <= 0; if(clk_cnt + rate > SYS_CLK/2) begin diff --git a/rtl/ioc.v b/rtl/ioc.v index 33d01c0..fdaee85 100644 --- a/rtl/ioc.v +++ b/rtl/ioc.v @@ -114,6 +114,7 @@ wire ir_edge; ) IRQA ( .clkcpu ( clkcpu ), + .reset ( por ), .i ( {1'b1, timer[1].reload, timer[0].reload, por, ir_edge, 3'b000}), .irq ( irqa_req ), @@ -133,6 +134,7 @@ wire ir_edge; ) IRQB ( .clkcpu ( clkcpu ), + .reset ( por ), .i ( { kbd_in_irq, txdone, ~il[5:0]}), .c ( {!kbd_in_irq, ~txdone, il[5:0]}), @@ -152,6 +154,7 @@ wire ir_edge; ) FIRQ ( .clkcpu ( clkcpu ), + .reset ( por ), .i ( {6'h00, fh[1:0]} ), .c ( {6'h00, ~fh[1:0]}), @@ -224,48 +227,39 @@ generate endgenerate -initial begin - - ctrl_state = 6'h3F; - - ir_r = 1'b1; - -end - - - // here we generate the ack signal and the 2mhz enable. always @(posedge clkcpu) begin - // generate strobe one clock cycle after data has been latched - kbd_out_strobe <= !txdone; - kbd_in_irq_ack <= serial_selected && read_request; + if (por) begin + ctrl_state <= 6'h3F; + ir_r <= 1'b1; + end else begin + // generate strobe one clock cycle after data has been latched + kbd_out_strobe <= !txdone; + kbd_in_irq_ack <= serial_selected && read_request; - ir_r <= ir; - - if (!txdone &&(timer[3].reload)) begin - - txcount <= txcount - 4'd1; - - end + ir_r <= ir; - // increment the clock counter. 42 MHz clkcpu assumed. - clken_counter <= clken_counter + 1'd1; - if (clken_counter == 20) clken_counter <= 0; + if (!txdone &&(timer[3].reload)) begin + txcount <= txcount - 4'd1; + end - if (write_request & ctrl_selected) begin - - ctrl_state <= wb_dat_i[5:0]; - + // increment the clock counter. 42 MHz clkcpu assumed. + clken_counter <= clken_counter + 1'd1; + if (clken_counter == 20) clken_counter <= 0; + + if (write_request & ctrl_selected) begin + ctrl_state <= wb_dat_i[5:0]; + end + + if (write_request & serial_selected) begin + // simulate a serial port write to the console. + kbd_out_strobe <= 1'b0; + kbd_out_data <= wb_dat_i[7:0]; + txcount <= 5'd20; + end end - if (write_request & serial_selected) begin - // simulate a serial port write to the console. - kbd_out_strobe <= 1'b0; - kbd_out_data <= wb_dat_i[7:0]; - txcount <= 5'd20; - end - end diff --git a/rtl/ioc_irq.v b/rtl/ioc_irq.v index 6a1246f..45134fc 100644 --- a/rtl/ioc_irq.v +++ b/rtl/ioc_irq.v @@ -34,6 +34,7 @@ ( input clkcpu, // cpu bus clock domain + input reset, input [7:0] i, input [7:0] c, @@ -55,16 +56,19 @@ wire selected = ~addr[6] & (addr[5:4] == ADDRESS); always @(posedge clkcpu) begin - status <= status & CANCLEAR | status & ~CANCLEAR & ~c | i | PERMBITS; - - if (selected & write) begin - - if (addr[3:2] == 2'b10) mask <= din; - - if (addr[3:2] == 2'b01) begin - status <= (status & ~CANCLEAR) | (status & ~din & CANCLEAR) | PERMBITS; + if (reset) begin + mask <= 8'h00; + status <= 8'h00; + end else begin + + status <= status & CANCLEAR | status & ~CANCLEAR & ~c | i | PERMBITS; + + if (selected & write) begin + if (addr[3:2] == 2'b10) mask <= din; + if (addr[3:2] == 2'b01) begin + status <= (status & ~CANCLEAR) | (status & ~din & CANCLEAR) | PERMBITS; + end end - end end diff --git a/rtl/memc.v b/rtl/memc.v index 1d4adea..51f05ba 100644 --- a/rtl/memc.v +++ b/rtl/memc.v @@ -144,41 +144,31 @@ memc_translator PAGETABLES( .addr_o ( phys_address ), .valid ( table_valid ) ); - -initial begin - // start with rom overlay - rom_overlay = 1'b1; - - // memc state registers - vid_load = 1'b0; - snd_load = 1'b0; - cur_load = 1'b0; - cpu_load = 1'b0; - - // sound init. - snd_next_valid = 1'b0; - dma_request_r = 1'b0; - // video init. - dma_ack_r = 4'd0; - - // initial cursor and video addresses - vid_init = INITIAL_SCREEN_BASE; - cur_init = INITIAL_CURSOR_BASE; - - vid_start = INITIAL_SCREEN_BASE; - vid_end = INITIAL_SCREEN_BASE + INITIAL_SCREEN_SIZE; - -end - -reg [31:0] cache_data[4]; +reg [31:0] cache_data[0:3]; reg cache_valid; reg [23:4] cache_addr; reg cache_ack; +wire logcs = cpu_address[25] == 1'b0; // 0000000-&1FFFFFF + +wire [21:2] ram_page = memc_control[3:2] == 2'b00 ? {3'd0, cpu_address[18:2]}: + memc_control[3:2] == 2'b01 ? {2'd0, cpu_address[19:2]} : + memc_control[3:2] == 2'b10 ? {1'd0, cpu_address[20:2]} : cpu_address[21:2]; + + +wire [23:2] caddr = phycs ? {2'd0, ram_page} : // use physical memory + romcs ? {3'b010, cpu_address[20:2]} : // use 2mb and up for rom space. + table_valid & logcs ? phys_address[23:2] : 22'd0; // use logical memory. + + assign cpu_dout = cache_data[caddr[3:2]]; -always @(posedge clkcpu) begin +wire cpu_mem_we = cpu_we & ((phycs & spvmd) | (table_valid & logcs)) & ~romcs; +wire memw = cpu_load & cpu_cyc & cpu_we & spvmd & (cpu_address[25:21] == 5'b11011); // &3600000 +wire err = ~address_valid; + +always @(posedge clkcpu) begin : block reg cache_rcv, cache_test; reg [1:0] cache_cnt; reg [1:0] cache_wraddr; @@ -194,8 +184,11 @@ always @(posedge clkcpu) begin vid_address <= INITIAL_SCREEN_BASE; cur_address <= INITIAL_CURSOR_BASE; + vid_load = 1'b0; + snd_load = 1'b0; + cur_load = 1'b0; cpu_load <= 1'b0; - rom_overlay <= 1'b1; + rom_overlay <= 1'b1; // start with rom overlay memc_control[11] <= 1'b0; // disable sound dma on reset. @@ -204,6 +197,10 @@ always @(posedge clkcpu) begin cache_valid <= 0; cache_test <= 0; + snd_next_valid = 1'b0; // sound init. + + dma_ack_r = 4'd0; // video init. + end else begin if(cache_rcv & mem_ack_i) begin @@ -416,19 +413,11 @@ always @(posedge clkcpu) begin end -wire [21:2] ram_page = memc_control[3:2] == 2'b00 ? {3'd0, cpu_address[18:2]}: - memc_control[3:2] == 2'b01 ? {2'd0, cpu_address[19:2]} : - memc_control[3:2] == 2'b10 ? {1'd0, cpu_address[20:2]} : cpu_address[21:2]; - assign mem_addr_o = vid_load ? {5'd0, vid_address[18:2]} : cur_load ? {5'd0, cur_address[18:2]} : snd_load ? {5'd0, snd_sptr[18:2]} : caddr; -wire [23:2] caddr = phycs ? {2'd0, ram_page} : // use physical memory - romcs ? {3'b010, cpu_address[20:2]} : // use 2mb and up for rom space. - table_valid & logcs ? phys_address[23:2] : 22'd0; // use logical memory. - // does this cpu cycle need to go to external RAM/ROM? //assign cpu_ram_cycle = cpu_cyc & cpu_stb & (table_valid | phycs | romcs); @@ -438,23 +427,20 @@ assign mem_sel_o = cpu_load ? cpu_sel : 4'b1111; assign mem_we_o = cpu_load ? cpu_mem_we : 1'b0; assign mem_cti_o = 3'b010; -wire cpu_mem_we = cpu_we & ((phycs & spvmd) | (table_valid & logcs)) & ~romcs; +wire vidc_cs = spvmd & (cpu_address[25:21] == 5'b11010); // &3400000 - &35FFFFF (WE & SPVMD) assign address_valid = (logcs & table_valid) | rom_low_cs| ioc_cs | memw | tablew | vidc_cs | (phycs & ~cpu_we) | (phycs & spvmd & cpu_we) | romcs; -wire err = ~address_valid; assign cpu_ack = (mem_we_o ? mem_ack_i : cache_ack) & ~err; assign cpu_err = cpu_load ? mem_ack_i & err : 1'b0; assign tablew = cpu_load & cpu_cyc & cpu_we & spvmd & (cpu_address[25:23] == 3'b111) & (cpu_address[12] == 0) & (cpu_address[7] == 0); // &3800000+ -wire memw = cpu_load & cpu_cyc & cpu_we & spvmd & (cpu_address[25:21] == 5'b11011); // &3600000 + assign vidw = cpu_load & cpu_cyc & cpu_we & vidc_cs; // &3400000 // bus chip selects -wire logcs = cpu_address[25] == 1'b0; // 0000000-&1FFFFFF assign phycs = cpu_address[25:24] == 2'b10; //&2000000 - &2FFFFFF assign ioc_cs = spvmd & (cpu_address[25:22] == 4'b1100); //&3000000 - &33FFFFF -wire vidc_cs = spvmd & (cpu_address[25:21] == 5'b11010); // &3400000 - &35FFFFF (WE & SPVMD) assign rom_low_cs = (cpu_address[25:22] == 4'b1101); assign romcs = ((cpu_address[25:23] == 3'b111) | (cpu_address[25:19] == 7'h00) & rom_overlay); diff --git a/rtl/vidc.v b/rtl/vidc.v index 558f7b4..f2b1cd6 100644 --- a/rtl/vidc.v +++ b/rtl/vidc.v @@ -158,7 +158,7 @@ vidc_dmachannel #(.FIFO_SIZE(2)) CURSORDMA ( ); -always @(posedge clkcpu) begin +always @(posedge clkcpu) begin : block reg old_en; old_en <= snd_sam_en; diff --git a/rtl/vidc_audio.v b/rtl/vidc_audio.v index c6234d2..5949bab 100644 --- a/rtl/vidc_audio.v +++ b/rtl/vidc_audio.v @@ -51,7 +51,7 @@ localparam SOUND_SAMFREQ = 4'b1100; localparam SOUND_REGISTERS = 5'b01100; reg [2:0] channel; -reg [2:0] vidc_sir[8]; +reg [2:0] vidc_sir[0:7]; reg [8:0] vidc_sfr; // 1mhz pulse counter. @@ -85,7 +85,7 @@ function [15:0] mu2lin; endfunction -always @(posedge aud_clk) begin +always @(posedge aud_clk) begin : block reg [15:0] data,al,ar; reg ce_d; diff --git a/rtl/vidc_dmachannel.v b/rtl/vidc_dmachannel.v index 42555b8..c5f58dd 100644 --- a/rtl/vidc_dmachannel.v +++ b/rtl/vidc_dmachannel.v @@ -75,7 +75,7 @@ vidc_fifo #(.FIFO_SIZE(FIFO_SIZE)) VIDEO_FIFO // DMA interface control // this is in the cpu clock domain. -always @(posedge clkcpu) begin +always @(posedge clkcpu) begin : block reg [1:0] dma_count; reg rstD, rstD2; diff --git a/rtl/vidc_fifo.v b/rtl/vidc_fifo.v index 320a589..b798b83 100644 --- a/rtl/vidc_fifo.v +++ b/rtl/vidc_fifo.v @@ -41,8 +41,8 @@ module vidc_fifo #( input rd_en, output reg [7:0] dout, - output reg [WORD_WIDTH-1:0] wr_ptr, - output reg [WORD_WIDTH-1:0] space, + output reg [FIFO_SIZE-1:0] wr_ptr, + output reg [FIFO_SIZE-1:0] space, output reg full, output empty ); @@ -74,7 +74,7 @@ end reg [BYTE_WIDTH-1:0] rd_ptr_r; -always @(posedge wr_clk) begin +always @(posedge wr_clk) begin : block reg rstD, rstD2; rd_ptr_r <= rd_ptr; @@ -103,7 +103,7 @@ end wire [7:0] q; -always @(posedge rd_clk) begin +always @(posedge rd_clk) begin : block2 reg rstD, rstD2; diff --git a/sim/cpu_export.vhd b/sim/cpu_export.vhd new file mode 100644 index 0000000..4d87d7f --- /dev/null +++ b/sim/cpu_export.vhd @@ -0,0 +1,144 @@ + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use STD.textio.all; + +entity cpu_export is + port + ( + clk : in std_logic; + rst : in std_logic; + new_export : in std_logic; + commandcount : out integer; + + R0 : std_logic_vector(31 downto 0); + R1 : std_logic_vector(31 downto 0); + R2 : std_logic_vector(31 downto 0); + R3 : std_logic_vector(31 downto 0); + R4 : std_logic_vector(31 downto 0); + R5 : std_logic_vector(31 downto 0); + R6 : std_logic_vector(31 downto 0); + R7 : std_logic_vector(31 downto 0); + R8 : std_logic_vector(31 downto 0); + R9 : std_logic_vector(31 downto 0); + R10 : std_logic_vector(31 downto 0); + R11 : std_logic_vector(31 downto 0); + R12 : std_logic_vector(31 downto 0); + R13 : std_logic_vector(31 downto 0); + R14 : std_logic_vector(31 downto 0); + R15 : std_logic_vector(31 downto 0) + ); +end entity; + +architecture arch of cpu_export is + + signal new_export_1 : std_logic := '0'; + + signal rst_1 : std_logic := '1'; + +begin + +-- synthesis translate_off + process + + file outfile : text; + variable f_status : FILE_OPEN_STATUS; + variable line_out : line; + variable recordcount : integer := 0; + + constant filenamebase : string := "R:\debug_"; + variable filename : string(1 to 14); + + variable nh : std_logic := '1'; + variable tc : integer := 0; + variable testrun : integer := 0; + + variable old_R0 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R1 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R2 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R3 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R4 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R5 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R6 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R7 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R8 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R9 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R10 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R11 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R12 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R13 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R14 : std_logic_vector(31 downto 0) := (others => '0'); + variable old_R15 : std_logic_vector(31 downto 0) := (others => '0'); + + begin + + filename := filenamebase & to_hstring(to_unsigned(testrun, 4)) & ".txt"; + file_open(f_status, outfile, filename, write_mode); + + while (true) loop + wait until rising_edge(clk); + + rst_1 <= rst; + if (rst_1 = '0' and rst = '1') then + nh := '1'; + tc := 0; + testrun := testrun + 1; + + filename := filenamebase & to_hstring(to_unsigned(testrun, 4)) & ".txt"; + file_close(outfile); + file_open(f_status, outfile, filename, write_mode); + file_close(outfile); + file_open(f_status, outfile, filename, append_mode); + + end if; + + new_export_1 <= new_export; + if (rst = '0' and new_export_1 = '1') then + + write(line_out, string'("#")); write(line_out, tc); writeline(outfile, line_out); + + -- cpu 7 + if (nh = '1' or R0 /= old_R0 ) then write(line_out, string'("R0 ")); write(line_out, to_hstring(signed(R0 ))); writeline(outfile, line_out); old_R0 := R0 ; end if; + if (nh = '1' or R1 /= old_R1 ) then write(line_out, string'("R1 ")); write(line_out, to_hstring(signed(R1 ))); writeline(outfile, line_out); old_R1 := R1 ; end if; + if (nh = '1' or R2 /= old_R2 ) then write(line_out, string'("R2 ")); write(line_out, to_hstring(signed(R2 ))); writeline(outfile, line_out); old_R2 := R2 ; end if; + if (nh = '1' or R3 /= old_R3 ) then write(line_out, string'("R3 ")); write(line_out, to_hstring(signed(R3 ))); writeline(outfile, line_out); old_R3 := R3 ; end if; + if (nh = '1' or R4 /= old_R4 ) then write(line_out, string'("R4 ")); write(line_out, to_hstring(signed(R4 ))); writeline(outfile, line_out); old_R4 := R4 ; end if; + if (nh = '1' or R5 /= old_R5 ) then write(line_out, string'("R5 ")); write(line_out, to_hstring(signed(R5 ))); writeline(outfile, line_out); old_R5 := R5 ; end if; + if (nh = '1' or R6 /= old_R6 ) then write(line_out, string'("R6 ")); write(line_out, to_hstring(signed(R6 ))); writeline(outfile, line_out); old_R6 := R6 ; end if; + if (nh = '1' or R7 /= old_R7 ) then write(line_out, string'("R7 ")); write(line_out, to_hstring(signed(R7 ))); writeline(outfile, line_out); old_R7 := R7 ; end if; + if (nh = '1' or R8 /= old_R8 ) then write(line_out, string'("R8 ")); write(line_out, to_hstring(signed(R8 ))); writeline(outfile, line_out); old_R8 := R8 ; end if; + if (nh = '1' or R9 /= old_R9 ) then write(line_out, string'("R9 ")); write(line_out, to_hstring(signed(R9 ))); writeline(outfile, line_out); old_R9 := R9 ; end if; + if (nh = '1' or R10 /= old_R10) then write(line_out, string'("R10 ")); write(line_out, to_hstring(signed(R10))); writeline(outfile, line_out); old_R10 := R10; end if; + if (nh = '1' or R11 /= old_R11) then write(line_out, string'("R11 ")); write(line_out, to_hstring(signed(R11))); writeline(outfile, line_out); old_R11 := R11; end if; + if (nh = '1' or R12 /= old_R12) then write(line_out, string'("R12 ")); write(line_out, to_hstring(signed(R12))); writeline(outfile, line_out); old_R12 := R12; end if; + if (nh = '1' or R13 /= old_R13) then write(line_out, string'("R13 ")); write(line_out, to_hstring(signed(R13))); writeline(outfile, line_out); old_R13 := R13; end if; + if (nh = '1' or R14 /= old_R14) then write(line_out, string'("R14 ")); write(line_out, to_hstring(signed(R14))); writeline(outfile, line_out); old_R14 := R14; end if; + if (nh = '1' or R15 /= old_R15) then write(line_out, string'("R15 ")); write(line_out, to_hstring(signed(R15))); writeline(outfile, line_out); old_R15 := R15; end if; + + recordcount := recordcount + 1; + tc := tc + 1; + + if (recordcount mod 1000 = 0) then + file_close(outfile); + file_open(f_status, outfile, filename, append_mode); + recordcount := 0; + end if; + + nh := '0'; + + end if; + + commandcount <= tc; + + end loop; + + end process; +-- synthesis translate_on + +end architecture; + + + + + diff --git a/sim/globals.vhd b/sim/globals.vhd new file mode 100644 index 0000000..e63127c --- /dev/null +++ b/sim/globals.vhd @@ -0,0 +1,13 @@ +library ieee; +use ieee.std_logic_1164.all; + +package globals is + + signal COMMAND_FILE_ENDIAN : std_logic; + signal COMMAND_FILE_NAME : string(1 to 1024); + signal COMMAND_FILE_NAMELEN : integer; + signal COMMAND_FILE_TARGET : integer; + signal COMMAND_FILE_START : std_logic; + signal COMMAND_FILE_ACK : std_logic; + +end package globals; \ No newline at end of file diff --git a/sim/lua_tests/run.lua b/sim/lua_tests/run.lua new file mode 100644 index 0000000..b41f893 --- /dev/null +++ b/sim/lua_tests/run.lua @@ -0,0 +1,40 @@ +package.path = package.path .. ";./../lualib/?.lua" +package.path = package.path .. ";./../luatools/?.lua" +require("vsim_comm") + +reg_set_file("../releases/riscos.rom", DUMMYREG, 0x400000, 0) + +reg_set_connection(0x81, DUMMYREG) +wait_ns(10000) +reg_set_connection(0x80, DUMMYREG) +wait_ns(100000) + +reg_set_connection(0x81, DUMMYREG) +wait_ns(10000) +reg_set_connection(0x80, DUMMYREG) +wait_ns(50000) + +reg_set_connection(0x81, DUMMYREG) +wait_ns(10000) +reg_set_connection(0x80, DUMMYREG) +wait_ns(60000) + +reg_set_connection(0x81, DUMMYREG) +wait_ns(10000) +reg_set_connection(0x80, DUMMYREG) +wait_ns(70000) + +reg_set_connection(0x81, DUMMYREG) +wait_ns(10000) +reg_set_connection(0x80, DUMMYREG) +wait_ns(80000) + +reg_set_connection(0x81, DUMMYREG) +wait_ns(10000) +reg_set_connection(0x80, DUMMYREG) +wait_ns(90000) + +reg_set_connection(0x81, DUMMYREG) +wait_ns(10000) +reg_set_connection(0x80, DUMMYREG) +wait_ns(100000) \ No newline at end of file diff --git a/sim/lualib/vsim_comm.lua b/sim/lualib/vsim_comm.lua new file mode 100644 index 0000000..fb5dd7b --- /dev/null +++ b/sim/lualib/vsim_comm.lua @@ -0,0 +1,418 @@ +function string:split(sep) + local sep, fields = sep or ":", {} + local pattern = string.format("([^%s]+)", sep) + self:gsub(pattern, function(c) fields[#fields+1] = c end) + return fields +end + +function conv_neg(x) + if (x < 0) then + return (2147483647 + (2147483649 - ((x * (-1)) ))) + else + return x + end +end + +function conv_to_neg(x) + if (x > 2147483647) then + return x - (2* 2147483648) + else + return x + end +end + +function binary_and(a,b) + local r = 0 + local neg = 1 + if (a < 0) then + a = a * (-1) + neg = neg * (-1) + end + if (b < 0) then + b = b * (-1) + neg = neg * (-1) + end + for i = 31, 0, -1 do + local x = 2^i + if (a >= x and b>=x) then + r = r + 2^i + end + if (a >= x) then + a = a - x + end + if (b >= x) then + b = b - x + end + end + return r * neg +end + +function binary_or(a,b) + local r = 0 +local neg = 1 + if (a < 0) then + a = a * (-1) + neg = neg * (-1) + end + if (b < 0) then + b = b * (-1) + neg = neg * (-1) + end + for i = 31, 0, -1 do + local x = 2^i + if (a >= x or b>=x) then + r = r + 2^i + end + if (a >= x) then + a = a - x + end + if (b >= x) then + b = b - x + end + end + return r * neg +end +-------------- +-- file access +-------------- + +inputfile = "../input.txt" +outputfile = "../output.txt" + +blockwritesize = 128 +wait_on_writeblock = true + +function write_one(command) + + local file = nil + while (file == nil) do + file=io.open(inputfile,"a+") + end + + io.output(file) + + io.write(command) + io.write("\n") + + io.close(file) + +end + +function read_one(command) + + local read_line = "" + + command = string.sub(command, 1, #command - 1) + + --print("#command: "..#command) + + if (endpointer > 1000) then + endpointer = endpointer - 1000 + else + endpointer = 0 + end + + while read_line ~= command do + + local file = nil + while (file == nil) do + file=io.open(outputfile,"r") + end + + file:seek("set", endpointer) + + local line = file:read() + + while (line ~= nil) do + + local buf_line = line + + local ix = #command + 1 + while ix < #buf_line do + if (string.sub(buf_line,ix,ix) == "#") then + break + end + ix = ix + 1 + end + + result = string.sub(buf_line,ix + 2,#buf_line - 1) + buf_line = string.sub(buf_line,0,ix - 2) + + --print("########") + --print(line) + --print(command) + --print(buf_line) + --print("Result:"..result) + + if (buf_line == command) then + read_line = buf_line + break; + end + + line = file:read() + + end + + new_endpointer = file:seek("end") + io.close(file) + + end + + endpointer = new_endpointer + + return result +end + +------------------- +-- connect commands +------------------- + +function reg_get_block_connection(reg, index, size) + command_nr = command_nr + 1 + if (index == null) then index = 0 end + + block = {} + local readindex = 0 + local dataleft = size + while (dataleft > 0) do + + local blocksize = math.min(dataleft, 128) + + command = "get # "..command_nr.." # "..process_id.." # ".."1".." # "..blocksize.." # "..(reg[1] + index).."&" + write_one(command) + values = read_one(command) + + blockraw = values:split("#") + for i = 1, blocksize do + block[readindex] = tonumber(blockraw[i]) + readindex = readindex + 1 + end + + dataleft = dataleft - blocksize + index = index + blocksize + + end + + return block +end + +function reg_get_connection(reg, index) + block = reg_get_block_connection(reg, index, 1) + return block[0] +end + +function reg_set_block_connection(values, reg, index) + if (index == null) then index = 0 end + command_nr = command_nr + 1 + local length = (#values + 1) + command = "set # "..command_nr.." # "..process_id.." # ".."1".." # "..math.min(blockwritesize, length).." # "..(reg[1] + index) + local writecount = 0 + for i = 0, #values do + value = conv_to_neg(values[i]) + command = command.." # "..value + writecount = writecount + 1 + if (writecount == blockwritesize) then + command = command.."&" + write_one(command) + if (wait_on_writeblock) then + read_one(command) + end + writecount = 0 + index = index + blockwritesize + command_nr = command_nr + 1 + length = length - blockwritesize + command = "set # "..command_nr.." # "..process_id.." # ".."1".." # "..math.min(blockwritesize, length).." # "..(reg[1] + index) + end + end + if (length > 0) then + command = command.."&" + write_one(command) + if (wait_on_writeblock) then + read_one(command) + end + end +end + +function reg_set_connection(value, reg, index) + values = {} + values[0] = value + reg_set_block_connection(values, reg, index) +end + +----------- +-- commands +----------- + +function reg_filter(reg, value) + + filter = 0 + for i = reg[3], reg[2] do + filter = filter + 2^i; + end + + value = conv_neg(value) + value = binary_and(value,filter); + value = value / (2 ^ reg[3]); + + return value + +end + +function reg_get(reg, index) + value = reg_get_connection(reg, index) + + value = reg_filter(reg, value) + + return value +end + +function reg_get_block(reg, index, size) + + block = reg_get_block_connection(reg, index, size) + for i = 0, size - 1 do + value = block[i] + + filter = 0 + for i = reg[3], reg[2] do + filter = filter + 2^i; + end + + value = conv_neg(value) + value = binary_and(value,filter); + value = value / (2 ^ reg[3]); + + block[i] = value + end + + return block +end + +function reg_set_block(block, reg, index) + reg_set_block_connection(block, reg, index) +end + + +function reg_set(value, reg, index) + if (index == null) then index = 0 end + + if (value < 100) then + --print ("Address "..(reg[1] + index).."["..reg[2]..".."..reg[3].."] => "..value) + else + --print ("Address "..(reg[1] + index).."["..reg[2]..".."..reg[3].."] => 0x"..string.format("%X", value)) + end + + -- find out if parameter is the only one in this register + local singlereg = true + local fullname = reg[6] + local sectionname = fullname:split(".")[1] + local secttable = _G[sectionname] + for name, register in pairs(secttable) do + if (register[1] == reg[1]) then + if (register[6] ~= reg[6]) then + singlereg = false + break + end + end + end + + oldval = 0 + + if (singlereg == false) then + + oldval = reg_get_connection(reg, index) + + --print ("oldval= "..oldval.." at "..(reg[1]+index)) + + filter = 0 + for i = 0, reg[3] - 1 do + filter = filter + 2^i; + end + for i = reg[2] + 1, 31 do + filter = filter + 2^i; + end + oldval = binary_and(oldval,filter); + + --print ("oldval filtered= "..oldval.." at "..(reg[1]+index).." with filter "..filter) + + end + + value = value * (2 ^ reg[3]) + value = binary_or(value, oldval); + + reg_set_connection(value, reg, index) +end + + +function compare_reg(target, reg, index) + if (index == null) then index = 0 end + value = reg_get(reg, index) + if (value == target) then + if (value < 100 and target < 100) then + print (reg[6].." -> Address "..(reg[1] + index).."["..reg[2]..".."..reg[3].."] = "..value.." - OK") + else + print (reg[6].." -> Address "..(reg[1] + index).."["..reg[2]..".."..reg[3].."] = 0x"..string.format("%X", value).." - OK") + end + return true + else + testerrorcount = testerrorcount + 1 + if (value < 100 and target < 100) then + print (reg[6].." -> Address "..(reg[1] + index).."["..reg[2]..".."..reg[3].."] = "..value.." | should be = "..target.." - ERROR") + else + print (reg[6].." -> Address "..(reg[1] + index).."["..reg[2]..".."..reg[3].."] = 0x"..string.format("%X", tonumber(value)).." | should be = 0x"..string.format("%X", tonumber(target)).." - ERROR") + end + return false; + end +end + +function reg_set_file(filename, reg, index, endian) + if (index == null) then index = 0 end + if (endian == null) then endian = 0 end + command_nr = command_nr + 1 + command = "fil # "..command_nr.." # "..process_id.." # "..endian.." # "..(reg[1] + index).." # "..filename + command = command.."&" + write_one(command) + if (wait_on_writeblock) then + read_one(command) + end +end + +function wait_ns(waittime) + command_nr = command_nr + 1 + command = "wtn # "..command_nr.." # "..process_id.." # "..waittime.."&" + write_one(command) + read_one(command) +end + +function brk() + command_nr = command_nr + 1 + command = "brk&" + write_one(command) +end + +function sleep(n) -- seconds + local t0 = os.clock() + while os.clock() - t0 <= n do end +end + +---------- +-- init +---------- + + +seed = os.time() + os.clock() * 1000 +math.randomseed(seed) +process_id = math.random(2147483647) +process_id = math.random(2147483647) +process_id = math.random(2147483647) +process_id = math.random(2147483647) +process_id = math.random(2147483647) + +endpointer = 0 + +command_nr = 0 + +DUMMYREG = {0,31,0,1,0,"DUMMYREG"} + + + + diff --git a/sim/readme.txt b/sim/readme.txt new file mode 100644 index 0000000..b681931 --- /dev/null +++ b/sim/readme.txt @@ -0,0 +1,16 @@ +Tested with Modelsim 10.5 + +- compile with vcom_all.bat. Make sure you have altera_mf library in folder, generated from quartus +- run modelsim with vsim_start.bat +- run all + +Simulation will now wait for input from outside + +Run Luascript run.lua with "lua run.lua" from folder lua_tests + +It will upload riscos into the testbench memory and let the cpu run it + +Current test checks for reset working. + +CPU Export will write a log with every register change for every clock cycle. +This can be used to compare(with a diff tool) original behavior to any changes made. diff --git a/sim/stringprocessor.vhd b/sim/stringprocessor.vhd new file mode 100644 index 0000000..dd76717 --- /dev/null +++ b/sim/stringprocessor.vhd @@ -0,0 +1,389 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use STD.textio.all; + +use work.globals.all; + +entity estringprocessor is + generic + ( + clk_speed : integer := 50000000 + ); + port + ( + ready : in std_logic; + tx_command : out std_logic_vector(31 downto 0); + tx_bytes : out integer range 0 to 4; + tx_enable : out std_logic := '0'; + rx_command : in std_logic_vector(31 downto 0); + rx_valid : in std_logic + ); +end entity; + +architecture arch of estringprocessor is + + constant proc_busadr : integer := 28; + constant proc_buswidth : integer := 32; + + constant clk_period : time := (1000000000 / clk_speed) * 1 ns; + + signal string_command : string(1 to 3); + + type t_internal_variables is array(0 to 256) of integer; + signal internal_variables : t_internal_variables := (others => 0); + + type r_thread_record is record + id : integer; + waittime : integer; + waitcommand : line; + end record; + + type t_thread_buffers is array(0 to 255) of r_thread_record; + + + procedure find_id + ( + variable t_buf : inout t_thread_buffers; + variable id : in integer; + variable slot : out integer + ) is + begin + for i in 0 to 255 loop + if (t_buf(i).id = id) then + slot := i; + exit; + elsif (t_buf(i).id = -1) then + t_buf(i).id := id; + slot := i; + exit; + end if; + end loop; + end procedure; + + + +begin + + + process + + file infile : text; + file outfile : text; + variable f_status : FILE_OPEN_STATUS; + variable newdat : LINE; + variable endfound : boolean; + variable buf : LINE; + variable run : boolean := true; + + variable line_out : line; + variable debugline_out : line; + variable command : string(1 to 3); + + variable dev_null_str3 : string (1 to 3); + variable dev_null_str6 : string (1 to 6); + variable OK : boolean := FALSE; + variable para_int1 : integer; + variable para_int2 : integer; + variable para_int3 : integer; + variable para_int4 : integer; + + variable address : integer; + variable data : integer; + variable count : integer; + + variable thread_buffers : t_thread_buffers := (others => (-1, 0, null)); + + variable freerun : boolean := false; + + begin + + file_open(f_status, outfile, "input.txt", write_mode); + file_close(outfile); + file_open(f_status, outfile, "output.txt", write_mode); + file_close(outfile); + + file_open(f_status, infile, "input.txt", read_mode); + + wait for 1000 ns; + + while (run) loop + + if not endfile(infile) then + + endfound := false; + buf := null; + while (endfound = false) loop + if not endfile(infile) then + readline(infile,newdat); + for i in 1 to newdat'length loop + write(buf, newdat(i to i)); + if (newdat(i to i) = "&") then + endfound := true; + end if; + end loop; + end if; + end loop; + + command := buf(1 to 3); + string_command <= command; + + line_out := null; + buf(buf'length) := ' '; + write(line_out, buf(1 to buf'length)); + write(line_out, string'("# ")); + + if (command(1 to 3) = String'("set")) then + -- command + Read(buf, dev_null_str6); + -- command nr + Read(buf, para_int1, OK); + Read(buf, dev_null_str3); + -- process id + Read(buf, para_int1, OK); + Read(buf, dev_null_str3); + -- target for reading + Read(buf, para_int2, OK); + Read(buf, dev_null_str3); + -- count + Read(buf, count, OK); + Read(buf, dev_null_str3); + -- address in target space + Read(buf, address, OK); + Read(buf, dev_null_str3); + + -- write address + if (ready = '0') then + wait until ready = '1'; + end if; + tx_command <= "0000" & std_logic_vector(to_unsigned(address,proc_busadr)); + if (count > 1) then + tx_command(31) <= '1'; + end if; + tx_bytes <= 4; + tx_enable <= '1'; + wait for clk_period*2; + tx_enable <= '0'; + + -- write block size + if (count > 1) then + if (ready = '0') then + wait until ready = '1'; + end if; + tx_command <= std_logic_vector(to_unsigned(count - 1,32)); + tx_bytes <= 4; + tx_enable <= '1'; + wait for clk_period*2; + tx_enable <= '0'; + end if; + + for i in 1 to count loop + + -- value to write + Read(buf, data, OK); + if (i < count) then + Read(buf, dev_null_str3); + end if; + + -- write data + if (ready = '0') then + wait until ready = '1'; + end if; + tx_command <= std_logic_vector(to_signed(data,proc_buswidth)); + tx_bytes <= 4; + tx_enable <= '1'; + wait for clk_period*2; + tx_enable <= '0'; + wait for 20*clk_period; -- this is required, because there is no answer for write commands + + address := address + 1; + + end loop; + + write(line_out, string'("&")); + file_open(f_status, outfile, "output.txt", append_mode); + writeline(outfile, line_out); + file_close(outfile); + end if; + + if (command(1 to 3) = String'("get")) then + -- command + Read(buf, dev_null_str6); + -- command nr + Read(buf, para_int1, OK); + Read(buf, dev_null_str3); + -- process id + Read(buf, para_int1, OK); + Read(buf, dev_null_str3); + -- target for reading + Read(buf, para_int1, OK); + Read(buf, dev_null_str3); + -- count + Read(buf, count, OK); + Read(buf, dev_null_str3); + -- address in target space + Read(buf, address, OK); + + -- write address + if (ready = '0') then + wait until ready = '1'; + end if; + tx_command <= "0100" & std_logic_vector(to_unsigned(address,proc_busadr)); + if (count > 1) then + tx_command(31) <= '1'; + end if; + tx_bytes <= 4; + tx_enable <= '1'; + wait for clk_period*2; + tx_enable <= '0'; + + -- write block size + if (count > 1) then + if (ready = '0') then + wait until ready = '1'; + end if; + tx_command <= std_logic_vector(to_unsigned(count - 1,32)); + tx_bytes <= 4; + tx_enable <= '1'; + wait for clk_period*2; + tx_enable <= '0'; + end if; + + for i in 1 to count loop + + if (rx_valid = '0') then + wait until rx_valid = '1'; + end if; + data := to_integer(signed(rx_command(31 downto 0))); + wait until rx_valid = '0'; + + write(line_out, data); + write(line_out, string'("#")); + + address := address + 1; + + end loop; + + write(line_out, string'("&")); + file_open(f_status, outfile, "output.txt", append_mode); + writeline(outfile, line_out); + file_close(outfile); + end if; + + if (command(1 to 3) = String'("fil")) then + -- command + Read(buf, dev_null_str6); + -- command nr + Read(buf, para_int1, OK); + Read(buf, dev_null_str3); + -- process id + Read(buf, para_int1, OK); + Read(buf, dev_null_str3); + -- endianess + Read(buf, para_int2, OK); + Read(buf, dev_null_str3); + -- address in target space + Read(buf, address, OK); + Read(buf, dev_null_str3); + + COMMAND_FILE_NAME <= (others => ' '); + COMMAND_FILE_NAME(1 to buf'length) <= buf(1 to buf'length); + COMMAND_FILE_NAMELEN <= buf'length; + COMMAND_FILE_TARGET <= address; + if (para_int2 = 1) then + COMMAND_FILE_ENDIAN <= '1'; + else + COMMAND_FILE_ENDIAN <= '0'; + end if; + COMMAND_FILE_START <= '1'; + wait until COMMAND_FILE_ACK = '1'; + COMMAND_FILE_START <= '0'; + wait for 20 ns; + + write(line_out, string'("&")); + file_open(f_status, outfile, "output.txt", append_mode); + writeline(outfile, line_out); + file_close(outfile); + end if; + + if (command(1 to 3) = String'("brk")) then + run := false; + end if; + + if (command(1 to 3) = String'("wtn")) then + -- command + Read(buf, dev_null_str6); + -- command nr + Read(buf, para_int1, OK); + Read(buf, dev_null_str3); + -- process id + Read(buf, para_int1, OK); + Read(buf, dev_null_str3); + -- time to wait + Read(buf, para_int2, OK); + + + write(line_out, string'("&")); + if (para_int2 = -1) then + freerun := true; + find_id(thread_buffers, para_int1, para_int3); + thread_buffers(para_int3).waittime := 2; + thread_buffers(para_int3).waitcommand := line_out; + else + find_id(thread_buffers, para_int1, para_int3); + thread_buffers(para_int3).waittime := para_int2; + thread_buffers(para_int3).waitcommand := line_out; + end if; + + end if; + + wait for 1 ps; + + end if; + + OK := false; + for i in 0 to 255 loop + if (thread_buffers(i).id /= -1) then + if (thread_buffers(i).waittime = 1) then + file_open(f_status, outfile, "output.txt", append_mode); + writeline(outfile, thread_buffers(i).waitcommand); + file_close(outfile); + end if; + if (thread_buffers(i).waittime > 0) then + OK := true; + thread_buffers(i).waittime := thread_buffers(i).waittime - 1; + end if; + end if; + end loop; + + if (OK = true or freerun = true) then + wait for 1 ns; + end if; + + end loop; + + file_close(infile); + + wait; + + end process; + + + + +end architecture; + + + + + + + + + + + + + + + diff --git a/sim/tb.vhd b/sim/tb.vhd new file mode 100644 index 0000000..9c6094a --- /dev/null +++ b/sim/tb.vhd @@ -0,0 +1,294 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use ieee.math_real.all; + +use work.globals.all; + +entity etb is +end entity; + +architecture arch of etb is + + signal clk : std_logic := '1'; + + signal CLKCPU_I : std_logic := '1'; + signal CLKPIX_I : std_logic := '1'; + signal CEPIX_I : std_logic := '1'; + signal SELPIX_O : std_logic_vector(1 downto 0); + signal CEAUD_I : std_logic; + signal RESET_I : std_logic := '1'; + signal MEM_CYC_O : std_logic; + signal MEM_STB_O : std_logic; + signal MEM_WE_O : std_logic; + signal MEM_ACK_I : std_logic; + signal MEM_ERR_I : std_logic; + signal MEM_RTY_I : std_logic; + signal MEM_SEL_O : std_logic_vector(3 downto 0); + signal MEM_CTI_O : std_logic_vector(2 downto 0); + signal MEM_ADDR_O : std_logic_vector(21 downto 0); + signal MEM_DAT_I : std_logic_vector(31 downto 0); + signal MEM_DAT_O : std_logic_vector(31 downto 0); + signal HSYNC : std_logic; + signal VSYNC : std_logic; + signal VIDEO_R : std_logic_vector(3 downto 0); + signal VIDEO_G : std_logic_vector(3 downto 0); + signal VIDEO_B : std_logic_vector(3 downto 0); + signal VIDEO_EN : std_logic; + signal VIDBASECLK_O : std_logic_vector(1 downto 0); + signal VIDSYNCPOL_O : std_logic_vector(1 downto 0); + signal I2C_DOUT : std_logic; + signal I2C_DIN : std_logic; + signal I2C_CLOCK : std_logic; + signal DEBUG_LED : std_logic; + signal img_mounted : std_logic_vector(1 downto 0); + signal img_wp : std_logic; + signal img_size : std_logic_vector(31 downto 0); + signal sd_lba : std_logic_vector(31 downto 0) := (others => '0'); + signal sd_rd : std_logic_vector(1 downto 0); + signal sd_wr : std_logic_vector(1 downto 0); + signal sd_ack : std_logic; + signal sd_buff_addr : std_logic_vector(7 downto 0) := (others => '0'); + signal sd_buff_dout : std_logic_vector(15 downto 0) := (others => '0'); + signal sd_buff_din : std_logic_vector(15 downto 0); + signal sd_buff_wr : std_logic := '0'; + signal KBD_OUT_DATA : std_logic_vector(7 downto 0); + signal KBD_OUT_STROBE : std_logic; + signal KBD_IN_DATA : std_logic_vector(7 downto 0); + signal KBD_IN_STROBE : std_logic; + signal JOYSTICK0 : std_logic_vector(4 downto 0); + signal JOYSTICK1 : std_logic_vector(4 downto 0); + signal AUDIO_L : std_logic_vector(15 downto 0); + signal AUDIO_R : std_logic_vector(15 downto 0); + + signal DDRAM_OUT_BUSY : std_logic := '0'; + signal DDRAM_OUT_DOUT : std_logic_vector(31 downto 0); + signal DDRAM_OUT_DOUT_READY : std_logic; + signal DDRAM_OUT_BURSTCNT : std_logic_vector(7 downto 0); + signal DDRAM_OUT_ADDR : std_logic_vector(27 downto 0) := (others => '0'); + signal DDRAM_OUT_RD : std_logic; + signal DDRAM_OUT_DIN : std_logic_vector(31 downto 0); + signal DDRAM_OUT_BE : std_logic_vector(7 downto 0); + signal DDRAM_OUT_WE : std_logic; + + type t_data is array(0 to (2**27)-1) of integer; + type bit_vector_file is file of bit_vector; + + signal tx_command : std_logic_vector(31 downto 0); + signal tx_bytes : integer range 0 to 4; + signal tx_enable : std_logic := '0'; + +begin + + clk <= not clk after 5 ns; + CLKCPU_I <= not CLKCPU_I after 24 ns; -- not exactly 42Mhz + CLKPIX_I <= not CLKPIX_I after 20 ns; -- ? + CEPIX_I <= not CEPIX_I after 40 ns; -- ? + + process + begin + wait until rising_edge(clk); + if (tx_enable = '1' and tx_command(7) = '1') then + RESET_I <= tx_command(0); + wait until rising_edge(clk); + wait until rising_edge(clk); + end if; + end process; + + iarchimedes_top : entity work.archimedes_top + generic map + ( + CLKCPU => 42000000 + ) + port map + ( + CLKCPU_I => CLKCPU_I , + CLKPIX_I => CLKPIX_I , + CEPIX_I => CEPIX_I , + SELPIX_O => SELPIX_O , + CEAUD_I => CEAUD_I , + RESET_I => RESET_I , + MEM_CYC_O => MEM_CYC_O , + MEM_STB_O => MEM_STB_O , + MEM_WE_O => MEM_WE_O , + MEM_ACK_I => MEM_ACK_I , + MEM_ERR_I => MEM_ERR_I , + MEM_RTY_I => MEM_RTY_I , + MEM_SEL_O => MEM_SEL_O , + MEM_CTI_O => MEM_CTI_O , + MEM_ADDR_O => MEM_ADDR_O , + MEM_DAT_I => MEM_DAT_I , + MEM_DAT_O => MEM_DAT_O , + HSYNC => HSYNC , + VSYNC => VSYNC , + VIDEO_R => VIDEO_R , + VIDEO_G => VIDEO_G , + VIDEO_B => VIDEO_B , + VIDEO_EN => VIDEO_EN , + VIDBASECLK_O => VIDBASECLK_O , + VIDSYNCPOL_O => VIDSYNCPOL_O , + I2C_DOUT => I2C_DOUT , + I2C_DIN => I2C_DIN , + I2C_CLOCK => I2C_CLOCK , + DEBUG_LED => DEBUG_LED , + img_mounted => img_mounted , + img_wp => img_wp , + img_size => img_size , + sd_lba => sd_lba , + sd_rd => sd_rd , + sd_wr => sd_wr , + sd_ack => sd_ack , + sd_buff_addr => sd_buff_addr , + sd_buff_dout => sd_buff_dout , + sd_buff_din => sd_buff_din , + sd_buff_wr => sd_buff_wr , + KBD_OUT_DATA => KBD_OUT_DATA , + KBD_OUT_STROBE => KBD_OUT_STROBE, + KBD_IN_DATA => KBD_IN_DATA , + KBD_IN_STROBE => KBD_IN_STROBE , + JOYSTICK0 => JOYSTICK0 , + JOYSTICK1 => JOYSTICK1 , + AUDIO_L => AUDIO_L , + AUDIO_R => AUDIO_R + ); + + DDRAM_OUT_RD <= MEM_STB_O and not MEM_WE_O; + DDRAM_OUT_WE <= MEM_STB_O and MEM_WE_O; + DDRAM_OUT_DIN <= MEM_DAT_O; + DDRAM_OUT_ADDR(23 downto 2) <= MEM_ADDR_O; + + --MEM_CYC_O + --MEM_STB_O + --MEM_WE_O + --MEM_SEL_O + --MEM_CTI_O + --MEM_ADDR_O + --MEM_DAT_O + + MEM_ACK_I <= DDRAM_OUT_DOUT_READY; + MEM_ERR_I <= '0'; + MEM_RTY_I <= '0'; + MEM_DAT_I <= DDRAM_OUT_DOUT; + + iestringprocessor : entity work.estringprocessor + port map + ( + ready => '1', + tx_command => tx_command, + tx_bytes => tx_bytes, + tx_enable => tx_enable, + rx_command => x"00000000", + rx_valid => '1' + ); + + process + variable address : integer; + + variable data : t_data := (others => 0); + + variable readmodifywrite : std_logic_vector(31 downto 0); + + file infile : bit_vector_file; + variable f_status : FILE_OPEN_STATUS; + variable read_byte0 : std_logic_vector(7 downto 0); + variable read_byte1 : std_logic_vector(7 downto 0); + variable read_byte2 : std_logic_vector(7 downto 0); + variable read_byte3 : std_logic_vector(7 downto 0); + variable next_vector : bit_vector (3 downto 0); + variable actual_len : natural; + variable targetpos : integer; + + -- copy from std_logic_arith, not used here because numeric std is also included + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR is + variable result: STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable temp: integer; + begin + + temp := ARG; + for i in 0 to SIZE-1 loop + + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + + if temp > 0 then + temp := temp / 2; + elsif (temp > integer'low) then + temp := (temp - 1) / 2; -- simulate ASR + else + temp := temp / 2; -- simulate ASR + end if; + end loop; + + return result; + end; + + begin + + DDRAM_OUT_DOUT_READY <= '0'; + + while (0 = 0) loop + + -- data from file + COMMAND_FILE_ACK <= '0'; + if COMMAND_FILE_START = '1' then + + assert false report "received" severity note; + assert false report COMMAND_FILE_NAME(1 to COMMAND_FILE_NAMELEN) severity note; + + file_open(f_status, infile, COMMAND_FILE_NAME(1 to COMMAND_FILE_NAMELEN), read_mode); + + targetpos := COMMAND_FILE_TARGET / 4; + + while (not endfile(infile)) loop + + read(infile, next_vector, actual_len); + + read_byte0 := CONV_STD_LOGIC_VECTOR(bit'pos(next_vector(0)), 8); + read_byte1 := CONV_STD_LOGIC_VECTOR(bit'pos(next_vector(1)), 8); + read_byte2 := CONV_STD_LOGIC_VECTOR(bit'pos(next_vector(2)), 8); + read_byte3 := CONV_STD_LOGIC_VECTOR(bit'pos(next_vector(3)), 8); + + if (COMMAND_FILE_ENDIAN = '1') then + data(targetpos) := to_integer(signed(read_byte3 & read_byte2 & read_byte1 & read_byte0)); + else + data(targetpos) := to_integer(signed(read_byte0 & read_byte1 & read_byte2 & read_byte3)); + end if; + targetpos := targetpos + 1; + + end loop; + + file_close(infile); + + COMMAND_FILE_ACK <= '1'; + + end if; + + if (DDRAM_OUT_BUSY = '0') then + address := to_integer(unsigned(DDRAM_OUT_ADDR)) / 4; + while (DDRAM_OUT_RD = '1') loop + DDRAM_OUT_DOUT_READY <= '1'; + DDRAM_OUT_DOUT <= std_logic_vector(to_signed(data(address), 32)); + wait until rising_edge(CLKCPU_I); + wait for 1 ns; + address := address + 1; + end loop; + DDRAM_OUT_DOUT_READY <= '0'; + + if (DDRAM_OUT_WE = '1') then + data(address) := to_integer(unsigned(DDRAM_OUT_DIN)); + end if; + end if; + + wait until rising_edge(CLKCPU_I); + end loop; + + end process; + + + +end architecture; + + diff --git a/sim/vcom_all.bat b/sim/vcom_all.bat new file mode 100644 index 0000000..767d5de --- /dev/null +++ b/sim/vcom_all.bat @@ -0,0 +1,50 @@ +RMDIR /s /q work +MKDIR work + +vmap altera_mf altera_mf + +vlib work + +vlog -O0 +incdir+./../rtl/ ../rtl/archimedes_top.v ^ +../rtl/memc.v ^ +../rtl/memc_translator.v ^ +../rtl/vidc.v ^ +../rtl/vidc_audio.v ^ +../rtl/vidc_dmachannel.v ^ +../rtl/vidc_fifo.v ^ +../rtl/vidc_timing.v ^ +../rtl/ioc.v ^ +../rtl/ioc_irq.v ^ +../rtl/fdc1772.v ^ +../rtl/floppy.v ^ +../rtl/latches.v ^ +../rtl/sram_line_en.v ^ +../rtl/sram_byte_en.v ^ +../rtl/podules.v + +vlog -O0 +incdir+./../rtl/amber/ ../rtl/amber/a23_alu.v ^ +../rtl/amber/a23_barrel_shift.v ^ +../rtl/amber/a23_barrel_shift_fpga.v ^ +../rtl/amber/a23_cache.v ^ +../rtl/amber/a23_config_defines.v ^ +../rtl/amber/a23_coprocessor.v ^ +../rtl/amber/a23_core.v ^ +../rtl/amber/a23_decode.v ^ +../rtl/amber/a23_execute.v ^ +../rtl/amber/a23_fetch.v ^ +../rtl/amber/a23_multiply.v ^ +../rtl/amber/a23_ram_register_bank.v ^ +../rtl/amber/a23_register_bank.v ^ +../rtl/amber/a23_wishbone.v + +vcom -O5 -2008 -vopt -quiet -work work ^ +../rtl/bram.vhd + +vcom -O5 -2008 -vopt -quiet -work work ^ +cpu_export.vhd + +vcom -O5 -vopt -quiet -work work ^ +globals.vhd ^ +stringprocessor.vhd ^ +tb.vhd + diff --git a/sim/vsim_start.bat b/sim/vsim_start.bat new file mode 100644 index 0000000..6474691 --- /dev/null +++ b/sim/vsim_start.bat @@ -0,0 +1 @@ +vsim -novopt work.etb -t 1ps -L C:\Projekte\ao486_MiSTer_dev\rtl\ao486\altera_mf_both \ No newline at end of file