From e4bde7a1f9c2e545df2d3d9886f577d900914198 Mon Sep 17 00:00:00 2001 From: MicroCoreLabs <54004369+MicroCoreLabs@users.noreply.github.com> Date: Sat, 25 Jan 2020 11:42:25 -0800 Subject: [PATCH] Uploaded_1_25_2020 --- Lockstep_QMR/Core/four_module_lockstep.v | 526 +++++----- Lockstep_QMR/Core/module_block.v | 94 +- MCL51/Core/MCL51_top.v | 118 ++- MCL51/Core/{mdio.vec => Microcode_MCL51.txt} | 249 +++-- MCL51/Core/biu.v | 417 ++++---- MCL51/Core/eu.v | 296 +++--- MCL65/MCL65.v | 493 ++++----- ...{microcode_rom.hex => Microcode_MCL65.txt} | 44 +- MCL86/Core/{mdio.vec => Microcode_MCL86.txt} | 162 +-- MCL86/Core/biu_max.v | 928 ++++++++--------- MCL86/Core/biu_min.v | 954 +++++++++--------- MCL86/Core/eu.v | 380 +++---- MCLR5/Core/MCLR5.v | 368 +++---- MCLR5/Core/MCLR5_alu.v | 98 +- Wheelwriter/Core/mclwr1.v | 30 +- Wheelwriter/Core/mclwr1.v.bak | 578 +++++++++++ Wheelwriter2/wheel.c | 24 +- 17 files changed, 3354 insertions(+), 2405 deletions(-) rename MCL51/Core/{mdio.vec => Microcode_MCL51.txt} (95%) rename MCL65/{microcode_rom.hex => Microcode_MCL65.txt} (98%) rename MCL86/Core/{mdio.vec => Microcode_MCL86.txt} (98%) create mode 100644 Wheelwriter/Core/mclwr1.v.bak diff --git a/Lockstep_QMR/Core/four_module_lockstep.v b/Lockstep_QMR/Core/four_module_lockstep.v index 5f4ad00..b633d42 100644 --- a/Lockstep_QMR/Core/four_module_lockstep.v +++ b/Lockstep_QMR/Core/four_module_lockstep.v @@ -21,29 +21,51 @@ // // //------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ `timescale 1ns/100ps module four_module_lockstep ( - input CORE_CLK, // Core Signals - input RST_n, + input CORE_CLK, // Core Signals + input RST_n, - - input [3:0] KILL_MODE, - input [3:0] PB_SWITCH, - output [3:0] LEDS, - output [3:0] PROBE, - - input UART_RX, // UART - output UART_TX, - output SPEAKER - + + input [3:0] KILL_MODE, + input [3:0] PB_SWITCH, + output [3:0] LEDS, + output [3:0] PROBE, + + input UART_RX, // UART + output UART_TX, + output SPEAKER + ); //------------------------------------------------------------------------ - + // Internal Signals @@ -123,15 +145,15 @@ assign core_clk_int = CORE_CLK; -assign LEDS[3] = ~module3_broadcast_ok; -assign LEDS[2] = ~module2_broadcast_ok; -assign LEDS[1] = ~module1_broadcast_ok; -assign LEDS[0] = ~module0_broadcast_ok; +assign LEDS[3] = ~module3_broadcast_ok; +assign LEDS[2] = ~module2_broadcast_ok; +assign LEDS[1] = ~module1_broadcast_ok; +assign LEDS[0] = ~module0_broadcast_ok; -assign PROBE[3] = ~module3_broadcast_ok; -assign PROBE[2] = ~module2_broadcast_ok; -assign PROBE[1] = ~module1_broadcast_ok; -assign PROBE[0] = ~module0_broadcast_ok; +assign PROBE[3] = ~module3_broadcast_ok; +assign PROBE[2] = ~module2_broadcast_ok; +assign PROBE[1] = ~module1_broadcast_ok; +assign PROBE[0] = ~module0_broadcast_ok; assign SPEAKER = speaker_int_d3; @@ -177,207 +199,207 @@ begin : BUTTON_DEBOUNCE - + //------------------------------------------------------------------------ // // Lockstep Modules // -//------------------------------------------------------------------------ - -module_block MODULE0 +//------------------------------------------------------------------------ + +module_block MODULE0 ( - .CORE_CLK (core_clk_int), - .RST_n (rst_n_d4), - .KILL (kill0), - .KILL_MODE (kmode_d4), - .MODULE_ID (2'h0), - - .BROADCAST_OK (module0_broadcast_ok), - .BROADCAST_STROBE (module0_strobe), - .BROADCAST_ADDRESS (module0_address), - .BROADCAST_DATA (module0_data), - .BROADCAST_IP (module0_ip), - .BROADCAST_SYNC (module0_sync), - .BROADCAST_IDSBL (module0_idsbl), + .CORE_CLK (core_clk_int), + .RST_n (rst_n_d4), + .KILL (kill0), + .KILL_MODE (kmode_d4), + .MODULE_ID (2'h0), + + .BROADCAST_OK (module0_broadcast_ok), + .BROADCAST_STROBE (module0_strobe), + .BROADCAST_ADDRESS (module0_address), + .BROADCAST_DATA (module0_data), + .BROADCAST_IP (module0_ip), + .BROADCAST_SYNC (module0_sync), + .BROADCAST_IDSBL (module0_idsbl), - .BROADCAST_OK_IN0 (module1_broadcast_ok), - .BROADCAST_STROBE_IN0 (module1_strobe), - .BROADCAST_ADDRESS_IN0 (module1_address), - .BROADCAST_DATA_IN0 (module1_data), - .BROADCAST_IP_IN0 (module1_ip), - .BROADCAST_SYNC_IN0 (module1_sync), - .BROADCAST_IDSBL_IN0 (module1_idsbl), - - .BROADCAST_OK_IN1 (module2_broadcast_ok), - .BROADCAST_STROBE_IN1 (module2_strobe), - .BROADCAST_ADDRESS_IN1 (module2_address), - .BROADCAST_DATA_IN1 (module2_data), - .BROADCAST_IP_IN1 (module2_ip), - .BROADCAST_SYNC_IN1 (module2_sync), - .BROADCAST_IDSBL_IN1 (module2_idsbl), + .BROADCAST_OK_IN0 (module1_broadcast_ok), + .BROADCAST_STROBE_IN0 (module1_strobe), + .BROADCAST_ADDRESS_IN0 (module1_address), + .BROADCAST_DATA_IN0 (module1_data), + .BROADCAST_IP_IN0 (module1_ip), + .BROADCAST_SYNC_IN0 (module1_sync), + .BROADCAST_IDSBL_IN0 (module1_idsbl), + + .BROADCAST_OK_IN1 (module2_broadcast_ok), + .BROADCAST_STROBE_IN1 (module2_strobe), + .BROADCAST_ADDRESS_IN1 (module2_address), + .BROADCAST_DATA_IN1 (module2_data), + .BROADCAST_IP_IN1 (module2_ip), + .BROADCAST_SYNC_IN1 (module2_sync), + .BROADCAST_IDSBL_IN1 (module2_idsbl), - .BROADCAST_OK_IN2 (module3_broadcast_ok), - .BROADCAST_STROBE_IN2 (module3_strobe), - .BROADCAST_ADDRESS_IN2 (module3_address), - .BROADCAST_DATA_IN2 (module3_data), - .BROADCAST_IP_IN2 (module3_ip), - .BROADCAST_SYNC_IN2 (module3_sync), - .BROADCAST_IDSBL_IN2 (module3_idsbl), + .BROADCAST_OK_IN2 (module3_broadcast_ok), + .BROADCAST_STROBE_IN2 (module3_strobe), + .BROADCAST_ADDRESS_IN2 (module3_address), + .BROADCAST_DATA_IN2 (module3_data), + .BROADCAST_IP_IN2 (module3_ip), + .BROADCAST_SYNC_IN2 (module3_sync), + .BROADCAST_IDSBL_IN2 (module3_idsbl), - . INT2 (interrupt2), - . INT3 (interrupt3), + . INT2 (interrupt2), + . INT3 (interrupt3), - .PROXY_RD_DATA (proxy_rd_data_int) + .PROXY_RD_DATA (proxy_rd_data_int) - ); + ); - -module_block MODULE1 + +module_block MODULE1 ( - .CORE_CLK (core_clk_int), - .RST_n (rst_n_d4), - .KILL (kill1), - .KILL_MODE (kmode_d4), - .MODULE_ID (2'h1), - - .BROADCAST_OK (module1_broadcast_ok), - .BROADCAST_STROBE (module1_strobe), - .BROADCAST_ADDRESS (module1_address), - .BROADCAST_DATA (module1_data), - .BROADCAST_IP (module1_ip), - .BROADCAST_SYNC (module1_sync), - .BROADCAST_IDSBL (module1_idsbl), + .CORE_CLK (core_clk_int), + .RST_n (rst_n_d4), + .KILL (kill1), + .KILL_MODE (kmode_d4), + .MODULE_ID (2'h1), + + .BROADCAST_OK (module1_broadcast_ok), + .BROADCAST_STROBE (module1_strobe), + .BROADCAST_ADDRESS (module1_address), + .BROADCAST_DATA (module1_data), + .BROADCAST_IP (module1_ip), + .BROADCAST_SYNC (module1_sync), + .BROADCAST_IDSBL (module1_idsbl), - .BROADCAST_OK_IN0 (module2_broadcast_ok), - .BROADCAST_STROBE_IN0 (module2_strobe), - .BROADCAST_ADDRESS_IN0 (module2_address), - .BROADCAST_DATA_IN0 (module2_data), - .BROADCAST_IP_IN0 (module2_ip), - .BROADCAST_SYNC_IN0 (module2_sync), - .BROADCAST_IDSBL_IN0 (module2_idsbl), - - .BROADCAST_OK_IN1 (module3_broadcast_ok), - .BROADCAST_STROBE_IN1 (module3_strobe), - .BROADCAST_ADDRESS_IN1 (module3_address), - .BROADCAST_DATA_IN1 (module3_data), - .BROADCAST_IP_IN1 (module3_ip), - .BROADCAST_SYNC_IN1 (module3_sync), - .BROADCAST_IDSBL_IN1 (module3_idsbl), + .BROADCAST_OK_IN0 (module2_broadcast_ok), + .BROADCAST_STROBE_IN0 (module2_strobe), + .BROADCAST_ADDRESS_IN0 (module2_address), + .BROADCAST_DATA_IN0 (module2_data), + .BROADCAST_IP_IN0 (module2_ip), + .BROADCAST_SYNC_IN0 (module2_sync), + .BROADCAST_IDSBL_IN0 (module2_idsbl), + + .BROADCAST_OK_IN1 (module3_broadcast_ok), + .BROADCAST_STROBE_IN1 (module3_strobe), + .BROADCAST_ADDRESS_IN1 (module3_address), + .BROADCAST_DATA_IN1 (module3_data), + .BROADCAST_IP_IN1 (module3_ip), + .BROADCAST_SYNC_IN1 (module3_sync), + .BROADCAST_IDSBL_IN1 (module3_idsbl), - .BROADCAST_OK_IN2 (module0_broadcast_ok), - .BROADCAST_STROBE_IN2 (module0_strobe), - .BROADCAST_ADDRESS_IN2 (module0_address), - .BROADCAST_DATA_IN2 (module0_data), - .BROADCAST_IP_IN2 (module0_ip), - .BROADCAST_SYNC_IN2 (module0_sync), - .BROADCAST_IDSBL_IN2 (module0_idsbl), + .BROADCAST_OK_IN2 (module0_broadcast_ok), + .BROADCAST_STROBE_IN2 (module0_strobe), + .BROADCAST_ADDRESS_IN2 (module0_address), + .BROADCAST_DATA_IN2 (module0_data), + .BROADCAST_IP_IN2 (module0_ip), + .BROADCAST_SYNC_IN2 (module0_sync), + .BROADCAST_IDSBL_IN2 (module0_idsbl), - . INT2 (interrupt2), - . INT3 (interrupt3), + . INT2 (interrupt2), + . INT3 (interrupt3), - .PROXY_RD_DATA (proxy_rd_data_int) + .PROXY_RD_DATA (proxy_rd_data_int) - ); + ); - -module_block MODULE2 + +module_block MODULE2 ( - .CORE_CLK (core_clk_int), - .RST_n (rst_n_d4), - .KILL (kill2), - .KILL_MODE (kmode_d4), - .MODULE_ID (2'h2), - - .BROADCAST_OK (module2_broadcast_ok), - .BROADCAST_STROBE (module2_strobe), - .BROADCAST_ADDRESS (module2_address), - .BROADCAST_DATA (module2_data), - .BROADCAST_IP (module2_ip), - .BROADCAST_SYNC (module2_sync), - .BROADCAST_IDSBL (module2_idsbl), + .CORE_CLK (core_clk_int), + .RST_n (rst_n_d4), + .KILL (kill2), + .KILL_MODE (kmode_d4), + .MODULE_ID (2'h2), + + .BROADCAST_OK (module2_broadcast_ok), + .BROADCAST_STROBE (module2_strobe), + .BROADCAST_ADDRESS (module2_address), + .BROADCAST_DATA (module2_data), + .BROADCAST_IP (module2_ip), + .BROADCAST_SYNC (module2_sync), + .BROADCAST_IDSBL (module2_idsbl), - .BROADCAST_OK_IN0 (module3_broadcast_ok), - .BROADCAST_STROBE_IN0 (module3_strobe), - .BROADCAST_ADDRESS_IN0 (module3_address), - .BROADCAST_DATA_IN0 (module3_data), - .BROADCAST_IP_IN0 (module3_ip), - .BROADCAST_SYNC_IN0 (module3_sync), - .BROADCAST_IDSBL_IN0 (module3_idsbl), - - .BROADCAST_OK_IN1 (module0_broadcast_ok), - .BROADCAST_STROBE_IN1 (module0_strobe), - .BROADCAST_ADDRESS_IN1 (module0_address), - .BROADCAST_DATA_IN1 (module0_data), - .BROADCAST_IP_IN1 (module0_ip), - .BROADCAST_SYNC_IN1 (module0_sync), - .BROADCAST_IDSBL_IN1 (module0_idsbl), + .BROADCAST_OK_IN0 (module3_broadcast_ok), + .BROADCAST_STROBE_IN0 (module3_strobe), + .BROADCAST_ADDRESS_IN0 (module3_address), + .BROADCAST_DATA_IN0 (module3_data), + .BROADCAST_IP_IN0 (module3_ip), + .BROADCAST_SYNC_IN0 (module3_sync), + .BROADCAST_IDSBL_IN0 (module3_idsbl), + + .BROADCAST_OK_IN1 (module0_broadcast_ok), + .BROADCAST_STROBE_IN1 (module0_strobe), + .BROADCAST_ADDRESS_IN1 (module0_address), + .BROADCAST_DATA_IN1 (module0_data), + .BROADCAST_IP_IN1 (module0_ip), + .BROADCAST_SYNC_IN1 (module0_sync), + .BROADCAST_IDSBL_IN1 (module0_idsbl), - .BROADCAST_OK_IN2 (module1_broadcast_ok), - .BROADCAST_STROBE_IN2 (module1_strobe), - .BROADCAST_ADDRESS_IN2 (module1_address), - .BROADCAST_DATA_IN2 (module1_data), - .BROADCAST_IP_IN2 (module1_ip), - .BROADCAST_SYNC_IN2 (module1_sync), - .BROADCAST_IDSBL_IN2 (module1_idsbl), + .BROADCAST_OK_IN2 (module1_broadcast_ok), + .BROADCAST_STROBE_IN2 (module1_strobe), + .BROADCAST_ADDRESS_IN2 (module1_address), + .BROADCAST_DATA_IN2 (module1_data), + .BROADCAST_IP_IN2 (module1_ip), + .BROADCAST_SYNC_IN2 (module1_sync), + .BROADCAST_IDSBL_IN2 (module1_idsbl), - . INT2 (interrupt2), - . INT3 (interrupt3), + . INT2 (interrupt2), + . INT3 (interrupt3), - .PROXY_RD_DATA (proxy_rd_data_int) + .PROXY_RD_DATA (proxy_rd_data_int) - ); + ); - -module_block MODULE3 + +module_block MODULE3 ( - .CORE_CLK (core_clk_int), - .RST_n (rst_n_d4), - .KILL (kill3), - .KILL_MODE (kmode_d4), - .MODULE_ID (2'h3), - - .BROADCAST_OK (module3_broadcast_ok), - .BROADCAST_STROBE (module3_strobe), - .BROADCAST_ADDRESS (module3_address), - .BROADCAST_DATA (module3_data), - .BROADCAST_IP (module3_ip), - .BROADCAST_SYNC (module3_sync), - .BROADCAST_IDSBL (module3_idsbl), + .CORE_CLK (core_clk_int), + .RST_n (rst_n_d4), + .KILL (kill3), + .KILL_MODE (kmode_d4), + .MODULE_ID (2'h3), + + .BROADCAST_OK (module3_broadcast_ok), + .BROADCAST_STROBE (module3_strobe), + .BROADCAST_ADDRESS (module3_address), + .BROADCAST_DATA (module3_data), + .BROADCAST_IP (module3_ip), + .BROADCAST_SYNC (module3_sync), + .BROADCAST_IDSBL (module3_idsbl), - .BROADCAST_OK_IN0 (module0_broadcast_ok), - .BROADCAST_STROBE_IN0 (module0_strobe), - .BROADCAST_ADDRESS_IN0 (module0_address), - .BROADCAST_DATA_IN0 (module0_data), - .BROADCAST_IP_IN0 (module0_ip), - .BROADCAST_SYNC_IN0 (module0_sync), - .BROADCAST_IDSBL_IN0 (module0_idsbl), - - .BROADCAST_OK_IN1 (module1_broadcast_ok), - .BROADCAST_STROBE_IN1 (module1_strobe), - .BROADCAST_ADDRESS_IN1 (module1_address), - .BROADCAST_DATA_IN1 (module1_data), - .BROADCAST_IP_IN1 (module1_ip), - .BROADCAST_SYNC_IN1 (module1_sync), - .BROADCAST_IDSBL_IN1 (module1_idsbl), + .BROADCAST_OK_IN0 (module0_broadcast_ok), + .BROADCAST_STROBE_IN0 (module0_strobe), + .BROADCAST_ADDRESS_IN0 (module0_address), + .BROADCAST_DATA_IN0 (module0_data), + .BROADCAST_IP_IN0 (module0_ip), + .BROADCAST_SYNC_IN0 (module0_sync), + .BROADCAST_IDSBL_IN0 (module0_idsbl), + + .BROADCAST_OK_IN1 (module1_broadcast_ok), + .BROADCAST_STROBE_IN1 (module1_strobe), + .BROADCAST_ADDRESS_IN1 (module1_address), + .BROADCAST_DATA_IN1 (module1_data), + .BROADCAST_IP_IN1 (module1_ip), + .BROADCAST_SYNC_IN1 (module1_sync), + .BROADCAST_IDSBL_IN1 (module1_idsbl), - .BROADCAST_OK_IN2 (module2_broadcast_ok), - .BROADCAST_STROBE_IN2 (module2_strobe), - .BROADCAST_ADDRESS_IN2 (module2_address), - .BROADCAST_DATA_IN2 (module2_data), - .BROADCAST_IP_IN2 (module2_ip), - .BROADCAST_SYNC_IN2 (module2_sync), - .BROADCAST_IDSBL_IN2 (module2_idsbl), + .BROADCAST_OK_IN2 (module2_broadcast_ok), + .BROADCAST_STROBE_IN2 (module2_strobe), + .BROADCAST_ADDRESS_IN2 (module2_address), + .BROADCAST_DATA_IN2 (module2_data), + .BROADCAST_IP_IN2 (module2_ip), + .BROADCAST_SYNC_IN2 (module2_sync), + .BROADCAST_IDSBL_IN2 (module2_idsbl), - . INT2 (interrupt2), - . INT3 (interrupt3), + . INT2 (interrupt2), + . INT3 (interrupt3), - .PROXY_RD_DATA (proxy_rd_data_int) + .PROXY_RD_DATA (proxy_rd_data_int) - ); + ); -//------------------------------------------------------------------------ +//------------------------------------------------------------------------ // Fixed-priority arbiter that chooses which // core's outputs to direct to the peripherals. @@ -387,23 +409,23 @@ assign top_strobe = (module0_broadcast_ok==1'b1) ? module0_strobe : (module1_broadcast_ok==1'b1) ? module1_strobe : (module2_broadcast_ok==1'b1) ? module2_strobe : (module3_broadcast_ok==1'b1) ? module3_strobe : - 8'hEE; - + 8'hEE; + assign top_address = (module0_broadcast_ok==1'b1) ? module0_address : (module1_broadcast_ok==1'b1) ? module1_address : (module2_broadcast_ok==1'b1) ? module2_address : (module3_broadcast_ok==1'b1) ? module3_address : - 16'hEEEE; - - + 16'hEEEE; + + assign top_data = (module0_broadcast_ok==1'b1) ? module0_data : (module1_broadcast_ok==1'b1) ? module1_data : (module2_broadcast_ok==1'b1) ? module2_data : (module3_broadcast_ok==1'b1) ? module3_data : - 8'hEE; - + 8'hEE; + @@ -422,39 +444,39 @@ begin : PROXY_ADDRESSING if (rst_n_d4==1'b0) begin - proxy_wr <= 'h0; - proxy_rd <= 'h0; - proxy_address <= 'h0; - prody_wr_data <= 'h0; + proxy_wr <= 'h0; + proxy_rd <= 'h0; + proxy_address <= 'h0; + prody_wr_data <= 'h0; end else begin - - if (top_strobe[7:0]==8'h11 && top_address[15:0]==16'h00C1) - begin - proxy_wr <= 1'b1; - prody_wr_data <= top_data; - end + + if (top_strobe[7:0]==8'h11 && top_address[15:0]==16'h00C1) + begin + proxy_wr <= 1'b1; + prody_wr_data <= top_data; + end else - begin - proxy_wr <= 1'b0; - end - - if (top_strobe[7:0]==8'h11 && top_address[15:0]==16'h00C2) - begin - proxy_rd <= 1'b1; - proxy_address <= top_data; - end + begin + proxy_wr <= 1'b0; + end + + if (top_strobe[7:0]==8'h11 && top_address[15:0]==16'h00C2) + begin + proxy_rd <= 1'b1; + proxy_address <= top_data; + end else - begin - proxy_rd <= 1'b0; - end - end -end - + begin + proxy_rd <= 1'b0; + end + end +end + - + //------------------------------------------------------------------------ //------------------------------------------------------------------------ // @@ -471,14 +493,14 @@ end // Steer the peripheral read data back to the modules // -assign proxy_rd_data_int = (proxy_address[7:4]==4'h0) ? timer_dataout : - (proxy_address[7:4]==4'h1) ? uart_dataout : - 8'hEE ; - +assign proxy_rd_data_int = (proxy_address[7:4]==4'h0) ? timer_dataout : + (proxy_address[7:4]==4'h1) ? uart_dataout : + 8'hEE ; + // Gate the peripheral read and write strobes -assign timer_wr_strobe = (proxy_address[7:4]==4'h0) ? proxy_wr : 1'b0; -assign uart_wr_strobe = (proxy_address[7:4]==4'h1) ? proxy_wr : 1'b0; -assign uart_rd_strobe = (proxy_address[7:4]==4'h1) ? proxy_rd : 1'b0; +assign timer_wr_strobe = (proxy_address[7:4]==4'h0) ? proxy_wr : 1'b0; +assign uart_wr_strobe = (proxy_address[7:4]==4'h1) ? proxy_wr : 1'b0; +assign uart_rd_strobe = (proxy_address[7:4]==4'h1) ? proxy_rd : 1'b0; @@ -490,40 +512,40 @@ assign uart_rd_strobe = (proxy_address[7:4]==4'h1) ? proxy_rd : 1'b0; // Timer-0 = Frequency generator // Timer-1 = Pulse generator // -//------------------------------------------------------------------------ - -timer TIMER +//------------------------------------------------------------------------ + +timer TIMER ( - .CORE_CLK (core_clk_int), - .RST_n (rst_n_d4), - .ADDRESS (proxy_address[3:0]), - .DATA_IN (prody_wr_data), - .DATA_OUT (timer_dataout), - .STROBE_WR (timer_wr_strobe), - .TIMER0_OUT (speaker_int), - .TIMER1_OUT (interrupt2) + .CORE_CLK (core_clk_int), + .RST_n (rst_n_d4), + .ADDRESS (proxy_address[3:0]), + .DATA_IN (prody_wr_data), + .DATA_OUT (timer_dataout), + .STROBE_WR (timer_wr_strobe), + .TIMER0_OUT (speaker_int), + .TIMER1_OUT (interrupt2) ); - + //------------------------------------------------------------------------ // // UART - Fixed 9600 baud // -//------------------------------------------------------------------------ +//------------------------------------------------------------------------ -uart UART +uart UART ( - .CLK (core_clk_int), - .RST_n (rst_n_d4), - .ADDRESS (proxy_address[1:0]), - .DATA_IN (prody_wr_data), - .DATA_OUT (uart_dataout), - .STROBE_RD (uart_rd_strobe), - .STROBE_WR (uart_wr_strobe), - .UART_RX (UART_RX), - .UART_TX (UART_TX), - .UART_INT (interrupt3) + .CLK (core_clk_int), + .RST_n (rst_n_d4), + .ADDRESS (proxy_address[1:0]), + .DATA_IN (prody_wr_data), + .DATA_OUT (uart_dataout), + .STROBE_RD (uart_rd_strobe), + .STROBE_WR (uart_wr_strobe), + .UART_RX (UART_RX), + .UART_TX (UART_TX), + .UART_INT (interrupt3) ); diff --git a/Lockstep_QMR/Core/module_block.v b/Lockstep_QMR/Core/module_block.v index 17281c9..aa9a11a 100644 --- a/Lockstep_QMR/Core/module_block.v +++ b/Lockstep_QMR/Core/module_block.v @@ -21,6 +21,28 @@ // // //------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ `timescale 1ns/100ps @@ -49,7 +71,7 @@ module module_block input [7:0] BROADCAST_DATA_IN0, input [15:0] BROADCAST_IP_IN0, input BROADCAST_SYNC_IN0, - input BROADCAST_IDSBL_IN0, + input BROADCAST_IDSBL_IN0, input BROADCAST_OK_IN1, input [7:0] BROADCAST_STROBE_IN1, @@ -57,7 +79,7 @@ module module_block input [7:0] BROADCAST_DATA_IN1, input [15:0] BROADCAST_IP_IN1, input BROADCAST_SYNC_IN1, - input BROADCAST_IDSBL_IN1, + input BROADCAST_IDSBL_IN1, input BROADCAST_OK_IN2, input [7:0] BROADCAST_STROBE_IN2, @@ -65,7 +87,7 @@ module module_block input [7:0] BROADCAST_DATA_IN2, input [15:0] BROADCAST_IP_IN2, input BROADCAST_SYNC_IN2, - input BROADCAST_IDSBL_IN2, + input BROADCAST_IDSBL_IN2, @@ -268,7 +290,7 @@ assign BROADCAST_DATA = ((KILL_MODE==4'h2 && kill_d4==1'b1) || (run_level! assign BROADCAST_IP = eu_register_ip; assign BROADCAST_STROBE = (run_level!=2'h3) ? { 6'h0 , MODULE_ID } : eu_biu_strobe; assign BROADCAST_SYNC = (eu_rom_address==9'h103) ? 1'b1 : 1'b0; -assign BROADCAST_IDSBL = core_interrupt_disable; +assign BROADCAST_IDSBL = core_interrupt_disable; @@ -589,12 +611,12 @@ kill_d4 <= kill_d3; // Register writeback - if (run_level==2'h1) - begin + if (run_level==2'h1) + begin eu_register_ip <= rebuild_ip_in; eu_biu_strobe <= 'h0; - end - + end + else if (eu_stall_pipeline==1'b0 && eu_opcode_type!=3'h0 && eu_opcode_type!=3'h1) begin eu_alu_last_result <= eu_alu_out[15:0]; @@ -645,14 +667,14 @@ kill_d4 <= kill_d3; else begin eu_stall_pipeline <= 1'b0; // Debounce the pipeline stall - if (KILL_MODE==4'h1 && kill_d4==1'b1) - begin - eu_rom_address <= 'h0; - end - else - begin - eu_rom_address <= eu_rom_address + 1'b1; - end + if (KILL_MODE==4'h1 && kill_d4==1'b1) + begin + eu_rom_address <= 'h0; + end + else + begin + eu_rom_address <= eu_rom_address + 1'b1; + end end end @@ -683,7 +705,7 @@ begin : BIU_CONTROLLER rebuild_addr_out <= 'h0; rebuild_addr_out_d <= 'h0; rebuild_cross_zero <= 'h0; - run_level <= 'h3; + run_level <= 'h3; end else @@ -691,16 +713,16 @@ begin : BIU_CONTROLLER // Delay address out by one clock to line up with the broadcast data if (KILL_MODE==4'h5 && kill_d4==1'b1) - begin - rebuild_addr_out_d <= 'h0; - end - else - begin - rebuild_addr_out_d <= rebuild_addr_out; - end - - // Pipeline the neighboring code SYNC pulse - rebuild_sync_in_d1 <= rebuild_sync_in; + begin + rebuild_addr_out_d <= 'h0; + end + else + begin + rebuild_addr_out_d <= rebuild_addr_out; + end + + // Pipeline the neighboring code SYNC pulse + rebuild_sync_in_d1 <= rebuild_sync_in; rebuild_sync_in_d2 <= rebuild_sync_in_d1; rebuild_sync_in_d3 <= rebuild_sync_in_d2; @@ -721,17 +743,17 @@ begin : BIU_CONTROLLER end - // Allow four passes of the full range or memory and register addresses when rebuilding a module + // Allow four passes of the full range or memory and register addresses when rebuilding a module if (run_level==2'h3) - begin + begin rebuild_cross_zero <= 'h0; - end + end else if (run_level==2'h0 && rebuild_addr=='h0) begin rebuild_cross_zero <= rebuild_cross_zero + 1'b1; end - + // If Voter has detected a failure and module is not currently in rebuilding mode, then enter rebuilding mode. if ( run_level==2'h3 && voter_good==1'b0) begin @@ -757,12 +779,12 @@ begin : BIU_CONTROLLER eu_register_r3_d1 <= eu_register_r3; - + if (run_level==2'h2) - begin - core_interrupt_disable <= neighbor_idsbl; - end - else if (eu_biu_strobe_int==3'h3) + begin + core_interrupt_disable <= neighbor_idsbl; + end + else if (eu_biu_strobe_int==3'h3) begin core_interrupt_disable <= 1'b1; end diff --git a/MCL51/Core/MCL51_top.v b/MCL51/Core/MCL51_top.v index cfc7f07..c52a11f 100644 --- a/MCL51/Core/MCL51_top.v +++ b/MCL51/Core/MCL51_top.v @@ -21,20 +21,42 @@ // // //------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ module MCL51_top ( - input CLK, - input RESET_n, + input CLK, + input RESET_n, - input UART_RX, - output UART_TX, - output SPEAKER + input UART_RX, + output UART_TX, + output SPEAKER ); //------------------------------------------------------------------------ - + // Internal Signals @@ -58,57 +80,57 @@ wire [7:0] t_biu_return_data; assign clk_int = CLK; assign t_rst_n_int = (t_biu_reset_out==1'b0 && RESET_n==1'b1) ? 1'b1 : 1'b0; - + //------------------------------------------------------------------------ // EU Core //------------------------------------------------------------------------ -eu EU_CORE +eu EU_CORE ( - .CORE_CLK (clk_int), - .RST_n (t_rst_n_int), - - .EU_BIU_STROBE (t_eu_biu_strobe), - .EU_BIU_DATAOUT (t_eu_biu_dataout), - .EU_REGISTER_R3 (t_eu_register_r3), - .EU_REGISTER_IP (t_eu_register_ip), - - .BIU_SFR_ACC (t_biu_sfr_acc), - .BIU_SFR_DPTR (t_biu_sfr_dptr), - .BIU_SFR_SP (t_biu_sfr_sp), - .BIU_SFR_PSW (t_biu_sfr_psw), - .BIU_RETURN_DATA (t_biu_return_data), - .BIU_INTERRUPT (t_biu_interrupt) + .CORE_CLK (clk_int), + .RST_n (t_rst_n_int), + + .EU_BIU_STROBE (t_eu_biu_strobe), + .EU_BIU_DATAOUT (t_eu_biu_dataout), + .EU_REGISTER_R3 (t_eu_register_r3), + .EU_REGISTER_IP (t_eu_register_ip), + + .BIU_SFR_ACC (t_biu_sfr_acc), + .BIU_SFR_DPTR (t_biu_sfr_dptr), + .BIU_SFR_SP (t_biu_sfr_sp), + .BIU_SFR_PSW (t_biu_sfr_psw), + .BIU_RETURN_DATA (t_biu_return_data), + .BIU_INTERRUPT (t_biu_interrupt) - ); - - - + ); + + + //------------------------------------------------------------------------ // BIU Core //------------------------------------------------------------------------ -biu BIU_CORE +biu BIU_CORE ( - .CORE_CLK (clk_int), - .RST_n (t_rst_n_int), - .UART_RX (UART_RX), - .UART_TX (UART_TX), - .SPEAKER (SPEAKER), - .EU_BIU_STROBE (t_eu_biu_strobe), - .EU_BIU_DATAOUT (t_eu_biu_dataout), - .EU_REGISTER_R3 (t_eu_register_r3), - .EU_REGISTER_IP (t_eu_register_ip), - .BIU_SFR_ACC (t_biu_sfr_acc), - .BIU_SFR_DPTR (t_biu_sfr_dptr), - .BIU_SFR_SP (t_biu_sfr_sp), - .BIU_SFR_PSW (t_biu_sfr_psw), - .BIU_RETURN_DATA (t_biu_return_data), - .BIU_INTERRUPT (t_biu_interrupt), - .RESET_OUT (t_biu_reset_out) - - ); - - - + .CORE_CLK (clk_int), + .RST_n (t_rst_n_int), + .UART_RX (UART_RX), + .UART_TX (UART_TX), + .SPEAKER (SPEAKER), + .EU_BIU_STROBE (t_eu_biu_strobe), + .EU_BIU_DATAOUT (t_eu_biu_dataout), + .EU_REGISTER_R3 (t_eu_register_r3), + .EU_REGISTER_IP (t_eu_register_ip), + .BIU_SFR_ACC (t_biu_sfr_acc), + .BIU_SFR_DPTR (t_biu_sfr_dptr), + .BIU_SFR_SP (t_biu_sfr_sp), + .BIU_SFR_PSW (t_biu_sfr_psw), + .BIU_RETURN_DATA (t_biu_return_data), + .BIU_INTERRUPT (t_biu_interrupt), + .RESET_OUT (t_biu_reset_out) + + ); + + + diff --git a/MCL51/Core/mdio.vec b/MCL51/Core/Microcode_MCL51.txt similarity index 95% rename from MCL51/Core/mdio.vec rename to MCL51/Core/Microcode_MCL51.txt index 0a803ee..f2064d5 100644 --- a/MCL51/Core/mdio.vec +++ b/MCL51/Core/Microcode_MCL51.txt @@ -1,111 +1,144 @@ -# -# Microcode for the MCL51 -# -# ------------------------------------------------------------------------ -# -# Copyright (C) 2019 by Ted Fried info@MicroCoreLabs.com -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, provided -# that the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting documentation. -# This software is provided "as is" without express or implied warranty. -# -# ------------------------------------------------------------------------ -# -# -# -# [15:8]=Internal Flags and system signals [7:0]=Actual PSW register from the BIU -# ** Flags must be written to the PSW through the BIU - User could access PSW by address at any time -# -# assign eu_flags_r[15] = eu_add_carry -# assign eu_flags_r[14] = eu_add_aux_carry -# assign eu_flags_r[13] = eu_add_carry16 -# assign eu_flags_r[12] = -# assign eu_flags_r[11] = -# assign eu_flags_r[10] = eu_add_overflow -# assign eu_flags_r[9] = -# assign eu_flags_r[8] = BIU_INTERRUPT -# -# assign eu_flags_r[7] = BIU_SFR_PSW[7] // C -# assign eu_flags_r[6] = BIU_SFR_PSW[6] // AC -# assign eu_flags_r[5] = BIU_SFR_PSW[5] // F0 -# assign eu_flags_r[4] = BIU_SFR_PSW[4] // RS1 -# assign eu_flags_r[3] = BIU_SFR_PSW[3] // RS0 -# assign eu_flags_r[2] = BIU_SFR_PSW[2] // Overflow -# assign eu_flags_r[1] = BIU_INTR // Interrupt from the BIU -# assign eu_flags_r[0] = BIU_SFR_PSW[0] // Parity -# -# -# -# BIU Strobes -# ------------- -# // Signals from the EU to request BIU processing -# // Only asserted for one clock cycle and cause BIU to take immediate action. -# // -# -# eu_biu_address_code = eu_biu_strobe[6:4]; -# 0=Program code space -# 1=Direct Data space -# 2=Indirect Data space -# 3=SFR or Bit address? -# -# eu_biu_strobe = eu_biu_strobe[2:0]; -# 0=idle -# 1=write BIU_DATAOUT to address in r3 -# 2=read address in r3 into BIU_RETURN_DATA -# 3=Global Interrupt Disable -# 4=Global Interrupt Enable -# -# -# EU Registers -# -------------- -# -# Destination Operand0 Operand1 -# ----------------------------------------------------------------------------------------------- -# 0 r0 0 r0 0 r0 -# 1 r1 1 r1 1 r1 -# 2 r2 2 r2 2 r2 -# 3 r3 3 r3 3 r3 -# 4 BIU_Dataout 4 00,BIU_Return_Data 4 00,SP -# 5 Dummy 5 {eu_flags_r} 5 -# 6 BIU_Strobe 6 00,ACC 6 DPTR -# 7 IP 7 IP 7 Opcode Immediate[15:0] -# 8+ 16'h0000 -# -# -# EU Opcodes -# ----------- -# 0x1 - JUMP -# ---------------- -# Bits[31:28] : 0x1 -# Bits[27:24] : CALL 1=Push next IP address to call stack -# Bits[22:20] : Jump Source: -# 0x0=Immediate[12:0] -# 0x1={4'h0 & code_byte} -- For initial Jump -# 0x2={immediate[xx:0] & code_byte[3:0]} -- Addressing modes -# 0x3=Return to CALL stored IP address -- CALL Return -# 0x4={ 7'h00 , BIU_RETURN_DATA[2:0] } -- Bit Mask decoding table -# -# -# Bits[19:16] : Jump Condition: -# 0x0=Unconditional -# 0x1=Last_ALU_Result!=0 -# 0x2=Last_ALU_Result==0 -# Bits[12:0] : Immediate[12:0] -# -# -# 0x2 - ADD -# 0x3 - XOR -# 0x4 - OR -# 0x5 - AND -# 0x6 - Byte swap eu_operand0 -# 0x7 - Shift Right based on type: { immediate[0] , eu_operand0[7:0] } -# Immedaite = 0 = Eight bit - shift in op0[0], -# 1 = Eight bit - shift in PSW_carry -# 2 = Sixteen bit - shift in eu_add_carry16 -# - +// +// +// File Name : Microcode_MCL51.txt +// Used on : MCL51 +// Author : Ted Fried, MicroCore Labs +// Creation : 1/25/2020 +// Code Type : Microcode +// +// Description: +// ============ +// +// Microcode for the MCL51 +// +//------------------------------------------------------------------------ +// +// Modification History: +// ===================== +// +// Revision 1.0 1/25/2020 +// Initial revision +// +// +//------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ + +// Microcode and microsequencer notes: +// + +[15:8]=Internal Flags and system signals [7:0]=Actual PSW register from the BIU + ** Flags must be written to the PSW through the BIU - User could access PSW by address at any time + +assign eu_flags_r[15] = eu_add_carry +assign eu_flags_r[14] = eu_add_aux_carry +assign eu_flags_r[13] = eu_add_carry16 +assign eu_flags_r[12] = +assign eu_flags_r[11] = +assign eu_flags_r[10] = eu_add_overflow +assign eu_flags_r[9] = +assign eu_flags_r[8] = BIU_INTERRUPT + +assign eu_flags_r[7] = BIU_SFR_PSW[7] // C +assign eu_flags_r[6] = BIU_SFR_PSW[6] // AC +assign eu_flags_r[5] = BIU_SFR_PSW[5] // F0 +assign eu_flags_r[4] = BIU_SFR_PSW[4] // RS1 +assign eu_flags_r[3] = BIU_SFR_PSW[3] // RS0 +assign eu_flags_r[2] = BIU_SFR_PSW[2] // Overflow +assign eu_flags_r[1] = BIU_INTR // Interrupt from the BIU +assign eu_flags_r[0] = BIU_SFR_PSW[0] // Parity + + + +BIU Strobes +------------- +// Signals from the EU to request BIU processing +// Only asserted for one clock cycle and cause BIU to take immediate action. +// + +eu_biu_address_code = eu_biu_strobe[6:4]; + 0=Program code space + 1=Direct Data space + 2=Indirect Data space + 3=SFR or Bit address? + +eu_biu_strobe = eu_biu_strobe[2:0]; + 0=idle + 1=write BIU_DATAOUT to address in r3 + 2=read address in r3 into BIU_RETURN_DATA + 3=Global Interrupt Disable + 4=Global Interrupt Enable + + +EU Registers +-------------- + +Destination Operand0 Operand1 +----------------------------------------------------------------------------------------------- +0 r0 0 r0 0 r0 +1 r1 1 r1 1 r1 +2 r2 2 r2 2 r2 +3 r3 3 r3 3 r3 +4 BIU_Dataout 4 00,BIU_Return_Data 4 00,SP +5 Dummy 5 {eu_flags_r} 5 +6 BIU_Strobe 6 00,ACC 6 DPTR +7 IP 7 IP 7 Opcode Immediate[15:0] + 8+ 16'h0000 + + +EU Opcodes +----------- +0x1 - JUMP +---------------- +Bits[31:28] : 0x1 +Bits[27:24] : CALL 1=Push next IP address to call stack +Bits[22:20] : Jump Source: + 0x0=Immediate[12:0] + 0x1={4'h0 & code_byte} -- For initial Jump + 0x2={immediate[xx:0] & code_byte[3:0]} -- Addressing modes + 0x3=Return to CALL stored IP address -- CALL Return + 0x4={ 7'h00 , BIU_RETURN_DATA[2:0] } -- Bit Mask decoding table + + +Bits[19:16] : Jump Condition: + 0x0=Unconditional + 0x1=Last_ALU_Result!=0 + 0x2=Last_ALU_Result==0 +Bits[12:0] : Immediate[12:0] + + +0x2 - ADD +0x3 - XOR +0x4 - OR +0x5 - AND +0x6 - Byte swap eu_operand0 +0x7 - Shift Right based on type: { immediate[0] , eu_operand0[7:0] } + Immedaite = 0 = Eight bit - shift in op0[0], + 1 = Eight bit - shift in PSW_carry + 2 = Sixteen bit - shift in eu_add_carry16 + + + # Reset the CPU p 00 00000 00001 0001 p 01 00000 00001 0000 diff --git a/MCL51/Core/biu.v b/MCL51/Core/biu.v index dcc8cce..d3deb50 100644 --- a/MCL51/Core/biu.v +++ b/MCL51/Core/biu.v @@ -2,7 +2,7 @@ // // File Name : biu.v // Used on : -// Author : MicroCore Labs +// Author : Ted Fried, MicroCore Labs // Creation : 3/13/16 // Code Type : Synthesizable // @@ -22,38 +22,59 @@ // // //------------------------------------------------------------------------ - +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ module biu ( - input CORE_CLK, // Core Signals - input RST_n, + input CORE_CLK, // Core Signals + input RST_n, - - input UART_RX, // Peripheral IOs - output UART_TX, - output SPEAKER, + + input UART_RX, // Peripheral IOs + output UART_TX, + output SPEAKER, - - input [7:0] EU_BIU_STROBE, // EU to BIU Signals - input [7:0] EU_BIU_DATAOUT, - input [15:0] EU_REGISTER_R3, - input [15:0] EU_REGISTER_IP, - - - output [7:0] BIU_SFR_ACC, // BIU to EU Signals - output [15:0] BIU_SFR_DPTR, - output [7:0] BIU_SFR_SP, - output [7:0] BIU_SFR_PSW, - output [7:0] BIU_RETURN_DATA, - output BIU_INTERRUPT, + + input [7:0] EU_BIU_STROBE, // EU to BIU Signals + input [7:0] EU_BIU_DATAOUT, + input [15:0] EU_REGISTER_R3, + input [15:0] EU_REGISTER_IP, + + + output [7:0] BIU_SFR_ACC, // BIU to EU Signals + output [15:0] BIU_SFR_DPTR, + output [7:0] BIU_SFR_SP, + output [7:0] BIU_SFR_PSW, + output [7:0] BIU_RETURN_DATA, + output BIU_INTERRUPT, - output RESET_OUT - + output RESET_OUT + ); //------------------------------------------------------------------------ - + // Internal Signals @@ -64,7 +85,7 @@ wire biu_int2; wire biu_int3; wire biu_sfr_select; wire acc_parity; -wire biu_timer_wr_strobe; +wire biu_timer_wr_strobe; wire biu_uart_rd_strobe; wire biu_uart_wr_strobe; wire loader_wr; @@ -85,8 +106,8 @@ wire [7:0] biu_program_data; wire [2:0] eu_biu_strobe_mode; wire [2:0] eu_biu_strobe_int; wire [7:0] biu_ram_dataout; -wire [7:0] biu_timer_dataout; -wire [7:0] biu_uart_dataout; +wire [7:0] biu_timer_dataout; +wire [7:0] biu_uart_dataout; wire [15:0] loader_addr_int; wire [7:0] loader_data_int; @@ -96,56 +117,56 @@ wire [7:0] loader_data_int; // // User Program ROM. 4Kx8 // -//------------------------------------------------------------------------ +//------------------------------------------------------------------------ /* Program ROM without interface to the UART Loader -biu_rom BIU_4Kx8 +biu_rom BIU_4Kx8 ( - .Reset (1'b0), - .OutClockEn (1'b1), - .OutClock (CORE_CLK), - .Address (EU_REGISTER_IP[11:0]), - .Q (biu_program_data) + .Reset (1'b0), + .OutClockEn (1'b1), + .OutClock (CORE_CLK), + .Address (EU_REGISTER_IP[11:0]), + .Q (biu_program_data) ); */ // For Lattice XO2 Series FPGAs -biu_rom_dp BIU_4Kx8 +biu_rom_dp BIU_4Kx8 ( - .ResetA (1'b0), - .ClockEnA (1'b1), - .ClockA (CORE_CLK), - .WrA (1'b0), - .AddressA (EU_REGISTER_IP[11:0]), - .DataInA (8'h00), - .QA (biu_program_data), + .ResetA (1'b0), + .ClockEnA (1'b1), + .ClockA (CORE_CLK), + .WrA (1'b0), + .AddressA (EU_REGISTER_IP[11:0]), + .DataInA (8'h00), + .QA (biu_program_data), - .ResetB (1'b0), - .ClockEnB (1'b1), - .ClockB (CORE_CLK), - .WrB (loader_wr), - .AddressB (loader_addr_int[11:0]), - .DataInB (loader_data_int), - .QB ( ) + .ResetB (1'b0), + .ClockEnB (1'b1), + .ClockB (CORE_CLK), + .WrB (loader_wr), + .AddressB (loader_addr_int[11:0]), + .DataInB (loader_data_int), + .QB ( ) ); - + //------------------------------------------------------------------------ // // User Data RAM. 512x8 // -//------------------------------------------------------------------------ +//------------------------------------------------------------------------ // For Lattice XO2 Series FPGAs -biu_ram BIU_512x8 +biu_ram BIU_512x8 ( - .Reset (1'b0), - .ClockEn (1'b1), - .Clock (CORE_CLK), - .Address (eu_register_r3_d1[8:0]), - .Data (EU_BIU_DATAOUT), - .Q (biu_ram_dataout), - .WE (biu_ram_wr) + .Reset (1'b0), + .ClockEn (1'b1), + .Clock (CORE_CLK), + .Address (eu_register_r3_d1[8:0]), + .Data (EU_BIU_DATAOUT), + .Q (biu_ram_dataout), + .WE (biu_ram_wr) ); //------------------------------------------------------------------------ @@ -160,12 +181,12 @@ biu_ram BIU_512x8 assign BIU_SFR_ACC = biu_sfr_acc_int; assign BIU_SFR_DPTR = { biu_sfr_dph_int , biu_sfr_dpl_int }; assign BIU_SFR_SP = biu_sfr_sp_int; -assign BIU_SFR_PSW = { biu_sfr_psw_int[7:1] , acc_parity }; +assign BIU_SFR_PSW = { biu_sfr_psw_int[7:1] , acc_parity }; -assign BIU_RETURN_DATA = (eu_biu_strobe_mode==2'h0) ? biu_program_data : - (biu_sfr_select==1'b1) ? biu_sfr_dataout : - biu_ram_dataout ; +assign BIU_RETURN_DATA = (eu_biu_strobe_mode==2'h0) ? biu_program_data : + (biu_sfr_select==1'b1) ? biu_sfr_dataout : + biu_ram_dataout ; // Parity for the Accumulator @@ -174,8 +195,8 @@ assign acc_parity = (biu_sfr_acc_int[0]^biu_sfr_acc_int[1]^biu_sfr_acc_int[2]^bi - - + + // EU strobes to request BIU processing. assign eu_biu_strobe_mode[2:0] = EU_BIU_STROBE[6:4]; assign eu_biu_strobe_int[2:0] = EU_BIU_STROBE[2:0]; @@ -183,7 +204,7 @@ assign eu_biu_strobe_int[2:0] = EU_BIU_STROBE[2:0]; // Select the SFR range if the address is 0x0080 to 0x00FF and addressing mode is Direct -assign biu_sfr_select = ( eu_register_r3_d1[15:7]==9'b0000_0000_1 && eu_biu_strobe_mode[1:0]==3'h1) ? 1'b1 : 1'b0; +assign biu_sfr_select = ( eu_register_r3_d1[15:7]==9'b0000_0000_1 && eu_biu_strobe_mode[1:0]==3'h1) ? 1'b1 : 1'b0; // Decode the write enable to the RAM block @@ -191,41 +212,41 @@ assign biu_ram_wr = (biu_sfr_select==1'b0 && eu_biu_strobe_int==3'h1) ? 1'b1 : 1 // Mux the SFR data outputs -assign biu_sfr_dataout = (eu_register_r3_d1[7:0]==8'h81) ? biu_sfr_sp_int : - (eu_register_r3_d1[7:0]==8'h82) ? biu_sfr_dpl_int : - (eu_register_r3_d1[7:0]==8'h83) ? biu_sfr_dph_int : - (eu_register_r3_d1[7:0]==8'hA8) ? biu_sfr_ie_int : - (eu_register_r3_d1[7:0]==8'hA9) ? biu_sfr_is_int : +assign biu_sfr_dataout = (eu_register_r3_d1[7:0]==8'h81) ? biu_sfr_sp_int : + (eu_register_r3_d1[7:0]==8'h82) ? biu_sfr_dpl_int : + (eu_register_r3_d1[7:0]==8'h83) ? biu_sfr_dph_int : + (eu_register_r3_d1[7:0]==8'hA8) ? biu_sfr_ie_int : + (eu_register_r3_d1[7:0]==8'hA9) ? biu_sfr_is_int : (eu_register_r3_d1[7:0]==8'hC0) ? biu_sfr_pxy_din : - (eu_register_r3_d1[7:0]==8'hD0) ? biu_sfr_psw_int : + (eu_register_r3_d1[7:0]==8'hD0) ? biu_sfr_psw_int : (eu_register_r3_d1[7:0]==8'hE0) ? biu_sfr_acc_int : (eu_register_r3_d1[7:0]==8'hF0) ? biu_sfr_b_int : - 8'hEE ; + 8'hEE ; - - - - + + + + - + // Simple fixed priority interrupt controller // biu_sfr_ie_int[7] is the global_intr_enable // biu_sfr_is_int[3:0] contains the interrupt source -// Interrupt 2 = Timer Interrupt Vector at address 0x4 -// 3 = UART-RX Interrupt Vector at address 0x6 +// Interrupt 2 = Timer Interrupt Vector at address 0x4 +// 3 = UART-RX Interrupt Vector at address 0x6 // assign BIU_INTERRUPT = (core_interrupt_disable==1'b0 && biu_sfr_ie_int[7]==1'b1 && biu_int2==1'b1) ? 1'b1 : (core_interrupt_disable==1'b0 && biu_sfr_ie_int[7]==1'b1 && biu_int3==1'b1) ? 1'b1 : 1'b0; // (core_interrupt_disable==1'b0 && biu_sfr_ie_int[7]==1'b1 && biu_int4==1'b1) ? 1'b1 : -// 1'b0 ; - +// 1'b0 ; + assign biu_sfr_is_int[7:4] = 4'h0; assign biu_sfr_is_int[3:0] = (biu_int2==1'b1) ? 4'h2 : (biu_int3==1'b1) ? 4'h3 : 4'hF; -// 4'h4 ; - - - +// 4'h4 ; + + + //------------------------------------------------------------------------ // // BIU Controller @@ -238,89 +259,89 @@ begin : BIU_CONTROLLER if (RST_n==1'b0) begin - biu_sfr_dpl_int <= 'h0; - biu_sfr_dph_int <= 'h0; - biu_sfr_ie_int <= 'h0; - biu_sfr_psw_int <= 'h0; - biu_sfr_acc_int <= 'h0; - biu_sfr_b_int <= 8'h00; - biu_sfr_sp_int <= 'h07; - eu_register_r3_d1 <= 'h0; - biu_pxy_rd <= 'h0; - biu_pxy_wr <= 'h0; - biu_sfr_pxy_addr <= 'h0; - biu_sfr_pxy_dout <= 'h0; - core_interrupt_disable <= 'h0; + biu_sfr_dpl_int <= 'h0; + biu_sfr_dph_int <= 'h0; + biu_sfr_ie_int <= 'h0; + biu_sfr_psw_int <= 'h0; + biu_sfr_acc_int <= 'h0; + biu_sfr_b_int <= 8'h00; + biu_sfr_sp_int <= 'h07; + eu_register_r3_d1 <= 'h0; + biu_pxy_rd <= 'h0; + biu_pxy_wr <= 'h0; + biu_sfr_pxy_addr <= 'h0; + biu_sfr_pxy_dout <= 'h0; + core_interrupt_disable <= 'h0; end else begin eu_register_r3_d1 <= EU_REGISTER_R3; - - if (eu_biu_strobe_int==3'h3) - begin - core_interrupt_disable <= 1'b1; - end - - if (eu_biu_strobe_int==3'h4) - begin - core_interrupt_disable <= 1'b0; - end - - - - // Writes to SFR's - if (biu_sfr_select==1'b1 && eu_biu_strobe_int==3'h1) - begin - case (eu_register_r3_d1[7:0]) // synthesis parallel_case - - 8'h81 : biu_sfr_sp_int <= EU_BIU_DATAOUT[7:0]; - 8'h82 : biu_sfr_dpl_int <= EU_BIU_DATAOUT[7:0]; - 8'h83 : biu_sfr_dph_int <= EU_BIU_DATAOUT[7:0]; - 8'hA8 : biu_sfr_ie_int <= EU_BIU_DATAOUT[7:0]; - 8'hD0 : biu_sfr_psw_int <= EU_BIU_DATAOUT[7:0]; - 8'hE0 : biu_sfr_acc_int <= EU_BIU_DATAOUT[7:0]; - 8'hF0 : biu_sfr_b_int <= EU_BIU_DATAOUT[7:0]; - - // Proxy Addressing Registers - 8'hC1 : biu_sfr_pxy_dout <= EU_BIU_DATAOUT[7:0]; - 8'hC2 : biu_sfr_pxy_addr <= EU_BIU_DATAOUT[7:0]; - - default : ; - endcase - end - - - // Assert the write strobe to the proxy addressed peripherals - if (biu_sfr_select==1'b1 && eu_biu_strobe_int==3'h1 && eu_register_r3_d1[7:0]==8'hC1) - begin - biu_pxy_wr <= 1'b1; - end - else - begin - biu_pxy_wr <= 1'b0; - end - - - // Assert the read strobe to the proxy addressed peripherals - if (biu_sfr_select==1'b1 && eu_biu_strobe_int==3'h1 && eu_register_r3_d1[7:0]==8'hC2) - begin - biu_pxy_rd <= 1'b1; - end - else - begin - biu_pxy_rd <= 1'b0; - end - - - - end + + if (eu_biu_strobe_int==3'h3) + begin + core_interrupt_disable <= 1'b1; + end + + if (eu_biu_strobe_int==3'h4) + begin + core_interrupt_disable <= 1'b0; + end + + + + // Writes to SFR's + if (biu_sfr_select==1'b1 && eu_biu_strobe_int==3'h1) + begin + case (eu_register_r3_d1[7:0]) // synthesis parallel_case + + 8'h81 : biu_sfr_sp_int <= EU_BIU_DATAOUT[7:0]; + 8'h82 : biu_sfr_dpl_int <= EU_BIU_DATAOUT[7:0]; + 8'h83 : biu_sfr_dph_int <= EU_BIU_DATAOUT[7:0]; + 8'hA8 : biu_sfr_ie_int <= EU_BIU_DATAOUT[7:0]; + 8'hD0 : biu_sfr_psw_int <= EU_BIU_DATAOUT[7:0]; + 8'hE0 : biu_sfr_acc_int <= EU_BIU_DATAOUT[7:0]; + 8'hF0 : biu_sfr_b_int <= EU_BIU_DATAOUT[7:0]; + + // Proxy Addressing Registers + 8'hC1 : biu_sfr_pxy_dout <= EU_BIU_DATAOUT[7:0]; + 8'hC2 : biu_sfr_pxy_addr <= EU_BIU_DATAOUT[7:0]; + + default : ; + endcase + end + + + // Assert the write strobe to the proxy addressed peripherals + if (biu_sfr_select==1'b1 && eu_biu_strobe_int==3'h1 && eu_register_r3_d1[7:0]==8'hC1) + begin + biu_pxy_wr <= 1'b1; + end + else + begin + biu_pxy_wr <= 1'b0; + end + + + // Assert the read strobe to the proxy addressed peripherals + if (biu_sfr_select==1'b1 && eu_biu_strobe_int==3'h1 && eu_register_r3_d1[7:0]==8'hC2) + begin + biu_pxy_rd <= 1'b1; + end + else + begin + biu_pxy_rd <= 1'b0; + end + + + + end end - + //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ @@ -338,14 +359,14 @@ end // // Steer the peripheral read data -assign biu_sfr_pxy_din = (biu_sfr_pxy_addr[7:4]==4'h0) ? biu_timer_dataout : - (biu_sfr_pxy_addr[7:4]==4'h1) ? biu_uart_dataout : - 8'hEE ; - +assign biu_sfr_pxy_din = (biu_sfr_pxy_addr[7:4]==4'h0) ? biu_timer_dataout : + (biu_sfr_pxy_addr[7:4]==4'h1) ? biu_uart_dataout : + 8'hEE ; + // Gate the peripheral read and write strobes -assign biu_timer_wr_strobe = (biu_sfr_pxy_addr[7:4]==4'h0) ? biu_pxy_wr : 1'b0; -assign biu_uart_wr_strobe = (biu_sfr_pxy_addr[7:4]==4'h1) ? biu_pxy_wr : 1'b0; -assign biu_uart_rd_strobe = (biu_sfr_pxy_addr[7:4]==4'h1) ? biu_pxy_rd : 1'b0; +assign biu_timer_wr_strobe = (biu_sfr_pxy_addr[7:4]==4'h0) ? biu_pxy_wr : 1'b0; +assign biu_uart_wr_strobe = (biu_sfr_pxy_addr[7:4]==4'h1) ? biu_pxy_wr : 1'b0; +assign biu_uart_rd_strobe = (biu_sfr_pxy_addr[7:4]==4'h1) ? biu_pxy_rd : 1'b0; @@ -357,49 +378,49 @@ assign biu_uart_rd_strobe = (biu_sfr_pxy_addr[7:4]==4'h1) ? biu_pxy_rd : 1'b0; // Timer-0 = Frequency generator // Timer-1 = Pulse generator // -//------------------------------------------------------------------------ - -timer BIU_TIMER +//------------------------------------------------------------------------ + +timer BIU_TIMER ( - .CORE_CLK (CORE_CLK), - .RST_n (RST_n), - .ADDRESS (biu_sfr_pxy_addr[3:0]), - .DATA_IN (biu_sfr_pxy_dout), - .DATA_OUT (biu_timer_dataout), - .STROBE_WR (biu_timer_wr_strobe), - .TIMER0_OUT (SPEAKER), - .TIMER1_OUT (biu_int2) + .CORE_CLK (CORE_CLK), + .RST_n (RST_n), + .ADDRESS (biu_sfr_pxy_addr[3:0]), + .DATA_IN (biu_sfr_pxy_dout), + .DATA_OUT (biu_timer_dataout), + .STROBE_WR (biu_timer_wr_strobe), + .TIMER0_OUT (SPEAKER), + .TIMER1_OUT (biu_int2) ); - + //------------------------------------------------------------------------ // // UART - Fixed 9600 baud // -//------------------------------------------------------------------------ +//------------------------------------------------------------------------ -uart_and_loader BIU_UART +uart_and_loader BIU_UART ( - .CLK (CORE_CLK), - .RST_n (RST_n), - .ADDRESS (biu_sfr_pxy_addr[1:0]), - .DATA_IN (biu_sfr_pxy_dout), - .DATA_OUT (biu_uart_dataout), - .STROBE_RD (biu_uart_rd_strobe), - .STROBE_WR (biu_uart_wr_strobe), - .UART_RX (UART_RX), - .UART_TX (UART_TX), - .UART_INT (biu_int3), + .CLK (CORE_CLK), + .RST_n (RST_n), + .ADDRESS (biu_sfr_pxy_addr[1:0]), + .DATA_IN (biu_sfr_pxy_dout), + .DATA_OUT (biu_uart_dataout), + .STROBE_RD (biu_uart_rd_strobe), + .STROBE_WR (biu_uart_wr_strobe), + .UART_RX (UART_RX), + .UART_TX (UART_TX), + .UART_INT (biu_int3), - .LOADER_ADDR (loader_addr_int ), - .LOADER_DATA (loader_data_int ), - .LOADER_WR (loader_wr ), - .RESET_OUT (RESET_OUT ) - + .LOADER_ADDR (loader_addr_int ), + .LOADER_DATA (loader_data_int ), + .LOADER_WR (loader_wr ), + .RESET_OUT (RESET_OUT ) + ); - + endmodule // biu.v - - \ No newline at end of file + + \ No newline at end of file diff --git a/MCL51/Core/eu.v b/MCL51/Core/eu.v index 25574f2..bf2d760 100644 --- a/MCL51/Core/eu.v +++ b/MCL51/Core/eu.v @@ -2,7 +2,7 @@ // // File Name : eu.v // Used on : MCL51 -// Author : MicroCore Labs +// Author : Ted Fried, MicroCore Labs // Creation : 3/13/2016 // Code Type : Synthesizable // @@ -21,31 +21,53 @@ // // //------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ module eu ( - input CORE_CLK, // Core Clock - input RST_n, - - - output [7:0] EU_BIU_STROBE, // EU to BIU Signals - output [7:0] EU_BIU_DATAOUT, - output [15:0] EU_REGISTER_R3, - output [15:0] EU_REGISTER_IP, - - - input [7:0] BIU_SFR_ACC, // BIU to EU Signals - input [15:0] BIU_SFR_DPTR, - input [7:0] BIU_SFR_SP, - input [7:0] BIU_SFR_PSW, - input [7:0] BIU_RETURN_DATA, - input BIU_INTERRUPT + input CORE_CLK, // Core Clock + input RST_n, + + + output [7:0] EU_BIU_STROBE, // EU to BIU Signals + output [7:0] EU_BIU_DATAOUT, + output [15:0] EU_REGISTER_R3, + output [15:0] EU_REGISTER_IP, + + + input [7:0] BIU_SFR_ACC, // BIU to EU Signals + input [15:0] BIU_SFR_DPTR, + input [7:0] BIU_SFR_SP, + input [7:0] BIU_SFR_PSW, + input [7:0] BIU_RETURN_DATA, + input BIU_INTERRUPT ); //------------------------------------------------------------------------ - + // Internal Signals @@ -94,29 +116,29 @@ wire [15:0] eu_flags_r; // // EU Microcode ROM. 1Kx32 // -//------------------------------------------------------------------------ +//------------------------------------------------------------------------ /* // For Lattice XO2 FPGAs -eu_rom EU_1Kx32 +eu_rom EU_1Kx32 ( - .Reset (1'b0), - .OutClockEn (1'b1), - .OutClock (CORE_CLK), - .Address (eu_rom_address[9:0]), - .Q (eu_rom_data) + .Reset (1'b0), + .OutClockEn (1'b1), + .OutClock (CORE_CLK), + .Address (eu_rom_address[9:0]), + .Q (eu_rom_data) ); */ // For Xilinx Artix FPGAs -eu_rom EU_1Kx32 +eu_rom EU_1Kx32 ( - .clka (CORE_CLK), - .addra (eu_rom_address[9:0]), - .douta (eu_rom_data) + .clka (CORE_CLK), + .addra (eu_rom_address[9:0]), + .douta (eu_rom_data) ); - + @@ -127,72 +149,72 @@ eu_rom EU_1Kx32 // //------------------------------------------------------------------------ -assign EU_BIU_STROBE = eu_biu_strobe; -assign EU_BIU_DATAOUT = eu_biu_dataout; -assign EU_REGISTER_R3 = eu_register_r3; -assign EU_REGISTER_IP = eu_register_ip; +assign EU_BIU_STROBE = eu_biu_strobe; +assign EU_BIU_DATAOUT = eu_biu_dataout; +assign EU_REGISTER_R3 = eu_register_r3; +assign EU_REGISTER_IP = eu_register_ip; // EU ROM opcode decoder -assign eu_opcode_type = eu_rom_data[30:28]; -assign eu_opcode_dst_sel = eu_rom_data[26:24]; -assign eu_opcode_op0_sel = eu_rom_data[23:20]; -assign eu_opcode_op1_sel = eu_rom_data[18:16]; +assign eu_opcode_type = eu_rom_data[30:28]; +assign eu_opcode_dst_sel = eu_rom_data[26:24]; +assign eu_opcode_op0_sel = eu_rom_data[23:20]; +assign eu_opcode_op1_sel = eu_rom_data[18:16]; assign eu_opcode_immediate = eu_rom_data[15:0]; -assign eu_opcode_jump_call = eu_rom_data[24]; -assign eu_opcode_jump_src = eu_rom_data[22:20]; -assign eu_opcode_jump_cond = eu_rom_data[18:16]; +assign eu_opcode_jump_call = eu_rom_data[24]; +assign eu_opcode_jump_src = eu_rom_data[22:20]; +assign eu_opcode_jump_cond = eu_rom_data[18:16]; -assign eu_operand0 = (eu_opcode_op0_sel==4'h0) ? eu_register_r0 : - (eu_opcode_op0_sel==4'h1) ? eu_register_r1 : - (eu_opcode_op0_sel==4'h2) ? eu_register_r2 : - (eu_opcode_op0_sel==4'h3) ? eu_register_r3 : +assign eu_operand0 = (eu_opcode_op0_sel==4'h0) ? eu_register_r0 : + (eu_opcode_op0_sel==4'h1) ? eu_register_r1 : + (eu_opcode_op0_sel==4'h2) ? eu_register_r2 : + (eu_opcode_op0_sel==4'h3) ? eu_register_r3 : (eu_opcode_op0_sel==4'h4) ? { 8'h00 , BIU_RETURN_DATA } : - (eu_opcode_op0_sel==4'h5) ? { eu_flags_r[15:0] } : + (eu_opcode_op0_sel==4'h5) ? { eu_flags_r[15:0] } : (eu_opcode_op0_sel==4'h6) ? { 8'h00 , BIU_SFR_ACC } : - (eu_opcode_op0_sel==4'h7) ? eu_register_ip : - 16'h0000 ; + (eu_opcode_op0_sel==4'h7) ? eu_register_ip : + 16'h0000 ; -assign eu_operand1 = (eu_opcode_op1_sel==3'h0) ? eu_register_r0 : - (eu_opcode_op1_sel==3'h1) ? eu_register_r1 : - (eu_opcode_op1_sel==3'h2) ? eu_register_r2 : - (eu_opcode_op1_sel==3'h3) ? eu_register_r3 : - (eu_opcode_op1_sel==3'h4) ? { 8'h00 , BIU_SFR_SP } : - //(eu_opcode_op1_sel==3'h5) ? eu_alu_last_result : - (eu_opcode_op1_sel==3'h6) ? BIU_SFR_DPTR : - eu_opcode_immediate ; +assign eu_operand1 = (eu_opcode_op1_sel==3'h0) ? eu_register_r0 : + (eu_opcode_op1_sel==3'h1) ? eu_register_r1 : + (eu_opcode_op1_sel==3'h2) ? eu_register_r2 : + (eu_opcode_op1_sel==3'h3) ? eu_register_r3 : + (eu_opcode_op1_sel==3'h4) ? { 8'h00 , BIU_SFR_SP } : + //(eu_opcode_op1_sel==3'h5) ? eu_alu_last_result : + (eu_opcode_op1_sel==3'h6) ? BIU_SFR_DPTR : + eu_opcode_immediate ; - + // JUMP condition codes assign eu_jump_gate = (eu_opcode_jump_cond==4'h0) ? 1'b1 : // unconditional jump (eu_opcode_jump_cond==4'h1 && eu_alu_last_result!=16'h0) ? 1'b1 : (eu_opcode_jump_cond==4'h2 && eu_alu_last_result==16'h0) ? 1'b1 : - 1'b0 ; + 1'b0 ; - + // ** Flags must be written to the PSW through the BIU - -assign eu_flags_r[15] = eu_add_carry; -assign eu_flags_r[14] = eu_add_aux_carry; + +assign eu_flags_r[15] = eu_add_carry; +assign eu_flags_r[14] = eu_add_aux_carry; assign eu_flags_r[13] = eu_add_carry16; -//assign eu_flags_r[12] = -//assign eu_flags_r[11] = -assign eu_flags_r[10] = eu_add_overflow; -//assign eu_flags_r[9] = -assign eu_flags_r[8] = BIU_INTERRUPT; +//assign eu_flags_r[12] = +//assign eu_flags_r[11] = +assign eu_flags_r[10] = eu_add_overflow; +//assign eu_flags_r[9] = +assign eu_flags_r[8] = BIU_INTERRUPT; -assign eu_flags_r[7] = BIU_SFR_PSW[7]; // C -assign eu_flags_r[6] = BIU_SFR_PSW[6]; // AC -assign eu_flags_r[5] = BIU_SFR_PSW[5]; // F0 -assign eu_flags_r[4] = BIU_SFR_PSW[4]; // RS1 -assign eu_flags_r[3] = BIU_SFR_PSW[3]; // RS0 -assign eu_flags_r[2] = BIU_SFR_PSW[2]; // Overflow -assign eu_flags_r[1] = BIU_SFR_PSW[1]; // User Defined Flag -assign eu_flags_r[0] = BIU_SFR_PSW[0]; // ACC Parity generated in the BIU +assign eu_flags_r[7] = BIU_SFR_PSW[7]; // C +assign eu_flags_r[6] = BIU_SFR_PSW[6]; // AC +assign eu_flags_r[5] = BIU_SFR_PSW[5]; // F0 +assign eu_flags_r[4] = BIU_SFR_PSW[4]; // RS1 +assign eu_flags_r[3] = BIU_SFR_PSW[3]; // RS0 +assign eu_flags_r[2] = BIU_SFR_PSW[2]; // Overflow +assign eu_flags_r[1] = BIU_SFR_PSW[1]; // User Defined Flag +assign eu_flags_r[0] = BIU_SFR_PSW[0]; // ACC Parity generated in the BIU @@ -201,13 +223,13 @@ assign eu_flags_r[0] = BIU_SFR_PSW[0]; // ACC Parity generated in the BIU // ------------------------------------------ // eu_alu0 = NOP // eu_alu1 = JUMP -assign eu_alu2 = adder_out; // ADD -assign eu_alu3 = eu_operand0 ^ eu_operand1; // XOR -assign eu_alu4 = eu_operand0 | eu_operand1; // OR -assign eu_alu5 = eu_operand0 & eu_operand1; // AND -assign eu_alu6 = { eu_operand0[7:0] , eu_operand0[15:8] }; // BYTESWAP -assign eu_alu7 = (eu_opcode_immediate[1:0]==2'h0) ? { 8'h00 , eu_operand0[0] , eu_operand0[7:1] } : // Rotate in bit[0] - (eu_opcode_immediate[1:0]==2'h1) ? { 8'h00 , BIU_SFR_PSW[7] , eu_operand0[7:1] } : // Rotate in Carry bit +assign eu_alu2 = adder_out; // ADD +assign eu_alu3 = eu_operand0 ^ eu_operand1; // XOR +assign eu_alu4 = eu_operand0 | eu_operand1; // OR +assign eu_alu5 = eu_operand0 & eu_operand1; // AND +assign eu_alu6 = { eu_operand0[7:0] , eu_operand0[15:8] }; // BYTESWAP +assign eu_alu7 = (eu_opcode_immediate[1:0]==2'h0) ? { 8'h00 , eu_operand0[0] , eu_operand0[7:1] } : // Rotate in bit[0] + (eu_opcode_immediate[1:0]==2'h1) ? { 8'h00 , BIU_SFR_PSW[7] , eu_operand0[7:1] } : // Rotate in Carry bit { eu_add_carry16 , eu_operand0[15:1] } ; // 16-bit shift-right @@ -220,7 +242,7 @@ assign eu_alu_out = (eu_opcode_type==3'h2) ? eu_alu2 : (eu_opcode_type==3'h7) ? eu_alu7 : 16'hEEEE; - + // Generate 16-bit full adder for the EU assign carry[0] = 1'b0; @@ -228,17 +250,17 @@ genvar i; generate for (i=0; i < 16; i=i+1) begin : GEN_ADDER - assign adder_out[i] = eu_operand0[i] ^ eu_operand1[i] ^ carry[i]; - assign carry[i+1] = (eu_operand0[i] & eu_operand1[i]) | (eu_operand0[i] & carry[i]) | (eu_operand1[i] & carry[i]); + assign adder_out[i] = eu_operand0[i] ^ eu_operand1[i] ^ carry[i]; + assign carry[i+1] = (eu_operand0[i] & eu_operand1[i]) | (eu_operand0[i] & carry[i]) | (eu_operand1[i] & carry[i]); end endgenerate -assign new_instruction = (eu_rom_address[9:8]==2'b00) ? 1'b1 : 1'b0; +assign new_instruction = (eu_rom_address[9:8]==2'b00) ? 1'b1 : 1'b0; - + //------------------------------------------------------------------------------------------ // // EU Microsequencer @@ -259,7 +281,7 @@ begin : EU_MICROSEQUENCER eu_register_r1 <= 'h0; eu_register_r2 <= 'h0; eu_register_r3 <= 'h0; - eu_register_ip <= 16'hFFFF; // User Program code starts at 0x0000 after reset. Main loop does initial increment. + eu_register_ip <= 16'hFFFF; // User Program code starts at 0x0000 after reset. Main loop does initial increment. eu_biu_strobe <= 'h0; eu_biu_dataout <= 'h0; eu_stall_pipeline <= 'h0; @@ -270,64 +292,64 @@ begin : EU_MICROSEQUENCER else begin - - // Generate and store flags for addition - if (eu_stall_pipeline==1'b0 && eu_opcode_type==3'h2) - begin - eu_add_carry16 <= carry[16]; - eu_add_carry <= carry[8]; - eu_add_aux_carry <= carry[4]; - eu_add_overflow <= carry[8] ^ carry[7]; + + // Generate and store flags for addition + if (eu_stall_pipeline==1'b0 && eu_opcode_type==3'h2) + begin + eu_add_carry16 <= carry[16]; + eu_add_carry <= carry[8]; + eu_add_aux_carry <= carry[4]; + eu_add_overflow <= carry[8] ^ carry[7]; end - - // Register writeback + + // Register writeback if (eu_stall_pipeline==1'b0 && eu_opcode_type!=3'h0 && eu_opcode_type!=3'h1) - begin - eu_alu_last_result <= eu_alu_out[15:0]; - case (eu_opcode_dst_sel) // synthesis parallel_case - 3'h0 : eu_register_r0 <= eu_alu_out[15:0]; - 3'h1 : eu_register_r1 <= eu_alu_out[15:0]; - 3'h2 : eu_register_r2 <= eu_alu_out[15:0]; - 3'h3 : eu_register_r3 <= eu_alu_out[15:0]; - 3'h4 : eu_biu_dataout <= eu_alu_out[7:0]; - //3'h5 : - 3'h6 : eu_biu_strobe <= eu_alu_out[7:0]; - 3'h7 : eu_register_ip <= eu_alu_out[15:0]; - default : ; - endcase + begin + eu_alu_last_result <= eu_alu_out[15:0]; + case (eu_opcode_dst_sel) // synthesis parallel_case + 3'h0 : eu_register_r0 <= eu_alu_out[15:0]; + 3'h1 : eu_register_r1 <= eu_alu_out[15:0]; + 3'h2 : eu_register_r2 <= eu_alu_out[15:0]; + 3'h3 : eu_register_r3 <= eu_alu_out[15:0]; + 3'h4 : eu_biu_dataout <= eu_alu_out[7:0]; + //3'h5 : + 3'h6 : eu_biu_strobe <= eu_alu_out[7:0]; + 3'h7 : eu_register_ip <= eu_alu_out[15:0]; + default : ; + endcase end - // JUMP Opcode - if (eu_stall_pipeline==1'b0 && eu_opcode_type==3'h1 && eu_jump_gate==1'b1) - begin - eu_stall_pipeline <= 1'b1; - - // For subroutine CALLs, store next opcode address - if (eu_opcode_jump_call==1'b1) - begin - eu_calling_address[19:0] <= {eu_calling_address[9:0] , eu_rom_address[9:0] }; // Two deep calling addresses - end + // JUMP Opcode + if (eu_stall_pipeline==1'b0 && eu_opcode_type==3'h1 && eu_jump_gate==1'b1) + begin + eu_stall_pipeline <= 1'b1; + + // For subroutine CALLs, store next opcode address + if (eu_opcode_jump_call==1'b1) + begin + eu_calling_address[19:0] <= {eu_calling_address[9:0] , eu_rom_address[9:0] }; // Two deep calling addresses + end - case (eu_opcode_jump_src) // synthesis parallel_case - 3'h0 : eu_rom_address <= eu_opcode_immediate[9:0]; - 3'h1 : eu_rom_address <= { 2'h0 , BIU_RETURN_DATA }; // Initial opcode jump decoding - 3'h2 : eu_rom_address <= { eu_opcode_immediate[9:4] , eu_register_r0[11:8] }; // EA decoding - 3'h3 : begin // CALL Return - eu_rom_address <= eu_calling_address[9:0]; - eu_calling_address[9:0] <= eu_calling_address[19:10]; - end - 3'h4 : eu_rom_address <= { eu_opcode_immediate[5:0] , BIU_RETURN_DATA[2:0] , 1'b0 }; // Bit Mask decoding table - - default : ; - endcase - end - + case (eu_opcode_jump_src) // synthesis parallel_case + 3'h0 : eu_rom_address <= eu_opcode_immediate[9:0]; + 3'h1 : eu_rom_address <= { 2'h0 , BIU_RETURN_DATA }; // Initial opcode jump decoding + 3'h2 : eu_rom_address <= { eu_opcode_immediate[9:4] , eu_register_r0[11:8] }; // EA decoding + 3'h3 : begin // CALL Return + eu_rom_address <= eu_calling_address[9:0]; + eu_calling_address[9:0] <= eu_calling_address[19:10]; + end + 3'h4 : eu_rom_address <= { eu_opcode_immediate[5:0] , BIU_RETURN_DATA[2:0] , 1'b0 }; // Bit Mask decoding table + + default : ; + endcase + end + else begin - eu_stall_pipeline <= 1'b0; // Debounce the pipeline stall - eu_rom_address <= eu_rom_address + 1'b1; + eu_stall_pipeline <= 1'b0; // Debounce the pipeline stall + eu_rom_address <= eu_rom_address + 1'b1; end end diff --git a/MCL65/MCL65.v b/MCL65/MCL65.v index 1c67d14..04294eb 100644 --- a/MCL65/MCL65.v +++ b/MCL65/MCL65.v @@ -21,37 +21,58 @@ // // //------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ module MCL65 ( - input CORE_CLK, // Microsequencer Core Clock - + input CORE_CLK, // Microsequencer Core Clock - input CLK0, // 6502 Bus Signals - output CLK1, - output CLK2, + input CLK0, // 6502 Bus Signals + output CLK1, + output CLK2, - input RESET_n, - input NMI_n, - input IRQ_n, - input SO, + input RESET_n, + input NMI_n, + input IRQ_n, + input SO, - output SYNC, - output RDWR_n, - input READY, - - output [15:0] A, - inout [7:0] D, - - output DIR0, - output DIR1 + output SYNC, + output RDWR_n, + input READY, + + output [15:0] A, + inout [7:0] D, + + output DIR0, + output DIR1 ); //------------------------------------------------------------------------ - + // Internal Signals @@ -65,18 +86,18 @@ reg clk0_int_d3 = 'h0; reg clk0_int_d4 = 'h0; reg reset_n_d1 = 'h0; reg reset_n_d2 = 'h0; -reg nmi_n_d1 = 'h0; -reg nmi_n_d2 = 'h0; -reg nmi_n_d3 = 'h0; -reg nmi_asserted = 'h0; +reg nmi_n_d1 = 'h0; +reg nmi_n_d2 = 'h0; +reg nmi_n_d3 = 'h0; +reg nmi_asserted = 'h0; reg irq_d1 = 'h0; reg irq_d2 = 'h0; reg irq_d3 = 'h0; reg irq_d4 = 'h0; reg irq_gated = 'h0; -reg so_n_d1 = 'h0; -reg so_n_d2 = 'h0; -reg so_n_d3 = 'h0; +reg so_n_d1 = 'h0; +reg so_n_d2 = 'h0; +reg so_n_d3 = 'h0; reg so_asserted = 'h0; reg stall_pipeline = 'h0; reg sync_int_d1 = 'h0; @@ -85,7 +106,7 @@ reg rdwr_n_int_d2 = 'h0; reg ready_int_d1 = 'h0; reg ready_int_d2 = 'h0; reg ready_int_d3 = 'h0; -reg dataout_enable = 'h0; +reg dataout_enable = 'h0; wire flag_n; wire flag_v; wire flag_b; @@ -116,9 +137,9 @@ reg [4:0] system_output = 5'h01; reg [7:0] data_out = 'h0; reg [7:0] data_in_d1 = 'h0; reg [7:0] data_in_d2 = 'h0; -reg [7:0] register_flags = 8'h00; -reg [15:0] a_out_int = 'h0; -reg [7:0] d_out_int = 'h0; +reg [7:0] register_flags = 8'h00; +reg [15:0] a_out_int = 'h0; +reg [7:0] d_out_int = 'h0; wire [15:0] adder_out; wire [16:0] carry; wire [2:0] opcode_type; @@ -143,13 +164,13 @@ wire [31:0] rom_data; // // 2Kx32 Microcode ROM // -//------------------------------------------------------------------------ +//------------------------------------------------------------------------ -ROM_2Kx32 microcode_rom +ROM_2Kx32 microcode_rom ( - .clka (CORE_CLK), - .addra (rom_address[10:0]), - .douta (rom_data) + .clka (CORE_CLK), + .addra (rom_address[10:0]), + .douta (rom_data) ); @@ -160,106 +181,106 @@ ROM_2Kx32 microcode_rom //------------------------------------------------------------------------ -assign A = a_out_int; -assign D = (dataout_enable==1'b1) ? d_out_int : 8'hZZ; +assign A = a_out_int; +assign D = (dataout_enable==1'b1) ? d_out_int : 8'hZZ; -assign DIR0 = dataout_enable; -assign DIR1 = dataout_enable; +assign DIR0 = dataout_enable; +assign DIR1 = dataout_enable; -assign CLK1 = clk1_out_int; -assign CLK2 = clk2_out_int; +assign CLK1 = clk1_out_int; +assign CLK2 = clk2_out_int; -assign so_debounce = system_output[4]; -assign nmi_debounce = system_output[3]; -//assign dataout_enable = system_output[2]; -assign sync_int = system_output[1]; -assign rdwr_n_int = system_output[0]; +assign so_debounce = system_output[4]; +assign nmi_debounce = system_output[3]; +//assign dataout_enable = system_output[2]; +assign sync_int = system_output[1]; +assign rdwr_n_int = system_output[0]; -assign SYNC = sync_int_d1; -assign RDWR_n = rdwr_n_int_d1; +assign SYNC = sync_int_d1; +assign RDWR_n = rdwr_n_int_d1; // Microcode ROM opcode decoder -assign opcode_type = rom_data[30:28]; -assign opcode_dst_sel = rom_data[27:24]; -assign opcode_op0_sel = rom_data[23:20]; -assign opcode_op1_sel = rom_data[19:16]; -assign opcode_immediate = rom_data[15:0]; +assign opcode_type = rom_data[30:28]; +assign opcode_dst_sel = rom_data[27:24]; +assign opcode_op0_sel = rom_data[23:20]; +assign opcode_op1_sel = rom_data[19:16]; +assign opcode_immediate = rom_data[15:0]; -assign opcode_jump_call = rom_data[24]; -assign opcode_jump_src = rom_data[22:20]; -assign opcode_jump_cond = rom_data[19:16]; +assign opcode_jump_call = rom_data[24]; +assign opcode_jump_src = rom_data[22:20]; +assign opcode_jump_cond = rom_data[19:16]; -assign operand0 = (opcode_op0_sel==4'h0) ? register_r0 : - (opcode_op0_sel==4'h1) ? register_r1 : - (opcode_op0_sel==4'h2) ? register_r2 : - (opcode_op0_sel==4'h3) ? register_r3 : - (opcode_op0_sel==4'h4) ? { 8'h00 , register_a } : - (opcode_op0_sel==4'h5) ? { 8'h00 , register_x } : - (opcode_op0_sel==4'h6) ? { 8'h00 , register_y } : - (opcode_op0_sel==4'h7) ? register_pc : - (opcode_op0_sel==4'h8) ? { 8'h01 , register_sp } : - (opcode_op0_sel==4'h9) ? { 8'h00 , register_flags } : - (opcode_op0_sel==4'hA) ? address_out : - (opcode_op0_sel==4'hB) ? { data_in_d2 , data_in_d2 } : - (opcode_op0_sel==4'hC) ? system_status : +assign operand0 = (opcode_op0_sel==4'h0) ? register_r0 : + (opcode_op0_sel==4'h1) ? register_r1 : + (opcode_op0_sel==4'h2) ? register_r2 : + (opcode_op0_sel==4'h3) ? register_r3 : + (opcode_op0_sel==4'h4) ? { 8'h00 , register_a } : + (opcode_op0_sel==4'h5) ? { 8'h00 , register_x } : + (opcode_op0_sel==4'h6) ? { 8'h00 , register_y } : + (opcode_op0_sel==4'h7) ? register_pc : + (opcode_op0_sel==4'h8) ? { 8'h01 , register_sp } : + (opcode_op0_sel==4'h9) ? { 8'h00 , register_flags } : + (opcode_op0_sel==4'hA) ? address_out : + (opcode_op0_sel==4'hB) ? { data_in_d2 , data_in_d2 } : + (opcode_op0_sel==4'hC) ? system_status : (opcode_op0_sel==4'hD) ? { 11'h000 , system_output[4:0] } : //(opcode_op0_sel==4'hE) ? xxxx : 16'h0 ; - -assign operand1 = (opcode_op1_sel==4'h0) ? register_r0 : - (opcode_op1_sel==4'h1) ? register_r1 : - (opcode_op1_sel==4'h2) ? register_r2 : - (opcode_op1_sel==4'h3) ? register_r3 : - (opcode_op1_sel==4'h4) ? { 8'h00 , register_a } : - (opcode_op1_sel==4'h5) ? { 8'h00 , register_x } : - (opcode_op1_sel==4'h6) ? { 8'h00 , register_y } : - (opcode_op1_sel==4'h7) ? { register_pc[7:0] , register_pc[15:8] } : - (opcode_op1_sel==4'h8) ? { 8'h01 , register_sp } : - (opcode_op1_sel==4'h9) ? { 8'h00 , register_flags } : - (opcode_op1_sel==4'hA) ? address_out : - (opcode_op1_sel==4'hB) ? { data_in_d2 , data_in_d2 } : - (opcode_op1_sel==4'hC) ? system_status : + +assign operand1 = (opcode_op1_sel==4'h0) ? register_r0 : + (opcode_op1_sel==4'h1) ? register_r1 : + (opcode_op1_sel==4'h2) ? register_r2 : + (opcode_op1_sel==4'h3) ? register_r3 : + (opcode_op1_sel==4'h4) ? { 8'h00 , register_a } : + (opcode_op1_sel==4'h5) ? { 8'h00 , register_x } : + (opcode_op1_sel==4'h6) ? { 8'h00 , register_y } : + (opcode_op1_sel==4'h7) ? { register_pc[7:0] , register_pc[15:8] } : + (opcode_op1_sel==4'h8) ? { 8'h01 , register_sp } : + (opcode_op1_sel==4'h9) ? { 8'h00 , register_flags } : + (opcode_op1_sel==4'hA) ? address_out : + (opcode_op1_sel==4'hB) ? { data_in_d2 , data_in_d2 } : + (opcode_op1_sel==4'hC) ? system_status : (opcode_op1_sel==4'hD) ? { 11'h000 , system_output[4:0] } : //(opcode_op1_sel==4'hE) ? xxxx : opcode_immediate ; - + // JUMP condition codes -assign jump_boolean = (opcode_jump_cond==4'h0) ? 1'b1 : // Unconditional jump - (opcode_jump_cond==4'h1 && alu_last_result!=16'h0) ? 1'b1 : // Jump Not Zero - (opcode_jump_cond==4'h2 && alu_last_result==16'h0) ? 1'b1 : // Jump Zero - (opcode_jump_cond==4'h3 && clk0_int_d2==1'b0) ? 1'b1 : // Jump backwards until CLK=1 - (opcode_jump_cond==4'h4 && rdwr_n_int_d1==1'b0 && clk0_int_d2==1'b1) ? 1'b1 : // Jump backwards until CLK=0 for write cycles. READY ignored - (opcode_jump_cond==4'h4 && rdwr_n_int_d1==1'b1 && (clk0_int_d2==1'b1 || ready_int_d3==1'b0)) ? 1'b1 : // Jump backwards until CLK=0 for read cycles with READY active - 1'b0 ; +assign jump_boolean = (opcode_jump_cond==4'h0) ? 1'b1 : // Unconditional jump + (opcode_jump_cond==4'h1 && alu_last_result!=16'h0) ? 1'b1 : // Jump Not Zero + (opcode_jump_cond==4'h2 && alu_last_result==16'h0) ? 1'b1 : // Jump Zero + (opcode_jump_cond==4'h3 && clk0_int_d2==1'b0) ? 1'b1 : // Jump backwards until CLK=1 + (opcode_jump_cond==4'h4 && rdwr_n_int_d1==1'b0 && clk0_int_d2==1'b1) ? 1'b1 : // Jump backwards until CLK=0 for write cycles. READY ignored + (opcode_jump_cond==4'h4 && rdwr_n_int_d1==1'b1 && (clk0_int_d2==1'b1 || ready_int_d3==1'b0)) ? 1'b1 : // Jump backwards until CLK=0 for read cycles with READY active + 1'b0 ; - -// System status -assign system_status[15:7] = 'h0; -assign system_status[6] = add_overflow8; -assign system_status[5] = irq_gated; -assign system_status[4] = so_asserted; -assign system_status[3] = nmi_asserted; -assign system_status[2] = 1'b0; -assign system_status[1] = 1'b0; -assign system_status[0] = add_carry8; + +// System status +assign system_status[15:7] = 'h0; +assign system_status[6] = add_overflow8; +assign system_status[5] = irq_gated; +assign system_status[4] = so_asserted; +assign system_status[3] = nmi_asserted; +assign system_status[2] = 1'b0; +assign system_status[1] = 1'b0; +assign system_status[0] = add_carry8; -assign flag_n = register_flags[7]; -assign flag_v = register_flags[6]; +assign flag_n = register_flags[7]; +assign flag_v = register_flags[6]; -assign flag_b = register_flags[4]; -assign flag_d = register_flags[3]; -assign flag_i = register_flags[2]; -assign flag_z = register_flags[1]; -assign flag_c = register_flags[0]; +assign flag_b = register_flags[4]; +assign flag_d = register_flags[3]; +assign flag_i = register_flags[2]; +assign flag_z = register_flags[1]; +assign flag_c = register_flags[0]; @@ -267,11 +288,11 @@ assign flag_c = register_flags[0]; // ------------------------------------------ // alu0 = NOP // alu1 = JUMP -assign alu2 = adder_out; // ADD -assign alu3 = operand0 & operand1; // AND -assign alu4 = operand0 | operand1; // OR -assign alu5 = operand0 ^ operand1; // XOR -assign alu6 = { 1'b0 , operand0[15:1] }; // SHR +assign alu2 = adder_out; // ADD +assign alu3 = operand0 & operand1; // AND +assign alu4 = operand0 | operand1; // OR +assign alu5 = operand0 ^ operand1; // XOR +assign alu6 = { 1'b0 , operand0[15:1] }; // SHR @@ -284,7 +305,7 @@ assign alu_out = (opcode_type==3'h2) ? alu2 : (opcode_type==3'h6) ? alu6 : 16'hEEEE; - + @@ -294,8 +315,8 @@ genvar i; generate for (i=0; i < 16; i=i+1) begin : GEN_ADDER - assign adder_out[i] = operand0[i] ^ operand1[i] ^ carry[i]; - assign carry[i+1] = (operand0[i] & operand1[i]) | (operand0[i] & carry[i]) | (operand1[i] & carry[i]); + assign adder_out[i] = operand0[i] ^ operand1[i] ^ carry[i]; + assign carry[i+1] = (operand0[i] & operand1[i]) | (operand0[i] & carry[i]) | (operand1[i] & carry[i]); end endgenerate @@ -310,142 +331,142 @@ endgenerate always @(posedge CORE_CLK) begin : MICROSEQUENCER - clk0_int_d1 <= CLK0; - clk0_int_d2 <= clk0_int_d1; - clk0_int_d3 <= clk0_int_d2; - clk0_int_d4 <= clk0_int_d3; - - clk1_out_int <= ~clk0_int_d3; - clk2_out_int <= clk0_int_d2; - - reset_n_d1 <= RESET_n; - reset_n_d2 <= reset_n_d1; - - ready_int_d1 <= READY; - ready_int_d2 <= ready_int_d1; - ready_int_d3 <= ready_int_d2; - - sync_int_d1 <= sync_int; - rdwr_n_int_d1 <= rdwr_n_int; - rdwr_n_int_d2 <= rdwr_n_int_d1; - - a_out_int <= address_out; - d_out_int <= data_out; - - irq_d1 <= ~IRQ_n; - data_in_d1 <= D; - if (clk0_int_d3==1'b1 && clk0_int_d2==1'b0) // Store data and sample IRQ_n on falling edge of clk - begin - data_in_d2 <= data_in_d1; - irq_d2 <= irq_d1; - irq_d3 <= irq_d2; - irq_d4 <= irq_d3; + clk0_int_d1 <= CLK0; + clk0_int_d2 <= clk0_int_d1; + clk0_int_d3 <= clk0_int_d2; + clk0_int_d4 <= clk0_int_d3; + + clk1_out_int <= ~clk0_int_d3; + clk2_out_int <= clk0_int_d2; + + reset_n_d1 <= RESET_n; + reset_n_d2 <= reset_n_d1; + + ready_int_d1 <= READY; + ready_int_d2 <= ready_int_d1; + ready_int_d3 <= ready_int_d2; + + sync_int_d1 <= sync_int; + rdwr_n_int_d1 <= rdwr_n_int; + rdwr_n_int_d2 <= rdwr_n_int_d1; + + a_out_int <= address_out; + d_out_int <= data_out; + + irq_d1 <= ~IRQ_n; + data_in_d1 <= D; + if (clk0_int_d3==1'b1 && clk0_int_d2==1'b0) // Store data and sample IRQ_n on falling edge of clk + begin + data_in_d2 <= data_in_d1; + irq_d2 <= irq_d1; + irq_d3 <= irq_d2; + irq_d4 <= irq_d3; end - irq_gated <= irq_d4 & ~flag_i; + irq_gated <= irq_d4 & ~flag_i; - if (rdwr_n_int_d1==1'b0 && clk0_int_d4==1'b1) - begin - dataout_enable <= 1'b1; - end - else if (rdwr_n_int_d2==1'b0 && rdwr_n_int_d1==1'b1) - begin - dataout_enable <= 1'b0; - end - - nmi_n_d1 <= NMI_n; - nmi_n_d2 <= nmi_n_d1; - nmi_n_d3 <= nmi_n_d2; - if (nmi_debounce==1'b1) - begin - nmi_asserted <= 1'b0; - end - else if (nmi_n_d3==1'b1 && nmi_n_d2==1'b0) // Falling edge of NMI_n - begin - nmi_asserted <= 1'b1; - end - - so_n_d1 <= SO; - so_n_d2 <=so_n_d1; - so_n_d3 <=so_n_d2; - if (so_debounce==1'b1) - begin - so_asserted <= 1'b0; - end - else if (so_n_d3==1'b1 && so_n_d2==1'b0) // Falling edge of SO - begin - so_asserted <= 1'b1; - end - - - - // Generate and store flags for addition - if (stall_pipeline==1'b0 && opcode_type==3'h2) - begin - add_carry8 <= carry[8]; - add_overflow8 <= carry[8] ^ carry[7]; + if (rdwr_n_int_d1==1'b0 && clk0_int_d4==1'b1) + begin + dataout_enable <= 1'b1; + end + else if (rdwr_n_int_d2==1'b0 && rdwr_n_int_d1==1'b1) + begin + dataout_enable <= 1'b0; + end + + nmi_n_d1 <= NMI_n; + nmi_n_d2 <= nmi_n_d1; + nmi_n_d3 <= nmi_n_d2; + if (nmi_debounce==1'b1) + begin + nmi_asserted <= 1'b0; + end + else if (nmi_n_d3==1'b1 && nmi_n_d2==1'b0) // Falling edge of NMI_n + begin + nmi_asserted <= 1'b1; end - - // Register writeback + so_n_d1 <= SO; + so_n_d2 <=so_n_d1; + so_n_d3 <=so_n_d2; + if (so_debounce==1'b1) + begin + so_asserted <= 1'b0; + end + else if (so_n_d3==1'b1 && so_n_d2==1'b0) // Falling edge of SO + begin + so_asserted <= 1'b1; + end + + + + // Generate and store flags for addition + if (stall_pipeline==1'b0 && opcode_type==3'h2) + begin + add_carry8 <= carry[8]; + add_overflow8 <= carry[8] ^ carry[7]; + end + + + // Register writeback if (stall_pipeline==1'b0 && opcode_type!=3'h0 && opcode_type!=3'h1) - begin - alu_last_result <= alu_out[15:0]; - case (opcode_dst_sel) // synthesis parallel_case - 4'h0 : register_r0 <= alu_out[15:0]; - 4'h1 : register_r1 <= alu_out[15:0]; - 4'h2 : register_r2 <= alu_out[15:0]; - 4'h3 : register_r3 <= alu_out[15:0]; - 4'h4 : register_a <= alu_out[7:0]; - 4'h5 : register_x <= alu_out[7:0]; - 4'h6 : register_y <= alu_out[7:0]; - 4'h7 : register_pc <= alu_out[15:0]; - 4'h8 : register_sp <= alu_out[7:0]; - 4'h9 : register_flags <= { alu_out[7:6] , 2'b11 , alu_out[3:0] }; - 4'hA : address_out <= alu_out[15:0]; - 4'hB : data_out <= alu_out[7:0]; - //4'hC : - 4'hD : system_output <= alu_out[4:0]; - //4'hE : - //4'hF : - default : ; - endcase + begin + alu_last_result <= alu_out[15:0]; + case (opcode_dst_sel) // synthesis parallel_case + 4'h0 : register_r0 <= alu_out[15:0]; + 4'h1 : register_r1 <= alu_out[15:0]; + 4'h2 : register_r2 <= alu_out[15:0]; + 4'h3 : register_r3 <= alu_out[15:0]; + 4'h4 : register_a <= alu_out[7:0]; + 4'h5 : register_x <= alu_out[7:0]; + 4'h6 : register_y <= alu_out[7:0]; + 4'h7 : register_pc <= alu_out[15:0]; + 4'h8 : register_sp <= alu_out[7:0]; + 4'h9 : register_flags <= { alu_out[7:6] , 2'b11 , alu_out[3:0] }; + 4'hA : address_out <= alu_out[15:0]; + 4'hB : data_out <= alu_out[7:0]; + //4'hC : + 4'hD : system_output <= alu_out[4:0]; + //4'hE : + //4'hF : + default : ; + endcase end - - if (reset_n_d2==1'b0) + + if (reset_n_d2==1'b0) begin rom_address <= 11'h7D0; // Microcode starts here after reset - stall_pipeline <= 'h0; + stall_pipeline <= 'h0; end - // JUMP Opcode + // JUMP Opcode else if (stall_pipeline==1'b0 && opcode_type==3'h1 && jump_boolean==1'b1) - begin - stall_pipeline <= 1'b1; - - // For subroutine CALLs, store next opcode address - if (opcode_jump_call==1'b1) - begin - calling_address[21:0] <= {calling_address[10:0] , rom_address[10:0] }; // Two deep stack for calling addresses - end + begin + stall_pipeline <= 1'b1; + + // For subroutine CALLs, store next opcode address + if (opcode_jump_call==1'b1) + begin + calling_address[21:0] <= {calling_address[10:0] , rom_address[10:0] }; // Two deep stack for calling addresses + end - case (opcode_jump_src) // synthesis parallel_case - 3'h0 : rom_address <= opcode_immediate[10:0]; - 3'h1 : rom_address <= { 3'b000 , data_in_d2[7:0] }; // Opcode Jump Table - 3'h2 : begin - rom_address <= calling_address[10:0]; - calling_address[10:0] <= calling_address[21:11]; - end - 3'h3 : rom_address <= rom_address - 1'b1; - default : ; - endcase - end - + case (opcode_jump_src) // synthesis parallel_case + 3'h0 : rom_address <= opcode_immediate[10:0]; + 3'h1 : rom_address <= { 3'b000 , data_in_d2[7:0] }; // Opcode Jump Table + 3'h2 : begin + rom_address <= calling_address[10:0]; + calling_address[10:0] <= calling_address[21:11]; + end + 3'h3 : rom_address <= rom_address - 1'b1; + default : ; + endcase + end + else begin - stall_pipeline <= 1'b0; // Debounce the pipeline stall - rom_address <= rom_address + 1'b1; + stall_pipeline <= 1'b0; // Debounce the pipeline stall + rom_address <= rom_address + 1'b1; end end // MCL65 Microsequencer diff --git a/MCL65/microcode_rom.hex b/MCL65/Microcode_MCL65.txt similarity index 98% rename from MCL65/microcode_rom.hex rename to MCL65/Microcode_MCL65.txt index 30ee0d6..29b5e2b 100644 --- a/MCL65/microcode_rom.hex +++ b/MCL65/Microcode_MCL65.txt @@ -1,8 +1,50 @@ // -// Microcode for the MCL65 +// +// File Name : Microcode_MCL65.txt +// Used on : MCL65 +// Author : Ted Fried, MicroCore Labs +// Creation : 1/25/2020 +// Code Type : Microcode +// +// Description: +// ============ +// +// Microcode for the MCL65 // //------------------------------------------------------------------------ +// +// Modification History: +// ===================== +// +// Revision 1.0 1/25/2020 +// Initial revision +// +// +//------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried // +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ + +// Microcode and microsequencer notes: // // System status register // assign system_status[15:7] = 'h0; diff --git a/MCL86/Core/mdio.vec b/MCL86/Core/Microcode_MCL86.txt similarity index 98% rename from MCL86/Core/mdio.vec rename to MCL86/Core/Microcode_MCL86.txt index 38673de..9ec43f0 100644 --- a/MCL86/Core/mdio.vec +++ b/MCL86/Core/Microcode_MCL86.txt @@ -1,37 +1,69 @@ -# -# Microcode for the MCL86 -# -# ------------------------------------------------------------------------ -# -# Copyright (C) 2019 by Ted Fried info@MicroCoreLabs.com -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, provided -# that the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting documentation. -# This software is provided "as is" without express or implied warranty. -# -# ------------------------------------------------------------------------ -# +// +// +// File Name : Microcode_MCL86.txt +// Used on : MCL86 +// Author : Ted Fried, MicroCore Labs +// Creation : 1/25/2020 +// Code Type : Microcode +// +// Description: +// ============ +// +// Microcode for the MCL86 +// +//------------------------------------------------------------------------ +// +// Modification History: +// ===================== +// +// Revision 1.0 1/25/2020 +// Initial revision +// +// +//------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ +// Microcode and microsequencer notes: +// # # // Consolidated system signals # assign system_signals[15] # assign system_signals[14] -# assign system_signals[13] = eu_add_carry8; -# assign system_signals[12] = clock_cycle_counter_zero; -# assign system_signals[11] = eu_add_overflow16; +# assign system_signals[13] = eu_add_carry8; +# assign system_signals[12] = clock_cycle_counter_zero; +# assign system_signals[11] = eu_add_overflow16; # assign system_signals[10] -# assign system_signals[9] = eu_add_overflow8; -# assign system_signals[8] = eu_flag_t_asserted; -# assign system_signals[7] = ~pfq_empty; -# assign system_signals[6] = biu_done_caught; -# assign system_signals[5] = test_n_int; -# assign system_signals[4] = eu_add_aux_carry; -# assign system_signals[3] = nmi_caught; -# assign system_signals[2] = eu_parity; -# assign system_signals[1] = int_asserted; -# assign system_signals[0] = eu_add_carry16; +# assign system_signals[9] = eu_add_overflow8; +# assign system_signals[8] = eu_flag_t_asserted; +# assign system_signals[7] = ~pfq_empty; +# assign system_signals[6] = biu_done_caught; +# assign system_signals[5] = test_n_int; +# assign system_signals[4] = eu_add_aux_carry; +# assign system_signals[3] = nmi_caught; +# assign system_signals[2] = eu_parity; +# assign system_signals[1] = int_asserted; +# assign system_signals[0] = eu_add_carry16; # # # assign eu_prefix_repnz = eu_flags[15]; @@ -46,9 +78,9 @@ # assign eu_flag_z = eu_flags[6]; # assign eu_tf_debounce = eu_flags[5]; # assign eu_flag_a = eu_flags[4]; -# assign eu_flag_temp = eu_flags[3]; +# assign eu_flag_temp = eu_flags[3]; # assign eu_flag_p = eu_flags[2]; -# assign eu_flag_temp = eu_flags[1]; +# assign eu_flag_temp = eu_flags[1]; # assign eu_flag_c = eu_flags[0]; # # @@ -58,7 +90,7 @@ # // eu_biu_strobe[1:0] are available for only one clock cycle and cause BIU to take immediate action. # // eu_biu_req stays asserted until the BIU is available to service the request. # // -# = eu_biu_command[15]; +# = eu_biu_command[15]; # eu_segment_override = eu_biu_command[14]; # eu_biu_strobe[1:0] = eu_biu_command[13:12]; // 01=opcode fetch 10=clock load 11=load biu register(eu_biu_req_code has the register#) # eu_biu_segment[1:0] = eu_biu_command[11:10]; @@ -66,29 +98,29 @@ # eu_biu_req_code = eu_biu_command[8:4]; # eu_qs_out[1:0] = eu_biu_command[3:2]; // Updated for every opcode fetch strobe using biu_strobe and Jump request using eu_biu_rq # eu_segment_override_value[1:0] = eu_biu_command[1:0]; -# +# # # EU Registers # -------------- # -# Destination Operand0 Operand1 +# Destination Operand0 Operand1 # ----------------------------------------------------------------------------------------------- -# 0 AX 0 AX 0 ES -# 1 BX 1 BX 1 SS -# 2 CX 2 CX 2 CS -# 3 DX 3 DX 3 DS -# 4 SP 4 SP 4 { 8'h00 , pfq_top_byte } -# 5 BP 5 BP 5 EA_RM from BIU -# 6 SI 6 SI 6 EA_REG from BIU -# 7 DI 7 DI 7 BIU Return Data -# 8 Flags 8 Flags 8 Prefetch Queue Address (Current IP) -# 9 r0 9 r0 9 r0 -# A r1 A r1 A r1 -# B r2 B r2 B r2 -# C r3 C r3 C r3 -# D BIU Command D BIU Command D ALU Last Result -# E Dummy Reg E System Signals E System Signals -# F BIU Dataout F 16'h0000 F Opcode Immediate[15:0] +# 0 AX 0 AX 0 ES +# 1 BX 1 BX 1 SS +# 2 CX 2 CX 2 CS +# 3 DX 3 DX 3 DS +# 4 SP 4 SP 4 { 8'h00 , pfq_top_byte } +# 5 BP 5 BP 5 EA_RM from BIU +# 6 SI 6 SI 6 EA_REG from BIU +# 7 DI 7 DI 7 BIU Return Data +# 8 Flags 8 Flags 8 Prefetch Queue Address (Current IP) +# 9 r0 9 r0 9 r0 +# A r1 A r1 A r1 +# B r2 B r2 B r2 +# C r3 C r3 C r3 +# D BIU Command D BIU Command D ALU Last Result +# E Dummy Reg E System Signals E System Signals +# F BIU Dataout F 16'h0000 F Opcode Immediate[15:0] # # # EU Opcodes @@ -97,19 +129,19 @@ # ---------------- # Bits[31:28] : 0x1 # Bits[27:24] : CALL 1=Store next IP address -# Bits[22:20] : Jump Source: -# 0x0=Immediate[12:0] -# 0x1={immediate[4:0]&pfq_top_byte} -# 0x2={immediate[4:0]&pfq_top_byte[7:6]&pfq_top_byte[2:0]&000} -# 0x3=Return to CALL stored IP address -# 0x4={immediate[8:0], eu_biu_dataout[3:0] , 1'b0 } // For register fetch -# 0x5={immediate[7:0], eu_biu_dataout[3:0] , 2'b00 } // For register writeback -# 0x6={eu_opcode_immediate[12:3], eu_biu_dataout[5:3]} // For opcode group decoding +# Bits[22:20] : Jump Source: +# 0x0=Immediate[12:0] +# 0x1={immediate[4:0]&pfq_top_byte} +# 0x2={immediate[4:0]&pfq_top_byte[7:6]&pfq_top_byte[2:0]&000} +# 0x3=Return to CALL stored IP address +# 0x4={immediate[8:0], eu_biu_dataout[3:0] , 1'b0 } // For register fetch +# 0x5={immediate[7:0], eu_biu_dataout[3:0] , 2'b00 } // For register writeback +# 0x6={eu_opcode_immediate[12:3], eu_biu_dataout[5:3]} // For opcode group decoding # -# Bits[19:16] : Jump Condition: -# 0x0=Unconditional -# 0x1=Last_ALU_Result!=0 -# 0x2=Last_ALU_Result==0 +# Bits[19:16] : Jump Condition: +# 0x0=Unconditional +# 0x1=Last_ALU_Result!=0 +# 0x2=Last_ALU_Result==0 # Bits[12:0] : Immediate[12:0] # # 0x2 - ADD @@ -141,14 +173,14 @@ # (eu_biu_req_code == h14 ===> Memory Word Write - To Stack Segment # (eu_biu_req_code == h16 ===> Interrupt ACK Cycle # (eu_biu_req_code == h18 ===> HALT State -# (eu_biu_req_code == h19 ===> Jump Instruction +# (eu_biu_req_code == h19 ===> Jump Instruction # (eu_biu_req_code == h1A ===> IO Word Read -# (eu_biu_req_code == h1C ===> IO Word Write +# (eu_biu_req_code == h1C ===> IO Word Write # RESET State # # -# -# +# +# # # Stop CPU p 00 00000 00010 0001 diff --git a/MCL86/Core/biu_max.v b/MCL86/Core/biu_max.v index e10e9e4..f164f57 100644 --- a/MCL86/Core/biu_max.v +++ b/MCL86/Core/biu_max.v @@ -2,7 +2,7 @@ // // File Name : biu_max.v // Used on : -// Author : MicroCore Labs +// Author : Ted Fried, MicroCore Labs // Creation : 10/8/2015 // Code Type : Synthesizable // @@ -21,56 +21,78 @@ // // //------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ module biu_max ( - input CORE_CLK_INT, // Core Clock + input CORE_CLK_INT, // Core Clock - - input CLK, // 8088 Pins - input RESET_INT, - input READY_IN, - input NMI, - input INTR, - output reg LOCK_n, - output reg AD_OE, - output reg [19:0] AD_OUT, - input [7:0] AD_IN, - output reg S6_3_MUX, - output reg [2:0] S2_S0_OUT, + + input CLK, // 8088 Pins + input RESET_INT, + input READY_IN, + input NMI, + input INTR, + output reg LOCK_n, + output reg AD_OE, + output reg [19:0] AD_OUT, + input [7:0] AD_IN, + output reg S6_3_MUX, + output reg [2:0] S2_S0_OUT, - - input [15:0] EU_BIU_COMMAND, // EU to BIU Signals - input [15:0] EU_BIU_DATAOUT, - input [15:0] EU_REGISTER_R3, - input EU_PREFIX_LOCK, - - - output BIU_DONE, // BIU to EU Signals - output BIU_CLK_COUNTER_ZERO, - output [1:0] BIU_SEGMENT, - output BIU_NMI_CAUGHT, - input BIU_NMI_DEBOUNCE, - output reg BIU_INTR, + + input [15:0] EU_BIU_COMMAND, // EU to BIU Signals + input [15:0] EU_BIU_DATAOUT, + input [15:0] EU_REGISTER_R3, + input EU_PREFIX_LOCK, + + + output BIU_DONE, // BIU to EU Signals + output BIU_CLK_COUNTER_ZERO, + output [1:0] BIU_SEGMENT, + output BIU_NMI_CAUGHT, + input BIU_NMI_DEBOUNCE, + output reg BIU_INTR, - output [7:0] PFQ_TOP_BYTE, - output PFQ_EMPTY, - output[15:0] PFQ_ADDR_OUT, + output [7:0] PFQ_TOP_BYTE, + output PFQ_EMPTY, + output[15:0] PFQ_ADDR_OUT, - output [15:0] BIU_REGISTER_ES, - output [15:0] BIU_REGISTER_SS, - output [15:0] BIU_REGISTER_CS, - output [15:0] BIU_REGISTER_DS, - output [15:0] BIU_REGISTER_RM, - output [15:0] BIU_REGISTER_REG, - output [15:0] BIU_RETURN_DATA - + output [15:0] BIU_REGISTER_ES, + output [15:0] BIU_REGISTER_SS, + output [15:0] BIU_REGISTER_CS, + output [15:0] BIU_REGISTER_DS, + output [15:0] BIU_REGISTER_RM, + output [15:0] BIU_REGISTER_REG, + output [15:0] BIU_RETURN_DATA + ); //------------------------------------------------------------------------ - + // Internal Signals @@ -137,8 +159,8 @@ reg [7:0] pfq_top_byte_int_d1; reg [15:0] pfq_addr_out_d1; reg [2:0] s_bits; reg [2:0] s2_s0_out_int; -wire [15:0] biu_muxed_segment; -wire [1:0] biu_segment; +wire [15:0] biu_muxed_segment; +wire [1:0] biu_segment; wire [1:0] eu_biu_strobe; wire [1:0] eu_biu_segment; wire [4:0] eu_biu_req_code; @@ -158,7 +180,7 @@ wire [7:0] pfq_top_byte_int; assign BIU_DONE = biu_done_int; assign PFQ_EMPTY = pfq_empty; assign PFQ_ADDR_OUT = pfq_addr_out_d1; -assign BIU_SEGMENT = biu_segment; +assign BIU_SEGMENT = biu_segment; assign BIU_REGISTER_ES = biu_register_es_d2; assign BIU_REGISTER_SS = biu_register_ss_d2; assign BIU_REGISTER_CS = biu_register_cs_d2; @@ -166,7 +188,7 @@ assign BIU_REGISTER_DS = biu_register_ds_d2; assign BIU_REGISTER_RM = biu_register_rm_d2; assign BIU_REGISTER_REG = biu_register_reg_d2; assign BIU_RETURN_DATA = biu_return_data_int_d2; -assign BIU_NMI_CAUGHT = nmi_caught; +assign BIU_NMI_CAUGHT = nmi_caught; @@ -174,7 +196,7 @@ assign BIU_NMI_CAUGHT = nmi_caught; // eu_biu_strobe[1:0] are available for only one clock cycle and cause BIU to take immediate action. // eu_biu_req stays asserted until the BIU is available to service the request. // -assign eu_prefix_seg = EU_BIU_COMMAND[14]; +assign eu_prefix_seg = EU_BIU_COMMAND[14]; assign eu_biu_strobe[1:0] = EU_BIU_COMMAND[13:12]; // 01=opcode fetch 10=clock load 11=load segment register(eu_biu_req_code has the regiter#) assign eu_biu_segment[1:0] = EU_BIU_COMMAND[11:10]; assign eu_biu_req = EU_BIU_COMMAND[9]; @@ -187,18 +209,18 @@ assign eu_segment_override_value[1:0] = EU_BIU_COMMAND[1:0]; // Select either the current EU Segment or the Segment Override value. assign biu_segment = (eu_prefix_seg==1'b1) ? eu_segment_override_value : eu_biu_segment; - + assign biu_muxed_segment = (biu_segment==2'b00) ? biu_register_es : (biu_segment==2'b01) ? biu_register_ss : (biu_segment==2'b10) ? biu_register_cs : biu_register_ds ; - + // Steer the Prefetch Queue to the EU assign pfq_top_byte_int = (pfq_addr_out[1:0]==2'b00) ? pfq_entry0 : (pfq_addr_out[1:0]==2'b01) ? pfq_entry1 : (pfq_addr_out[1:0]==2'b10) ? pfq_entry2 : - pfq_entry3 ; + pfq_entry3 ; assign PFQ_TOP_BYTE = pfq_top_byte_int_d1; @@ -211,7 +233,7 @@ assign pfq_empty = ( (pfq_addr_in[2]==pfq_addr_out[2]) && (pfq_addr_in[1:0]==pfq assign BIU_CLK_COUNTER_ZERO = (clock_cycle_counter==13'h0000) ? 1'b1 : 1'b0; - + //------------------------------------------------------------------------ // // BIU State Machine @@ -228,10 +250,10 @@ begin : BIU_STATE_MACHINE clk_d2 <= 'h0; clk_d3 <= 'h0; clk_d4 <= 'h0; - nmi_d1 <= 'h0; + nmi_d1 <= 'h0; nmi_d2 <= 'h0; nmi_d3 <= 'h0; - nmi_caught <= 'h0; + nmi_caught <= 'h0; eu_register_r3_d <= 'h0; eu_biu_req_caught <= 'h0; biu_register_cs <= 16'hFFFF; @@ -253,27 +275,27 @@ begin : BIU_STATE_MACHINE pfq_addr_in <= 'h0; biu_lock_n_int <= 1'b1; S6_3_MUX <= 'h0; - AD_OE <= 'h0; - biu_return_data_int <= 'h0; - biu_done_int <= 'h0; - ready_d1 <= 'h0; + AD_OE <= 'h0; + biu_return_data_int <= 'h0; + biu_done_int <= 'h0; + ready_d1 <= 'h0; ready_d2 <= 'h0; ready_d3 <= 'h0; - eu_biu_req_d1 <= 'h0; - latched_data_in <= 'h0; - addr_out_temp <= 'h0; - s_bits <= 3'b111; - AD_OUT <= 'h0; - word_cycle <= 1'b0; - byte_num <= 1'b0; - ad_in_int <= 'h0; - BIU_INTR <= 'h0; - eu_prefix_lock_d1 <= 'h0; + eu_biu_req_d1 <= 'h0; + latched_data_in <= 'h0; + addr_out_temp <= 'h0; + s_bits <= 3'b111; + AD_OUT <= 'h0; + word_cycle <= 1'b0; + byte_num <= 1'b0; + ad_in_int <= 'h0; + BIU_INTR <= 'h0; + eu_prefix_lock_d1 <= 'h0; eu_prefix_lock_d2 <= 'h0; - LOCK_n <= 1'b1; - intr_d1 <= 'h0; - intr_d2 <= 'h0; - intr_d3 <= 'h0; + LOCK_n <= 1'b1; + intr_d1 <= 'h0; + intr_d2 <= 'h0; + intr_d3 <= 'h0; end else @@ -282,159 +304,159 @@ else // Register pipelining clk_d1 <= CLK; - clk_d2 <= clk_d1; - clk_d3 <= clk_d2; - clk_d4 <= clk_d3; + clk_d2 <= clk_d1; + clk_d3 <= clk_d2; + clk_d4 <= clk_d3; + + ready_d1 <= READY_IN; + ready_d2 <= ready_d1; + ready_d3 <= ready_d2; - ready_d1 <= READY_IN; - ready_d2 <= ready_d1; - ready_d3 <= ready_d2; - nmi_d1 <= NMI; - nmi_d2 <= nmi_d1; - nmi_d3 <= nmi_d2; - - intr_d1 <= INTR; - intr_d2 <= intr_d1; - intr_d3 <= intr_d2; - - - // These signals may be pipelined from zero to two clocks. - // They are currently pipelined by two clocks. - biu_register_es_d1 <= biu_register_es; - biu_register_ss_d1 <= biu_register_ss; - biu_register_cs_d1 <= biu_register_cs; + nmi_d2 <= nmi_d1; + nmi_d3 <= nmi_d2; + + intr_d1 <= INTR; + intr_d2 <= intr_d1; + intr_d3 <= intr_d2; + + + // These signals may be pipelined from zero to two clocks. + // They are currently pipelined by two clocks. + biu_register_es_d1 <= biu_register_es; + biu_register_ss_d1 <= biu_register_ss; + biu_register_cs_d1 <= biu_register_cs; biu_register_ds_d1 <= biu_register_ds; biu_register_rm_d1 <= biu_register_rm; biu_register_reg_d1 <= biu_register_reg; biu_register_es_d2 <= biu_register_es_d1; - biu_register_ss_d2 <= biu_register_ss_d1; - biu_register_cs_d2 <= biu_register_cs_d1; + biu_register_ss_d2 <= biu_register_ss_d1; + biu_register_cs_d2 <= biu_register_cs_d1; biu_register_ds_d2 <= biu_register_ds_d1; biu_register_rm_d2 <= biu_register_rm_d1; biu_register_reg_d2 <= biu_register_reg_d1; - + - // These signals may be pipelined from zero to one clock. - // They are currently pipelined by one clock. - pfq_top_byte_int_d1 <= pfq_top_byte_int; + // These signals may be pipelined from zero to one clock. + // They are currently pipelined by one clock. + pfq_top_byte_int_d1 <= pfq_top_byte_int; pfq_addr_out_d1 <= pfq_addr_out; - - // This signal may be pipelined any number of clocks as - // long as is stable before BIU_DONE is asserted. + + // This signal may be pipelined any number of clocks as + // long as is stable before BIU_DONE is asserted. biu_return_data_int_d1 <= biu_return_data_int; biu_return_data_int_d2 <= biu_return_data_int_d1; - - - // NMI caught on it's rising edge - if (nmi_d3==1'b0 && nmi_d2==1'b0 && nmi_d1==1'b1) - begin - nmi_caught <= 1'b1; - end - else if (BIU_NMI_DEBOUNCE==1'b1) - begin - nmi_caught <= 1'b0; - end - - // INTR sampled on the rising edge of the CLK - if (clk_d4==1'b0 && clk_d3==1'b0 && clk_d2==1'b1) - begin - BIU_INTR <= intr_d3; + + + // NMI caught on it's rising edge + if (nmi_d3==1'b0 && nmi_d2==1'b0 && nmi_d1==1'b1) + begin + nmi_caught <= 1'b1; end - - eu_prefix_lock_d1 <= EU_PREFIX_LOCK; - eu_prefix_lock_d2 <= eu_prefix_lock_d1; - - // Drive LOCK_n out of the chip only on the falling edge of the 8088 CLK. - // LOCK_n can be driven by either the BIU during an INTA cycle or by the - // LOCK prefix opcode generated by the EU. - if (clk_d3==1'b1 && clk_d2==1'b1 && clk_d1==1'b0) - begin - LOCK_n <= ~eu_prefix_lock_d2 && biu_lock_n_int; - end - - - - // Register pipelining in and out of the BIU. - eu_register_r3_d <= EU_REGISTER_R3; - ad_in_int <= AD_IN; - S2_S0_OUT <= s2_s0_out_int; - - - - // Capture a bus request from the EU - eu_biu_req_d1 <= eu_biu_req; - if (eu_biu_req_d1==1'b0 && eu_biu_req==1'b1) - begin - eu_biu_req_caught <= 1'b1; + else if (BIU_NMI_DEBOUNCE==1'b1) + begin + nmi_caught <= 1'b0; end - else if (biu_done_int==1'b1) - begin - eu_biu_req_caught <= 1'b0; - end - - - // Strobe from EU to update the segment and addressing registers - if (eu_biu_strobe==2'b11) - begin - case (eu_biu_req_code[2:0]) // synthesis parallel_case - 3'h0 : biu_register_es <= EU_BIU_DATAOUT[15:0]; - 3'h1 : biu_register_ss <= EU_BIU_DATAOUT[15:0]; - 3'h2 : biu_register_cs <= EU_BIU_DATAOUT[15:0]; - 3'h3 : biu_register_ds <= EU_BIU_DATAOUT[15:0]; - 3'h4 : biu_register_rm <= EU_BIU_DATAOUT[15:0]; - 3'h5 : biu_register_reg <= EU_BIU_DATAOUT[15:0]; - default : ; - endcase - end + // INTR sampled on the rising edge of the CLK + if (clk_d4==1'b0 && clk_d3==1'b0 && clk_d2==1'b1) + begin + BIU_INTR <= intr_d3; + end + + eu_prefix_lock_d1 <= EU_PREFIX_LOCK; + eu_prefix_lock_d2 <= eu_prefix_lock_d1; + + // Drive LOCK_n out of the chip only on the falling edge of the 8088 CLK. + // LOCK_n can be driven by either the BIU during an INTA cycle or by the + // LOCK prefix opcode generated by the EU. + if (clk_d3==1'b1 && clk_d2==1'b1 && clk_d1==1'b0) + begin + LOCK_n <= ~eu_prefix_lock_d2 && biu_lock_n_int; + end - + + + // Register pipelining in and out of the BIU. + eu_register_r3_d <= EU_REGISTER_R3; + ad_in_int <= AD_IN; + S2_S0_OUT <= s2_s0_out_int; + + + + // Capture a bus request from the EU + eu_biu_req_d1 <= eu_biu_req; + if (eu_biu_req_d1==1'b0 && eu_biu_req==1'b1) + begin + eu_biu_req_caught <= 1'b1; + end + else if (biu_done_int==1'b1) + begin + eu_biu_req_caught <= 1'b0; + end + + + + // Strobe from EU to update the segment and addressing registers + if (eu_biu_strobe==2'b11) + begin + case (eu_biu_req_code[2:0]) // synthesis parallel_case + 3'h0 : biu_register_es <= EU_BIU_DATAOUT[15:0]; + 3'h1 : biu_register_ss <= EU_BIU_DATAOUT[15:0]; + 3'h2 : biu_register_cs <= EU_BIU_DATAOUT[15:0]; + 3'h3 : biu_register_ds <= EU_BIU_DATAOUT[15:0]; + 3'h4 : biu_register_rm <= EU_BIU_DATAOUT[15:0]; + 3'h5 : biu_register_reg <= EU_BIU_DATAOUT[15:0]; + default : ; + endcase + end + + // Strobe from EU to set the 8088 clock cycle counter if (eu_biu_strobe==2'b10) begin - clock_cycle_counter <= EU_BIU_DATAOUT[12:0]; - end + clock_cycle_counter <= EU_BIU_DATAOUT[12:0]; + end else if (clock_cycle_counter!=13'h0000) begin - clock_cycle_counter <= clock_cycle_counter - 1; - end - + clock_cycle_counter <= clock_cycle_counter - 1; + end + // Prefetch Queue - // -------------- - // Increment the output address of the queue upon EU fetch request strobe. - // Update/flush the Prefetch Queue when the EU asserts the Jump request. - // Increment the input address during prefetch queue fetches. + // -------------- + // Increment the output address of the queue upon EU fetch request strobe. + // Update/flush the Prefetch Queue when the EU asserts the Jump request. + // Increment the input address during prefetch queue fetches. //--------------------------------------------------------------------------------- if (eu_biu_req_caught==1'b1 && eu_biu_req_code==5'h19) begin pfq_addr_out <= eu_register_r3_d; // Update the prefetch queue to the new address. end - else if (eu_biu_strobe==2'b01 && pfq_empty==1'b0) + else if (eu_biu_strobe==2'b01 && pfq_empty==1'b0) begin - pfq_addr_out <= pfq_addr_out + 1; // Increment the current IP - Instruction Pointer - end - - + pfq_addr_out <= pfq_addr_out + 1; // Increment the current IP - Instruction Pointer + end + + if (eu_biu_req_caught==1'b1 && eu_biu_req_code==5'h19) begin pfq_addr_in <= eu_register_r3_d; // Update the prefetch queue to the new address. end - else if (pfq_write==1'b1) + else if (pfq_write==1'b1) begin - pfq_addr_in <= pfq_addr_in + 1; - end - - - - // Write to the selected prefetch queue entry. - if (pfq_write==1'b1) + pfq_addr_in <= pfq_addr_in + 1; + end + + + + // Write to the selected prefetch queue entry. + if (pfq_write==1'b1) begin - case (pfq_addr_in[1:0]) // synthesis parallel_case + case (pfq_addr_in[1:0]) // synthesis parallel_case 2'b00 : pfq_entry0 <= latched_data_in[7:0]; 2'b01 : pfq_entry1 <= latched_data_in[7:0]; 2'b10 : pfq_entry2 <= latched_data_in[7:0]; @@ -442,304 +464,304 @@ else default : ; endcase end - + - - - - // 8088 BIU State Machine - // ---------------------- - - biu_state <= biu_state + 1'b1; - case (biu_state) // synthesis parallel_case - - 8'h00 : begin - // Debounce signals - pfq_write <= 1'b0; - biu_lock_n_int <= 1'b1; - S6_3_MUX <= 1'b0; - byte_num <= 1'b0; - word_cycle <= 1'b0; - + + + + // 8088 BIU State Machine + // ---------------------- + + biu_state <= biu_state + 1'b1; + case (biu_state) // synthesis parallel_case + + 8'h00 : begin + // Debounce signals + pfq_write <= 1'b0; + biu_lock_n_int <= 1'b1; + S6_3_MUX <= 1'b0; + byte_num <= 1'b0; + word_cycle <= 1'b0; + - if (eu_biu_req_caught==1'b1) - begin - - case (eu_biu_req_code) // synthesis parallel_case - - // Interrupt ACK Cycle - 8'h16 : begin - addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; - //AD_OE <= 'h0; - word_cycle <= 1'b1; - s_bits <= 3'b000; - biu_state <= 8'h01; - end - - // IO Byte Read - 8'h08 : begin - addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; - s_bits <= 3'b001; - biu_state <= 8'h01; - end - - // IO Word Read - 8'h1A : begin - addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; - word_cycle <= 1'b1; - s_bits <= 3'b001; - biu_state <= 8'h01; - end - - // IO Byte Write - 8'h0A : begin - addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; - s_bits <= 3'b010; - biu_state <= 8'h01; - end - - // IO Word Write - 8'h1C : begin - addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; - word_cycle <= 1'b1; - s_bits <= 3'b010; - biu_state <= 8'h01; - end - - // Halt Request - 8'h18 : begin - addr_out_temp <= { biu_register_cs[15:0] , 4'h0 } + pfq_addr_out[15:0] ; - s_bits <= 3'b011; - biu_state <= 8'h01; - end - - // Memory Byte Read - 8'h0C : begin - addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; - s_bits <= 3'b101; - biu_state <= 8'h01; - end - - // Memory Word Read - 8'h10 : begin - addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; - word_cycle <= 1'b1; - s_bits <= 3'b101; - biu_state <= 8'h01; - end - - // Memory Word Read from Stack Segment - 8'h11 : begin - addr_out_temp <= { biu_register_ss[15:0] , 4'h0 } + eu_register_r3_d[15:0]; - word_cycle <= 1'b1; - s_bits <= 3'b101; - biu_state <= 8'h01; - end - - // Memory Word Read from Segment 0x0000 - Used for interrupt vector fetches - 8'h12 : begin - addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; - word_cycle <= 1'b1; - s_bits <= 3'b101; - biu_state <= 8'h01; - end - - // Memory Byte Write - 8'h0E : begin - addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; - s_bits <= 3'b110; - biu_state <= 8'h01; - end - - // Memory Word Write - 8'h13 : begin - addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; - word_cycle <= 1'b1; - s_bits <= 3'b110; - biu_state <= 8'h01; - end - - // Memory Word Write to Stack Segment - 8'h14 : begin - addr_out_temp <= { biu_register_ss[15:0] , 4'h0 } + eu_register_r3_d[15:0]; - word_cycle <= 1'b1; - s_bits <= 3'b110; - biu_state <= 8'h01; - end - - // Jump Request - 8'h19 : begin - biu_done_int <= 1'b1; - biu_state <= 8'h46; - end - - default : ; - endcase - end - - - else if (pfq_full==1'b0) - begin - addr_out_temp <= { biu_register_cs[15:0] , 4'h0 } + pfq_addr_in[15:0] ; - s_bits <= 3'b100; - biu_state <= 8'h01; - end - - else - begin - biu_state <= 8'h00; - end - - end + if (eu_biu_req_caught==1'b1) + begin + + case (eu_biu_req_code) // synthesis parallel_case + + // Interrupt ACK Cycle + 8'h16 : begin + addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; + //AD_OE <= 'h0; + word_cycle <= 1'b1; + s_bits <= 3'b000; + biu_state <= 8'h01; + end + + // IO Byte Read + 8'h08 : begin + addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; + s_bits <= 3'b001; + biu_state <= 8'h01; + end + + // IO Word Read + 8'h1A : begin + addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; + word_cycle <= 1'b1; + s_bits <= 3'b001; + biu_state <= 8'h01; + end + + // IO Byte Write + 8'h0A : begin + addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; + s_bits <= 3'b010; + biu_state <= 8'h01; + end + + // IO Word Write + 8'h1C : begin + addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; + word_cycle <= 1'b1; + s_bits <= 3'b010; + biu_state <= 8'h01; + end + + // Halt Request + 8'h18 : begin + addr_out_temp <= { biu_register_cs[15:0] , 4'h0 } + pfq_addr_out[15:0] ; + s_bits <= 3'b011; + biu_state <= 8'h01; + end + + // Memory Byte Read + 8'h0C : begin + addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; + s_bits <= 3'b101; + biu_state <= 8'h01; + end + + // Memory Word Read + 8'h10 : begin + addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; + word_cycle <= 1'b1; + s_bits <= 3'b101; + biu_state <= 8'h01; + end + + // Memory Word Read from Stack Segment + 8'h11 : begin + addr_out_temp <= { biu_register_ss[15:0] , 4'h0 } + eu_register_r3_d[15:0]; + word_cycle <= 1'b1; + s_bits <= 3'b101; + biu_state <= 8'h01; + end + + // Memory Word Read from Segment 0x0000 - Used for interrupt vector fetches + 8'h12 : begin + addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; + word_cycle <= 1'b1; + s_bits <= 3'b101; + biu_state <= 8'h01; + end + + // Memory Byte Write + 8'h0E : begin + addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; + s_bits <= 3'b110; + biu_state <= 8'h01; + end + + // Memory Word Write + 8'h13 : begin + addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; + word_cycle <= 1'b1; + s_bits <= 3'b110; + biu_state <= 8'h01; + end + + // Memory Word Write to Stack Segment + 8'h14 : begin + addr_out_temp <= { biu_register_ss[15:0] , 4'h0 } + eu_register_r3_d[15:0]; + word_cycle <= 1'b1; + s_bits <= 3'b110; + biu_state <= 8'h01; + end + + // Jump Request + 8'h19 : begin + biu_done_int <= 1'b1; + biu_state <= 8'h46; + end + + default : ; + endcase + end + + + else if (pfq_full==1'b0) + begin + addr_out_temp <= { biu_register_cs[15:0] , 4'h0 } + pfq_addr_in[15:0] ; + s_bits <= 3'b100; + biu_state <= 8'h01; + end + + else + begin + biu_state <= 8'h00; + end + + end - - - // Wait for the rising edge of CLK to start the bus cycle; then assert the S bits. - // Leave AD bus hi-Z during INTA cycles. + + + // Wait for the rising edge of CLK to start the bus cycle; then assert the S bits. + // Leave AD bus hi-Z during INTA cycles. 8'h01 : - begin - if (s_bits!=3'b000) - begin - AD_OE <= 1'b1; - AD_OUT[19:0] <= addr_out_temp[19:0]; - end - - S6_3_MUX <= 1'b0; - if (clk_d4==1'b0 && clk_d3==1'b0 && clk_d2==1'b1) // Wait until next CLK rising edge - begin - s2_s0_out_int <= s_bits; - end - else - begin - biu_state <= 8'h01; - end - end - - - - // On the next falling CLK edge, switch the S[6:3] bits mode and float the AD[7:0] bus if it is a read cycle, and mux data to the databus - // Assert the LOCK_n signal on the first cycle of an INTA cycle. + begin + if (s_bits!=3'b000) + begin + AD_OE <= 1'b1; + AD_OUT[19:0] <= addr_out_temp[19:0]; + end + + S6_3_MUX <= 1'b0; + if (clk_d4==1'b0 && clk_d3==1'b0 && clk_d2==1'b1) // Wait until next CLK rising edge + begin + s2_s0_out_int <= s_bits; + end + else + begin + biu_state <= 8'h01; + end + end + + + + // On the next falling CLK edge, switch the S[6:3] bits mode and float the AD[7:0] bus if it is a read cycle, and mux data to the databus + // Assert the LOCK_n signal on the first cycle of an INTA cycle. 8'h1A : begin - if (s_bits==3'b000 && byte_num==1'b0) - begin - biu_lock_n_int <= 1'b0; - end - else - begin - biu_lock_n_int <= 1'b1; - end - - S6_3_MUX <= 1'b1; - - AD_OE <= s_bits[1]; // Turn off bus drivers for read cycles - - if (word_cycle==1'b1 && byte_num==1'b1) - begin - AD_OUT[7:0] <= EU_BIU_DATAOUT[15:8]; - end - else - begin - AD_OUT[7:0] <= EU_BIU_DATAOUT[7:0]; - end - end - + if (s_bits==3'b000 && byte_num==1'b0) + begin + biu_lock_n_int <= 1'b0; + end + else + begin + biu_lock_n_int <= 1'b1; + end + + S6_3_MUX <= 1'b1; + + AD_OE <= s_bits[1]; // Turn off bus drivers for read cycles + + if (word_cycle==1'b1 && byte_num==1'b1) + begin + AD_OUT[7:0] <= EU_BIU_DATAOUT[15:8]; + end + else + begin + AD_OUT[7:0] <= EU_BIU_DATAOUT[7:0]; + end + end + - - // On the next falling CLK edge, sample the READY signal + + // On the next falling CLK edge, sample the READY signal 8'h36 : begin - if (ready_d3==1'b0) // Not ready yet, wait another clock cycle - begin - biu_state <= 8'h22; - end - else - begin - s2_s0_out_int <= 3'b111; - end - end + if (ready_d3==1'b0) // Not ready yet, wait another clock cycle + begin + biu_state <= 8'h22; + end + else + begin + s2_s0_out_int <= 3'b111; + end + end - - + + // On the next rising CLK edge, sample the data. 8'h3D : begin - latched_data_in <= ad_in_int; - + latched_data_in <= ad_in_int; + // If a code fetch, then write data to the prefetch queue - if (s_bits==3'b100) - begin - pfq_write <= 1'b1; - end - - end - + if (s_bits==3'b100) + begin + pfq_write <= 1'b1; + end + + end + - + // Debounce the prefetch queue write pulse and increment the prefetch queue address. 8'h3E : begin - pfq_write <= 1'b0; - end - - - + pfq_write <= 1'b0; + end + + + // Steer the data 8'h40 : begin - if (s_bits!=3'b000 && (word_cycle==1'b1 && byte_num==1'b1)) - begin - biu_return_data_int[15:8] <= latched_data_in[7:0]; - end - else - begin - biu_return_data_int[15:0] <= { 8'h00 , latched_data_in[7:0] }; - end - end - - - + if (s_bits!=3'b000 && (word_cycle==1'b1 && byte_num==1'b1)) + begin + biu_return_data_int[15:8] <= latched_data_in[7:0]; + end + else + begin + biu_return_data_int[15:0] <= { 8'h00 , latched_data_in[7:0] }; + end + end + + + // On the next falling CLK edge, the cycle is complete. - 8'h45 : begin - addr_out_temp[15:0] <= addr_out_temp[15:0] + 1; - if (word_cycle==1'b1 && byte_num==1'b0) - begin - byte_num <= 1'b1; - biu_state <= 8'h50; - end - else - begin - if (s_bits!=3'b100) - begin - biu_done_int <= 1'b1; - end - end - end - - + 8'h45 : begin + addr_out_temp[15:0] <= addr_out_temp[15:0] + 1; + if (word_cycle==1'b1 && byte_num==1'b0) + begin + byte_num <= 1'b1; + biu_state <= 8'h50; + end + else + begin + if (s_bits!=3'b100) + begin + biu_done_int <= 1'b1; + end + end + end + + 8'h46 : begin - biu_done_int <= 1'b0; - end - - + biu_done_int <= 1'b0; + end + + 8'h4E : begin - biu_state <= 8'h00; - end - - + biu_state <= 8'h00; + end + + 8'h58 : begin - biu_state <= 8'h01; - end + biu_state <= 8'h01; + end - - default : ; + + default : ; endcase - + end end // BIU endmodule // biu.v - - - - - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/MCL86/Core/biu_min.v b/MCL86/Core/biu_min.v index 18ccecb..36418d2 100644 --- a/MCL86/Core/biu_min.v +++ b/MCL86/Core/biu_min.v @@ -2,7 +2,7 @@ // // File Name : biu_min.v // Used on : -// Author : MicroCore Labs +// Author : Ted Fried, MicroCore Labs // Creation : 10/8/2015 // Code Type : Synthesizable // @@ -21,60 +21,82 @@ // // //------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ module biu_min ( - input CORE_CLK_INT, // Core Clock + input CORE_CLK_INT, // Core Clock - - input CLK, // 8088 Pins - input RESET_INT, - input READY_IN, - input NMI, - input INTR, - output reg INTA_n, - output reg ALE, - output reg RD_n, - output reg WR_n, - output reg IOM, - output reg DTR, - output reg DEN, - output reg AD_OE, - output reg [19:0] AD_OUT, - input [7:0] AD_IN, + + input CLK, // 8088 Pins + input RESET_INT, + input READY_IN, + input NMI, + input INTR, + output reg INTA_n, + output reg ALE, + output reg RD_n, + output reg WR_n, + output reg IOM, + output reg DTR, + output reg DEN, + output reg AD_OE, + output reg [19:0] AD_OUT, + input [7:0] AD_IN, - - input [15:0] EU_BIU_COMMAND, // EU to BIU Signals - input [15:0] EU_BIU_DATAOUT, - input [15:0] EU_REGISTER_R3, - input EU_PREFIX_LOCK, - - - output BIU_DONE, // BIU to EU Signals - output BIU_CLK_COUNTER_ZERO, - output [1:0] BIU_SEGMENT, - output BIU_NMI_CAUGHT, - input BIU_NMI_DEBOUNCE, - output reg BIU_INTR, + + input [15:0] EU_BIU_COMMAND, // EU to BIU Signals + input [15:0] EU_BIU_DATAOUT, + input [15:0] EU_REGISTER_R3, + input EU_PREFIX_LOCK, + + + output BIU_DONE, // BIU to EU Signals + output BIU_CLK_COUNTER_ZERO, + output [1:0] BIU_SEGMENT, + output BIU_NMI_CAUGHT, + input BIU_NMI_DEBOUNCE, + output reg BIU_INTR, - output [7:0] PFQ_TOP_BYTE, - output PFQ_EMPTY, - output[15:0] PFQ_ADDR_OUT, + output [7:0] PFQ_TOP_BYTE, + output PFQ_EMPTY, + output[15:0] PFQ_ADDR_OUT, - output [15:0] BIU_REGISTER_ES, - output [15:0] BIU_REGISTER_SS, - output [15:0] BIU_REGISTER_CS, - output [15:0] BIU_REGISTER_DS, - output [15:0] BIU_REGISTER_RM, - output [15:0] BIU_REGISTER_REG, - output [15:0] BIU_RETURN_DATA - + output [15:0] BIU_REGISTER_ES, + output [15:0] BIU_REGISTER_SS, + output [15:0] BIU_REGISTER_CS, + output [15:0] BIU_REGISTER_DS, + output [15:0] BIU_REGISTER_RM, + output [15:0] BIU_REGISTER_REG, + output [15:0] BIU_RETURN_DATA + ); //------------------------------------------------------------------------ - + // Internal Signals @@ -139,8 +161,8 @@ reg [15:0] pfq_addr_in; reg [7:0] pfq_top_byte_int_d1; reg [15:0] pfq_addr_out_d1; reg [2:0] s_bits; -wire [15:0] biu_muxed_segment; -wire [1:0] biu_segment; +wire [15:0] biu_muxed_segment; +wire [1:0] biu_segment; wire [1:0] eu_biu_strobe; wire [1:0] eu_biu_segment; wire [4:0] eu_biu_req_code; @@ -160,7 +182,7 @@ wire [7:0] pfq_top_byte_int; assign BIU_DONE = biu_done_int; assign PFQ_EMPTY = pfq_empty; assign PFQ_ADDR_OUT = pfq_addr_out_d1; -assign BIU_SEGMENT = biu_segment; +assign BIU_SEGMENT = biu_segment; assign BIU_REGISTER_ES = biu_register_es_d2; assign BIU_REGISTER_SS = biu_register_ss_d2; assign BIU_REGISTER_CS = biu_register_cs_d2; @@ -168,7 +190,7 @@ assign BIU_REGISTER_DS = biu_register_ds_d2; assign BIU_REGISTER_RM = biu_register_rm_d2; assign BIU_REGISTER_REG = biu_register_reg_d2; assign BIU_RETURN_DATA = biu_return_data_int_d2; -assign BIU_NMI_CAUGHT = nmi_caught; +assign BIU_NMI_CAUGHT = nmi_caught; @@ -176,7 +198,7 @@ assign BIU_NMI_CAUGHT = nmi_caught; // eu_biu_strobe[1:0] are available for only one clock cycle and cause BIU to take immediate action. // eu_biu_req stays asserted until the BIU is available to service the request. // -assign eu_prefix_seg = EU_BIU_COMMAND[14]; +assign eu_prefix_seg = EU_BIU_COMMAND[14]; assign eu_biu_strobe[1:0] = EU_BIU_COMMAND[13:12]; // 01=opcode fetch 10=clock load 11=load segment register(eu_biu_req_code has the regiter#) assign eu_biu_segment[1:0] = EU_BIU_COMMAND[11:10]; assign eu_biu_req = EU_BIU_COMMAND[9]; @@ -189,18 +211,18 @@ assign eu_segment_override_value[1:0] = EU_BIU_COMMAND[1:0]; // Select either the current EU Segment or the Segment Override value. assign biu_segment = (eu_prefix_seg==1'b1) ? eu_segment_override_value : eu_biu_segment; - + assign biu_muxed_segment = (biu_segment==2'b00) ? biu_register_es : (biu_segment==2'b01) ? biu_register_ss : (biu_segment==2'b10) ? biu_register_cs : biu_register_ds ; - + // Steer the Prefetch Queue to the EU assign pfq_top_byte_int = (pfq_addr_out[1:0]==2'b00) ? pfq_entry0 : (pfq_addr_out[1:0]==2'b01) ? pfq_entry1 : (pfq_addr_out[1:0]==2'b10) ? pfq_entry2 : - pfq_entry3 ; + pfq_entry3 ; assign PFQ_TOP_BYTE = pfq_top_byte_int_d1; @@ -213,7 +235,7 @@ assign pfq_empty = ( (pfq_addr_in[2]==pfq_addr_out[2]) && (pfq_addr_in[1:0]==pfq assign BIU_CLK_COUNTER_ZERO = (clock_cycle_counter==13'h0000) ? 1'b1 : 1'b0; - + //------------------------------------------------------------------------ // // BIU State Machine @@ -230,10 +252,10 @@ begin : BIU_STATE_MACHINE clk_d2 <= 'h0; clk_d3 <= 'h0; clk_d4 <= 'h0; - nmi_d1 <= 'h0; + nmi_d1 <= 'h0; nmi_d2 <= 'h0; nmi_d3 <= 'h0; - nmi_caught <= 'h0; + nmi_caught <= 'h0; eu_register_r3_d <= 'h0; eu_biu_req_caught <= 'h0; biu_register_cs <= 16'hFFFF; @@ -251,34 +273,34 @@ begin : BIU_STATE_MACHINE biu_state <= 8'hD0; pfq_write <= 'h0; pfq_addr_in <= 'h0; - biu_return_data_int <= 'h0; - biu_done_int <= 'h0; - ready_d1 <= 'h0; + biu_return_data_int <= 'h0; + biu_done_int <= 'h0; + ready_d1 <= 'h0; ready_d2 <= 'h0; ready_d3 <= 'h0; - eu_biu_req_d1 <= 'h0; - latched_data_in <= 'h0; - addr_out_temp <= 'h0; - s_bits <= 3'b111; - AD_OUT <= 'h0; - word_cycle <= 1'b0; - byte_num <= 1'b0; - ad_in_int <= 'h0; - BIU_INTR <= 'h0; - eu_prefix_lock_d1 <= 'h0; + eu_biu_req_d1 <= 'h0; + latched_data_in <= 'h0; + addr_out_temp <= 'h0; + s_bits <= 3'b111; + AD_OUT <= 'h0; + word_cycle <= 1'b0; + byte_num <= 1'b0; + ad_in_int <= 'h0; + BIU_INTR <= 'h0; + eu_prefix_lock_d1 <= 'h0; eu_prefix_lock_d2 <= 'h0; - intr_d1 <= 'h0; - intr_d2 <= 'h0; - intr_d3 <= 'h0; - - AD_OE <= 'h0; - RD_n <= 1'b1; - WR_n <= 1'b1; - IOM <= 'h0; - DTR <= 'h0; - DEN <= 1'b1; - INTA_n <= 1'b1; - + intr_d1 <= 'h0; + intr_d2 <= 'h0; + intr_d3 <= 'h0; + + AD_OE <= 'h0; + RD_n <= 1'b1; + WR_n <= 1'b1; + IOM <= 'h0; + DTR <= 'h0; + DEN <= 1'b1; + INTA_n <= 1'b1; + end else @@ -287,149 +309,149 @@ else // Register pipelining clk_d1 <= CLK; - clk_d2 <= clk_d1; - clk_d3 <= clk_d2; - clk_d4 <= clk_d3; + clk_d2 <= clk_d1; + clk_d3 <= clk_d2; + clk_d4 <= clk_d3; + + ready_d1 <= READY_IN; + ready_d2 <= ready_d1; + ready_d3 <= ready_d2; - ready_d1 <= READY_IN; - ready_d2 <= ready_d1; - ready_d3 <= ready_d2; - nmi_d1 <= NMI; - nmi_d2 <= nmi_d1; - nmi_d3 <= nmi_d2; - - intr_d1 <= INTR; - intr_d2 <= intr_d1; - intr_d3 <= intr_d2; - - - // These signals may be pipelined from zero to two clocks. - // They are currently pipelined by two clocks. - biu_register_es_d1 <= biu_register_es; - biu_register_ss_d1 <= biu_register_ss; - biu_register_cs_d1 <= biu_register_cs; + nmi_d2 <= nmi_d1; + nmi_d3 <= nmi_d2; + + intr_d1 <= INTR; + intr_d2 <= intr_d1; + intr_d3 <= intr_d2; + + + // These signals may be pipelined from zero to two clocks. + // They are currently pipelined by two clocks. + biu_register_es_d1 <= biu_register_es; + biu_register_ss_d1 <= biu_register_ss; + biu_register_cs_d1 <= biu_register_cs; biu_register_ds_d1 <= biu_register_ds; biu_register_rm_d1 <= biu_register_rm; biu_register_reg_d1 <= biu_register_reg; biu_register_es_d2 <= biu_register_es_d1; - biu_register_ss_d2 <= biu_register_ss_d1; - biu_register_cs_d2 <= biu_register_cs_d1; + biu_register_ss_d2 <= biu_register_ss_d1; + biu_register_cs_d2 <= biu_register_cs_d1; biu_register_ds_d2 <= biu_register_ds_d1; biu_register_rm_d2 <= biu_register_rm_d1; biu_register_reg_d2 <= biu_register_reg_d1; - + - // These signals may be pipelined from zero to one clock. - // They are currently pipelined by one clock. - pfq_top_byte_int_d1 <= pfq_top_byte_int; + // These signals may be pipelined from zero to one clock. + // They are currently pipelined by one clock. + pfq_top_byte_int_d1 <= pfq_top_byte_int; pfq_addr_out_d1 <= pfq_addr_out; - - // This signal may be pipelined any number of clocks as - // long as is stable before BIU_DONE is asserted. + + // This signal may be pipelined any number of clocks as + // long as is stable before BIU_DONE is asserted. biu_return_data_int_d1 <= biu_return_data_int; biu_return_data_int_d2 <= biu_return_data_int_d1; - - - // NMI caught on it's rising edge - if (nmi_d3==1'b0 && nmi_d2==1'b0 && nmi_d1==1'b1) - begin - nmi_caught <= 1'b1; - end - else if (BIU_NMI_DEBOUNCE==1'b1) - begin - nmi_caught <= 1'b0; - end - - // INTR sampled on the rising edge of the CLK - if (clk_d4==1'b0 && clk_d3==1'b0 && clk_d2==1'b1) - begin - BIU_INTR <= intr_d3; + + + // NMI caught on it's rising edge + if (nmi_d3==1'b0 && nmi_d2==1'b0 && nmi_d1==1'b1) + begin + nmi_caught <= 1'b1; end - - eu_prefix_lock_d1 <= EU_PREFIX_LOCK; - eu_prefix_lock_d2 <= eu_prefix_lock_d1; - - - // Register pipelining in and out of the BIU. - eu_register_r3_d <= EU_REGISTER_R3; - ad_in_int <= AD_IN; - - - - // Capture a bus request from the EU - eu_biu_req_d1 <= eu_biu_req; - if (eu_biu_req_d1==1'b0 && eu_biu_req==1'b1) - begin - eu_biu_req_caught <= 1'b1; + else if (BIU_NMI_DEBOUNCE==1'b1) + begin + nmi_caught <= 1'b0; end - else if (biu_done_int==1'b1) - begin - eu_biu_req_caught <= 1'b0; - end - - - // Strobe from EU to update the segment and addressing registers - if (eu_biu_strobe==2'b11) - begin - case (eu_biu_req_code[2:0]) // synthesis parallel_case - 3'h0 : biu_register_es <= EU_BIU_DATAOUT[15:0]; - 3'h1 : biu_register_ss <= EU_BIU_DATAOUT[15:0]; - 3'h2 : biu_register_cs <= EU_BIU_DATAOUT[15:0]; - 3'h3 : biu_register_ds <= EU_BIU_DATAOUT[15:0]; - 3'h4 : biu_register_rm <= EU_BIU_DATAOUT[15:0]; - 3'h5 : biu_register_reg <= EU_BIU_DATAOUT[15:0]; - default : ; - endcase - end + // INTR sampled on the rising edge of the CLK + if (clk_d4==1'b0 && clk_d3==1'b0 && clk_d2==1'b1) + begin + BIU_INTR <= intr_d3; + end + + eu_prefix_lock_d1 <= EU_PREFIX_LOCK; + eu_prefix_lock_d2 <= eu_prefix_lock_d1; - + + // Register pipelining in and out of the BIU. + eu_register_r3_d <= EU_REGISTER_R3; + ad_in_int <= AD_IN; + + + + // Capture a bus request from the EU + eu_biu_req_d1 <= eu_biu_req; + if (eu_biu_req_d1==1'b0 && eu_biu_req==1'b1) + begin + eu_biu_req_caught <= 1'b1; + end + else if (biu_done_int==1'b1) + begin + eu_biu_req_caught <= 1'b0; + end + + + + // Strobe from EU to update the segment and addressing registers + if (eu_biu_strobe==2'b11) + begin + case (eu_biu_req_code[2:0]) // synthesis parallel_case + 3'h0 : biu_register_es <= EU_BIU_DATAOUT[15:0]; + 3'h1 : biu_register_ss <= EU_BIU_DATAOUT[15:0]; + 3'h2 : biu_register_cs <= EU_BIU_DATAOUT[15:0]; + 3'h3 : biu_register_ds <= EU_BIU_DATAOUT[15:0]; + 3'h4 : biu_register_rm <= EU_BIU_DATAOUT[15:0]; + 3'h5 : biu_register_reg <= EU_BIU_DATAOUT[15:0]; + default : ; + endcase + end + + // Strobe from EU to set the 8088 clock cycle counter if (eu_biu_strobe==2'b10) begin - clock_cycle_counter <= EU_BIU_DATAOUT[12:0]; - end + clock_cycle_counter <= EU_BIU_DATAOUT[12:0]; + end else if (clock_cycle_counter!=13'h0000) begin - clock_cycle_counter <= clock_cycle_counter - 1; - end - + clock_cycle_counter <= clock_cycle_counter - 1; + end + // Prefetch Queue - // -------------- - // Increment the output address of the queue upon EU fetch request strobe. - // Update/flush the Prefetch Queue when the EU asserts the Jump request. - // Increment the input address during prefetch queue fetches. + // -------------- + // Increment the output address of the queue upon EU fetch request strobe. + // Update/flush the Prefetch Queue when the EU asserts the Jump request. + // Increment the input address during prefetch queue fetches. //--------------------------------------------------------------------------------- if (eu_biu_req_caught==1'b1 && eu_biu_req_code==5'h19) begin pfq_addr_out <= eu_register_r3_d; // Update the prefetch queue to the new address. end - else if (eu_biu_strobe==2'b01 && pfq_empty==1'b0) + else if (eu_biu_strobe==2'b01 && pfq_empty==1'b0) begin - pfq_addr_out <= pfq_addr_out + 1; // Increment the current IP - Instruction Pointer - end - - + pfq_addr_out <= pfq_addr_out + 1; // Increment the current IP - Instruction Pointer + end + + if (eu_biu_req_caught==1'b1 && eu_biu_req_code==5'h19) begin pfq_addr_in <= eu_register_r3_d; // Update the prefetch queue to the new address. end - else if (pfq_write==1'b1) + else if (pfq_write==1'b1) begin - pfq_addr_in <= pfq_addr_in + 1; - end - - - - // Write to the selected prefetch queue entry. - if (pfq_write==1'b1) + pfq_addr_in <= pfq_addr_in + 1; + end + + + + // Write to the selected prefetch queue entry. + if (pfq_write==1'b1) begin - case (pfq_addr_in[1:0]) // synthesis parallel_case + case (pfq_addr_in[1:0]) // synthesis parallel_case 2'b00 : pfq_entry0 <= latched_data_in[7:0]; 2'b01 : pfq_entry1 <= latched_data_in[7:0]; 2'b10 : pfq_entry2 <= latched_data_in[7:0]; @@ -437,323 +459,323 @@ else default : ; endcase end - + - - - - // 8088 BIU State Machine - // ---------------------- - - biu_state <= biu_state + 1'b1; - case (biu_state) // synthesis parallel_case - - 8'h00 : begin - // Debounce signals - pfq_write <= 1'b0; - byte_num <= 1'b0; - word_cycle <= 1'b0; - + + + + // 8088 BIU State Machine + // ---------------------- + + biu_state <= biu_state + 1'b1; + case (biu_state) // synthesis parallel_case + + 8'h00 : begin + // Debounce signals + pfq_write <= 1'b0; + byte_num <= 1'b0; + word_cycle <= 1'b0; + - if (eu_biu_req_caught==1'b1) - begin - - case (eu_biu_req_code) // synthesis parallel_case - - // Interrupt ACK Cycle - 8'h16 : begin - addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; - //AD_OE <= 'h0; - word_cycle <= 1'b1; - s_bits <= 3'b000; - biu_state <= 8'h01; - end - - // IO Byte Read - 8'h08 : begin - addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; - s_bits <= 3'b001; - biu_state <= 8'h01; - end - - // IO Word Read - 8'h1A : begin - addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; - word_cycle <= 1'b1; - s_bits <= 3'b001; - biu_state <= 8'h01; - end - - // IO Byte Write - 8'h0A : begin - addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; - s_bits <= 3'b010; - biu_state <= 8'h01; - end - - // IO Word Write - 8'h1C : begin - addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; - word_cycle <= 1'b1; - s_bits <= 3'b010; - biu_state <= 8'h01; - end - - // Halt Request - 8'h18 : begin - addr_out_temp <= { biu_register_cs[15:0] , 4'h0 } + pfq_addr_out[15:0] ; - s_bits <= 3'b011; - biu_state <= 8'h01; - end - - // Memory Byte Read - 8'h0C : begin - addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; - s_bits <= 3'b101; - biu_state <= 8'h01; - end - - // Memory Word Read - 8'h10 : begin - addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; - word_cycle <= 1'b1; - s_bits <= 3'b101; - biu_state <= 8'h01; - end - - // Memory Word Read from Stack Segment - 8'h11 : begin - addr_out_temp <= { biu_register_ss[15:0] , 4'h0 } + eu_register_r3_d[15:0]; - word_cycle <= 1'b1; - s_bits <= 3'b101; - biu_state <= 8'h01; - end - - // Memory Word Read from Segment 0x0000 - Used for interrupt vector fetches - 8'h12 : begin - addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; - word_cycle <= 1'b1; - s_bits <= 3'b101; - biu_state <= 8'h01; - end - - // Memory Byte Write - 8'h0E : begin - addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; - s_bits <= 3'b110; - biu_state <= 8'h01; - end - - // Memory Word Write - 8'h13 : begin - addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; - word_cycle <= 1'b1; - s_bits <= 3'b110; - biu_state <= 8'h01; - end - - // Memory Word Write to Stack Segment - 8'h14 : begin - addr_out_temp <= { biu_register_ss[15:0] , 4'h0 } + eu_register_r3_d[15:0]; - word_cycle <= 1'b1; - s_bits <= 3'b110; - biu_state <= 8'h01; - end - - // Jump Request - 8'h19 : begin - biu_done_int <= 1'b1; - biu_state <= 8'h46; - end - - default : ; - endcase - end - - - else if (pfq_full==1'b0) - begin - addr_out_temp <= { biu_register_cs[15:0] , 4'h0 } + pfq_addr_in[15:0] ; - s_bits <= 3'b100; - biu_state <= 8'h01; - end - - else - begin - biu_state <= 8'h00; - end - - end + if (eu_biu_req_caught==1'b1) + begin + + case (eu_biu_req_code) // synthesis parallel_case + + // Interrupt ACK Cycle + 8'h16 : begin + addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; + //AD_OE <= 'h0; + word_cycle <= 1'b1; + s_bits <= 3'b000; + biu_state <= 8'h01; + end + + // IO Byte Read + 8'h08 : begin + addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; + s_bits <= 3'b001; + biu_state <= 8'h01; + end + + // IO Word Read + 8'h1A : begin + addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; + word_cycle <= 1'b1; + s_bits <= 3'b001; + biu_state <= 8'h01; + end + + // IO Byte Write + 8'h0A : begin + addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; + s_bits <= 3'b010; + biu_state <= 8'h01; + end + + // IO Word Write + 8'h1C : begin + addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; + word_cycle <= 1'b1; + s_bits <= 3'b010; + biu_state <= 8'h01; + end + + // Halt Request + 8'h18 : begin + addr_out_temp <= { biu_register_cs[15:0] , 4'h0 } + pfq_addr_out[15:0] ; + s_bits <= 3'b011; + biu_state <= 8'h01; + end + + // Memory Byte Read + 8'h0C : begin + addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; + s_bits <= 3'b101; + biu_state <= 8'h01; + end + + // Memory Word Read + 8'h10 : begin + addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; + word_cycle <= 1'b1; + s_bits <= 3'b101; + biu_state <= 8'h01; + end + + // Memory Word Read from Stack Segment + 8'h11 : begin + addr_out_temp <= { biu_register_ss[15:0] , 4'h0 } + eu_register_r3_d[15:0]; + word_cycle <= 1'b1; + s_bits <= 3'b101; + biu_state <= 8'h01; + end + + // Memory Word Read from Segment 0x0000 - Used for interrupt vector fetches + 8'h12 : begin + addr_out_temp <= { 4'h0 , eu_register_r3_d[15:0] }; + word_cycle <= 1'b1; + s_bits <= 3'b101; + biu_state <= 8'h01; + end + + // Memory Byte Write + 8'h0E : begin + addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; + s_bits <= 3'b110; + biu_state <= 8'h01; + end + + // Memory Word Write + 8'h13 : begin + addr_out_temp <= { biu_muxed_segment[15:0] , 4'h0 } + eu_register_r3_d[15:0]; + word_cycle <= 1'b1; + s_bits <= 3'b110; + biu_state <= 8'h01; + end + + // Memory Word Write to Stack Segment + 8'h14 : begin + addr_out_temp <= { biu_register_ss[15:0] , 4'h0 } + eu_register_r3_d[15:0]; + word_cycle <= 1'b1; + s_bits <= 3'b110; + biu_state <= 8'h01; + end + + // Jump Request + 8'h19 : begin + biu_done_int <= 1'b1; + biu_state <= 8'h46; + end + + default : ; + endcase + end + + + else if (pfq_full==1'b0) + begin + addr_out_temp <= { biu_register_cs[15:0] , 4'h0 } + pfq_addr_in[15:0] ; + s_bits <= 3'b100; + biu_state <= 8'h01; + end + + else + begin + biu_state <= 8'h00; + end + + end - - - // 1 Wait for the rising edge of CLK to start the bus cycle; then assert IOM and DTR + + + // 1 Wait for the rising edge of CLK to start the bus cycle; then assert IOM and DTR 8'h01 : - begin - if (clk_d4==1'b0 && clk_d3==1'b0 && clk_d2==1'b1) // Wait until next CLK rising edge - begin - IOM <= ~s_bits[2]; // Memory cycles - DTR <= s_bits[1]; // Read cycles - end - else - begin - biu_state <= 8'h01; - end - end - - - - // 2 On the next falling CLK edge, assert the ALE and the address + begin + if (clk_d4==1'b0 && clk_d3==1'b0 && clk_d2==1'b1) // Wait until next CLK rising edge + begin + IOM <= ~s_bits[2]; // Memory cycles + DTR <= s_bits[1]; // Read cycles + end + else + begin + biu_state <= 8'h01; + end + end + + + + // 2 On the next falling CLK edge, assert the ALE and the address 8'h04 : begin - AD_OUT[19:0] <= addr_out_temp[19:0]; - AD_OE <= 1'b1; - ALE <= 1'b1; + AD_OUT[19:0] <= addr_out_temp[19:0]; + AD_OE <= 1'b1; + ALE <= 1'b1; - end + end - - - // 3 On the next rising CLK edge, disable ALE, drive early DEN + + + // 3 On the next rising CLK edge, disable ALE, drive early DEN 8'h13 : begin ALE <= 1'b0; - if (s_bits[1]==1'b1) - begin - DEN <= 1'b0; - end - - end + if (s_bits[1]==1'b1) + begin + DEN <= 1'b0; + end + + end - - // 4 On the next falling CLK edge, float the AD[7:0] bus if it is a read cycle, and drive AD with write data + + // 4 On the next falling CLK edge, float the AD[7:0] bus if it is a read cycle, and drive AD with write data 8'h19 : begin - AD_OE <= s_bits[1]; // Turn off bus drivers for read cycles - RD_n <= s_bits[1]; // Assert RD_n for read cycles - WR_n <= ~s_bits[1]; // Assert WR_n for write cycles - - if (s_bits==3'b000) - begin - INTA_n <= 1'b0; - end - - if (word_cycle==1'b1 && byte_num==1'b1) - begin - AD_OUT[7:0] <= EU_BIU_DATAOUT[15:8]; - end - else - begin - AD_OUT[7:0] <= EU_BIU_DATAOUT[7:0]; - end - - end - - - // 5 On the next rising CLK edge, assert DEN is if has not been already + AD_OE <= s_bits[1]; // Turn off bus drivers for read cycles + RD_n <= s_bits[1]; // Assert RD_n for read cycles + WR_n <= ~s_bits[1]; // Assert WR_n for write cycles + + if (s_bits==3'b000) + begin + INTA_n <= 1'b0; + end + + if (word_cycle==1'b1 && byte_num==1'b1) + begin + AD_OUT[7:0] <= EU_BIU_DATAOUT[15:8]; + end + else + begin + AD_OUT[7:0] <= EU_BIU_DATAOUT[7:0]; + end + + end + + + // 5 On the next rising CLK edge, assert DEN is if has not been already 8'h28 : begin - DEN <= 1'b0; - end - - - - - // 6 On the next falling CLK edge, sample the READY signal + DEN <= 1'b0; + end + + + + + // 6 On the next falling CLK edge, sample the READY signal 8'h2F : begin - if (ready_d3==1'b0) // Not ready yet, wait another clock cycle - begin - biu_state <= 8'h1A; - end - end + if (ready_d3==1'b0) // Not ready yet, wait another clock cycle + begin + biu_state <= 8'h1A; + end + end - - + + // 7 On the next rising CLK edge, sample the data. 8'h3D : begin - latched_data_in <= ad_in_int; - + latched_data_in <= ad_in_int; + // If a code fetch, then write data to the prefetch queue - if (s_bits==3'b100) - begin - pfq_write <= 1'b1; - end - - end - - - - + if (s_bits==3'b100) + begin + pfq_write <= 1'b1; + end + + end + + + + // Debounce the prefetch queue write pulse and increment the prefetch queue address. 8'h3E : begin - pfq_write <= 1'b0; - end - - - + pfq_write <= 1'b0; + end + + + // 8 Steer the data 8'h40 : begin - if (s_bits!=3'b000 && (word_cycle==1'b1 && byte_num==1'b1)) - begin - biu_return_data_int[15:8] <= latched_data_in[7:0]; - end - else - begin - biu_return_data_int[15:0] <= { 8'h00 , latched_data_in[7:0] }; - end - end - - - + if (s_bits!=3'b000 && (word_cycle==1'b1 && byte_num==1'b1)) + begin + biu_return_data_int[15:8] <= latched_data_in[7:0]; + end + else + begin + biu_return_data_int[15:0] <= { 8'h00 , latched_data_in[7:0] }; + end + end + + + // 8 On the next falling CLK edge, the cycle is complete. - 8'h45 : begin - WR_n <= 1'b1; - RD_n <= 1'b1; - DEN <= 1'b1; - INTA_n <= 1'b1; + 8'h45 : begin + WR_n <= 1'b1; + RD_n <= 1'b1; + DEN <= 1'b1; + INTA_n <= 1'b1; - - addr_out_temp[15:0] <= addr_out_temp[15:0] + 1; - if (word_cycle==1'b1 && byte_num==1'b0) - begin - byte_num <= 1'b1; - biu_state <= 8'h50; - end - else - begin - if (s_bits!=3'b100) - begin - biu_done_int <= 1'b1; - end - end - end - - + + addr_out_temp[15:0] <= addr_out_temp[15:0] + 1; + if (word_cycle==1'b1 && byte_num==1'b0) + begin + byte_num <= 1'b1; + biu_state <= 8'h50; + end + else + begin + if (s_bits!=3'b100) + begin + biu_done_int <= 1'b1; + end + end + end + + 8'h46 : begin - biu_done_int <= 1'b0; - end - - + biu_done_int <= 1'b0; + end + + 8'h4E : begin - biu_state <= 8'h00; - end - - + biu_state <= 8'h00; + end + + 8'h58 : begin - biu_state <= 8'h01; - end + biu_state <= 8'h01; + end - - default : ; + + default : ; endcase - + end end // BIU endmodule // biu.v - - - - - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/MCL86/Core/eu.v b/MCL86/Core/eu.v index d2b4b04..f3a3141 100644 --- a/MCL86/Core/eu.v +++ b/MCL86/Core/eu.v @@ -2,7 +2,7 @@ // // File Name : mcl86_eu_core.v // Used on : -// Author : MicroCore Labs +// Author : Ted Fried, MicroCore Labs // Creation : 10/8/2015 // Code Type : Synthesizable // @@ -21,46 +21,68 @@ // // //------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ module mcl86_eu_core ( - input CORE_CLK_INT, // Core Clock - input RESET_INT, // Pipelined 8088 RESET pin - input TEST_N_INT, // Pipelined 8088 TEST_n pin + input CORE_CLK_INT, // Core Clock + input RESET_INT, // Pipelined 8088 RESET pin + input TEST_N_INT, // Pipelined 8088 TEST_n pin - - output [15:0] EU_BIU_COMMAND, // EU to BIU Signals - output [15:0] EU_BIU_DATAOUT, - output [15:0] EU_REGISTER_R3, - output EU_PREFIX_LOCK, - output EU_FLAG_I, - - - input BIU_DONE, // BIU to EU Signals - input BIU_CLK_COUNTER_ZERO, - input BIU_NMI_CAUGHT, - output BIU_NMI_DEBOUNCE, - input BIU_INTR, + + output [15:0] EU_BIU_COMMAND, // EU to BIU Signals + output [15:0] EU_BIU_DATAOUT, + output [15:0] EU_REGISTER_R3, + output EU_PREFIX_LOCK, + output EU_FLAG_I, + + + input BIU_DONE, // BIU to EU Signals + input BIU_CLK_COUNTER_ZERO, + input BIU_NMI_CAUGHT, + output BIU_NMI_DEBOUNCE, + input BIU_INTR, - - input [7:0] PFQ_TOP_BYTE, - input PFQ_EMPTY, - input[15:0] PFQ_ADDR_OUT, + + input [7:0] PFQ_TOP_BYTE, + input PFQ_EMPTY, + input[15:0] PFQ_ADDR_OUT, - - input [15:0] BIU_REGISTER_ES, - input [15:0] BIU_REGISTER_SS, - input [15:0] BIU_REGISTER_CS, - input [15:0] BIU_REGISTER_DS, - input [15:0] BIU_REGISTER_RM, - input [15:0] BIU_REGISTER_REG, - input [15:0] BIU_RETURN_DATA + + input [15:0] BIU_REGISTER_ES, + input [15:0] BIU_REGISTER_SS, + input [15:0] BIU_REGISTER_CS, + input [15:0] BIU_REGISTER_DS, + input [15:0] BIU_REGISTER_RM, + input [15:0] BIU_REGISTER_REG, + input [15:0] BIU_RETURN_DATA ); //------------------------------------------------------------------------ - + // Internal Signals @@ -140,13 +162,13 @@ wire [31:0] eu_rom_data; // // EU Microcode RAM. 4Kx32 DPRAM // -//------------------------------------------------------------------------ +//------------------------------------------------------------------------ -eu_rom EU_4Kx32 ( +eu_rom EU_4Kx32 ( - .clka (CORE_CLK_INT), - .addra (eu_rom_address[11:0]), - .douta (eu_rom_data) + .clka (CORE_CLK_INT), + .addra (eu_rom_address[11:0]), + .douta (eu_rom_data) ); @@ -158,23 +180,23 @@ eu_rom EU_4Kx32 ( // //------------------------------------------------------------------------ -assign EU_BIU_COMMAND = eu_biu_command; -assign EU_BIU_DATAOUT = eu_biu_dataout; -assign EU_REGISTER_R3 = eu_register_r3; -assign EU_FLAG_I = intr_enable_delayed; -assign EU_PREFIX_LOCK = eu_prefix_lock; +assign EU_BIU_COMMAND = eu_biu_command; +assign EU_BIU_DATAOUT = eu_biu_dataout; +assign EU_REGISTER_R3 = eu_register_r3; +assign EU_FLAG_I = intr_enable_delayed; +assign EU_PREFIX_LOCK = eu_prefix_lock; // EU ROM opcode decoder -assign eu_opcode_type = eu_rom_data[30:28]; -assign eu_opcode_dst_sel = eu_rom_data[27:24]; -assign eu_opcode_op0_sel = eu_rom_data[23:20]; -assign eu_opcode_op1_sel = eu_rom_data[19:16]; +assign eu_opcode_type = eu_rom_data[30:28]; +assign eu_opcode_dst_sel = eu_rom_data[27:24]; +assign eu_opcode_op0_sel = eu_rom_data[23:20]; +assign eu_opcode_op1_sel = eu_rom_data[19:16]; assign eu_opcode_immediate = eu_rom_data[15:0]; -assign eu_opcode_jump_call = eu_rom_data[24]; -assign eu_opcode_jump_src = eu_rom_data[22:20]; -assign eu_opcode_jump_cond = eu_rom_data[19:16]; +assign eu_opcode_jump_call = eu_rom_data[24]; +assign eu_opcode_jump_src = eu_rom_data[22:20]; +assign eu_opcode_jump_cond = eu_rom_data[19:16]; @@ -195,7 +217,7 @@ assign eu_operand0 = (eu_opcode_op0_sel==4'h0) ? eu_register_ax : (eu_opcode_op0_sel==4'hE) ? system_signals : 16'h0 ; - + assign eu_operand1 = (eu_opcode_op1_sel==4'h0) ? BIU_REGISTER_ES : (eu_opcode_op1_sel==4'h1) ? BIU_REGISTER_SS : (eu_opcode_op1_sel==4'h2) ? BIU_REGISTER_CS : @@ -219,42 +241,42 @@ assign eu_operand1 = (eu_opcode_op1_sel==4'h0) ? BIU_REGISTER_ES : assign eu_jump_boolean = (eu_opcode_jump_cond==4'h0) ? 1'b1 : // unconditional jump (eu_opcode_jump_cond==4'h1 && eu_alu_last_result!=16'h0) ? 1'b1 : (eu_opcode_jump_cond==4'h2 && eu_alu_last_result==16'h0) ? 1'b1 : - 1'b0 ; + 1'b0 ; - + // Consolidated system signals -assign system_signals[13] = eu_add_carry8; -assign system_signals[12] = BIU_CLK_COUNTER_ZERO; -assign system_signals[11] = eu_add_overflow16; -assign system_signals[9] = eu_add_overflow8; -assign system_signals[8] = eu_tr_latched; -assign system_signals[7] = ~PFQ_EMPTY; -assign system_signals[6] = biu_done_caught; -assign system_signals[5] = TEST_N_INT; -assign system_signals[4] = eu_add_aux_carry; -assign system_signals[3] = BIU_NMI_CAUGHT; -assign system_signals[2] = eu_parity; -assign system_signals[1] = intr_asserted; -assign system_signals[0] = eu_add_carry; +assign system_signals[13] = eu_add_carry8; +assign system_signals[12] = BIU_CLK_COUNTER_ZERO; +assign system_signals[11] = eu_add_overflow16; +assign system_signals[9] = eu_add_overflow8; +assign system_signals[8] = eu_tr_latched; +assign system_signals[7] = ~PFQ_EMPTY; +assign system_signals[6] = biu_done_caught; +assign system_signals[5] = TEST_N_INT; +assign system_signals[4] = eu_add_aux_carry; +assign system_signals[3] = BIU_NMI_CAUGHT; +assign system_signals[2] = eu_parity; +assign system_signals[1] = intr_asserted; +assign system_signals[0] = eu_add_carry; -assign eu_prefix_repnz = eu_flags[15]; -assign eu_prefix_rep = eu_flags[14]; -assign eu_prefix_lock = eu_flags[13]; -assign BIU_NMI_DEBOUNCE = eu_flags[12]; -assign eu_flag_o = eu_flags[11]; -assign eu_flag_d = eu_flags[10]; -assign eu_flag_i = eu_flags[9]; -assign eu_flag_t = eu_flags[8]; -assign eu_flag_s = eu_flags[7]; -assign eu_flag_z = eu_flags[6]; -assign eu_tf_debounce = eu_flags[5]; -assign eu_flag_a = eu_flags[4]; -assign eu_nmi_pending = eu_flags[3]; -assign eu_flag_p = eu_flags[2]; -assign eu_flag_temp = eu_flags[1]; -assign eu_flag_c = eu_flags[0]; +assign eu_prefix_repnz = eu_flags[15]; +assign eu_prefix_rep = eu_flags[14]; +assign eu_prefix_lock = eu_flags[13]; +assign BIU_NMI_DEBOUNCE = eu_flags[12]; +assign eu_flag_o = eu_flags[11]; +assign eu_flag_d = eu_flags[10]; +assign eu_flag_i = eu_flags[9]; +assign eu_flag_t = eu_flags[8]; +assign eu_flag_s = eu_flags[7]; +assign eu_flag_z = eu_flags[6]; +assign eu_tf_debounce = eu_flags[5]; +assign eu_flag_a = eu_flags[4]; +assign eu_nmi_pending = eu_flags[3]; +assign eu_flag_p = eu_flags[2]; +assign eu_flag_temp = eu_flags[1]; +assign eu_flag_c = eu_flags[0]; @@ -262,12 +284,12 @@ assign eu_flag_c = eu_flags[0]; // ------------------------------------------ // eu_alu0 = NOP // eu_alu1 = JUMP -assign eu_alu2 = adder_out; // ADD -assign eu_alu3 = { eu_operand0[7:0] , eu_operand0[15:8] }; // BYTESWAP -assign eu_alu4 = eu_operand0 & eu_operand1; // AND -assign eu_alu5 = eu_operand0 | eu_operand1; // OR -assign eu_alu6 = eu_operand0 ^ eu_operand1; // XOR -assign eu_alu7 = { 1'b0 , eu_operand0[15:1] }; // SHR +assign eu_alu2 = adder_out; // ADD +assign eu_alu3 = { eu_operand0[7:0] , eu_operand0[15:8] }; // BYTESWAP +assign eu_alu4 = eu_operand0 & eu_operand1; // AND +assign eu_alu5 = eu_operand0 | eu_operand1; // OR +assign eu_alu6 = eu_operand0 ^ eu_operand1; // XOR +assign eu_alu7 = { 1'b0 , eu_operand0[15:1] }; // SHR @@ -281,7 +303,7 @@ assign eu_alu_out = (eu_opcode_type==3'h2) ? eu_alu2 : (eu_opcode_type==3'h7) ? eu_alu7 : 20'hEEEEE; - + @@ -291,8 +313,8 @@ genvar i; generate for (i=0; i < 16; i=i+1) begin : GEN_ADDER - assign adder_out[i] = eu_operand0[i] ^ eu_operand1[i] ^ carry[i]; - assign carry[i+1] = (eu_operand0[i] & eu_operand1[i]) | (eu_operand0[i] & carry[i]) | (eu_operand1[i] & carry[i]); + assign adder_out[i] = eu_operand0[i] ^ eu_operand1[i] ^ carry[i]; + assign carry[i+1] = (eu_operand0[i] & eu_operand1[i]) | (eu_operand0[i] & carry[i]) | (eu_operand1[i] & carry[i]); end endgenerate @@ -304,9 +326,9 @@ assign eu_biu_req = eu_biu_command[9]; assign intr_asserted = BIU_INTR & intr_enable_delayed; -assign new_instruction = (eu_rom_address[12:8]==5'h01) ? 1'b1 : 1'b0; +assign new_instruction = (eu_rom_address[12:8]==5'h01) ? 1'b1 : 1'b0; - + //------------------------------------------------------------------------------------------ // // EU Microsequencer @@ -348,117 +370,117 @@ begin : EU_MICROSEQUENCER eu_stall_pipeline <= 'h0; eu_rom_address <= 13'h0020; eu_calling_address <= 'h0; - intr_enable_delayed <= 1'b0; + intr_enable_delayed <= 1'b0; end else begin // Delay the INTR enable flag until after the next instruction begins. - // No delay when it is disabled. - if (eu_flag_i==1'b0) - begin - intr_enable_delayed <= 1'b0; - end + // No delay when it is disabled. + if (eu_flag_i==1'b0) + begin + intr_enable_delayed <= 1'b0; + end else - if (new_instruction==1'b1) - begin - intr_enable_delayed <= eu_flag_i; - end - + if (new_instruction==1'b1) + begin + intr_enable_delayed <= eu_flag_i; + end + // Latch the TF flag on its rising edge. - eu_flag_t_d <= eu_flag_t; - if (eu_flag_t_d==1'b0 && eu_flag_t==1'b1) - begin - eu_tr_latched <= 1'b1; + eu_flag_t_d <= eu_flag_t; + if (eu_flag_t_d==1'b0 && eu_flag_t==1'b1) + begin + eu_tr_latched <= 1'b1; end - else if (eu_tf_debounce==1'b1) - begin - eu_tr_latched <= 1'b0; + else if (eu_tf_debounce==1'b1) + begin + eu_tr_latched <= 1'b0; end - - - + + + // Latch the done bit from the biu. - // Debounce it when the request is released. + // Debounce it when the request is released. biu_done_d1 <= BIU_DONE; - biu_done_d2 <= biu_done_d1; - eu_biu_req_d1 <= eu_biu_req; - if (biu_done_d2==1'b0 && biu_done_d1==1'b1) - biu_done_caught <= 1'b1; - else if (eu_biu_req_d1==1'b1 && eu_biu_req==1'b0) - biu_done_caught <= 1'b0; - + biu_done_d2 <= biu_done_d1; + eu_biu_req_d1 <= eu_biu_req; + if (biu_done_d2==1'b0 && biu_done_d1==1'b1) + biu_done_caught <= 1'b1; + else if (eu_biu_req_d1==1'b1 && eu_biu_req==1'b0) + biu_done_caught <= 1'b0; + - - // Generate and store flags for addition - if (eu_stall_pipeline==1'b0 && eu_opcode_type==3'h2) - begin - eu_add_carry <= carry[16]; - eu_add_carry8 <= carry[8]; - eu_add_aux_carry <= carry[4]; - eu_add_overflow16 <= carry[16] ^ carry[15]; - eu_add_overflow8 <= carry[8] ^ carry[7]; + + // Generate and store flags for addition + if (eu_stall_pipeline==1'b0 && eu_opcode_type==3'h2) + begin + eu_add_carry <= carry[16]; + eu_add_carry8 <= carry[8]; + eu_add_aux_carry <= carry[4]; + eu_add_overflow16 <= carry[16] ^ carry[15]; + eu_add_overflow8 <= carry[8] ^ carry[7]; end - - // Register writeback + + // Register writeback if (eu_stall_pipeline==1'b0 && eu_opcode_type!=3'h0 && eu_opcode_type!=3'h1) - begin - eu_alu_last_result <= eu_alu_out[15:0]; - case (eu_opcode_dst_sel) // synthesis parallel_case - 4'h0 : eu_register_ax <= eu_alu_out[15:0]; - 4'h1 : eu_register_bx <= eu_alu_out[15:0]; - 4'h2 : eu_register_cx <= eu_alu_out[15:0]; - 4'h3 : eu_register_dx <= eu_alu_out[15:0]; - 4'h4 : eu_register_sp <= eu_alu_out[15:0]; - 4'h5 : eu_register_bp <= eu_alu_out[15:0]; - 4'h6 : eu_register_si <= eu_alu_out[15:0]; - 4'h7 : eu_register_di <= eu_alu_out[15:0]; - 4'h8 : eu_flags <= eu_alu_out[15:0]; - 4'h9 : eu_register_r0 <= eu_alu_out[15:0]; - 4'hA : eu_register_r1 <= eu_alu_out[15:0]; - 4'hB : eu_register_r2 <= eu_alu_out[15:0]; - 4'hC : eu_register_r3 <= eu_alu_out[15:0]; - 4'hD : eu_biu_command <= eu_alu_out[15:0]; - //4'hE : ; - 4'hF : eu_biu_dataout <= eu_alu_out[15:0]; - default : ; - endcase + begin + eu_alu_last_result <= eu_alu_out[15:0]; + case (eu_opcode_dst_sel) // synthesis parallel_case + 4'h0 : eu_register_ax <= eu_alu_out[15:0]; + 4'h1 : eu_register_bx <= eu_alu_out[15:0]; + 4'h2 : eu_register_cx <= eu_alu_out[15:0]; + 4'h3 : eu_register_dx <= eu_alu_out[15:0]; + 4'h4 : eu_register_sp <= eu_alu_out[15:0]; + 4'h5 : eu_register_bp <= eu_alu_out[15:0]; + 4'h6 : eu_register_si <= eu_alu_out[15:0]; + 4'h7 : eu_register_di <= eu_alu_out[15:0]; + 4'h8 : eu_flags <= eu_alu_out[15:0]; + 4'h9 : eu_register_r0 <= eu_alu_out[15:0]; + 4'hA : eu_register_r1 <= eu_alu_out[15:0]; + 4'hB : eu_register_r2 <= eu_alu_out[15:0]; + 4'hC : eu_register_r3 <= eu_alu_out[15:0]; + 4'hD : eu_biu_command <= eu_alu_out[15:0]; + //4'hE : ; + 4'hF : eu_biu_dataout <= eu_alu_out[15:0]; + default : ; + endcase end - // JUMP Opcode - if (eu_stall_pipeline==1'b0 && eu_opcode_type==3'h1 && eu_jump_boolean==1'b1) - begin - eu_stall_pipeline <= 1'b1; - - // For subroutine CALLs, store next opcode address - if (eu_opcode_jump_call==1'b1) - begin - eu_calling_address[51:0] <= {eu_calling_address[38:0] , eu_rom_address[12:0] }; // 4 deep calling addresses - end + // JUMP Opcode + if (eu_stall_pipeline==1'b0 && eu_opcode_type==3'h1 && eu_jump_boolean==1'b1) + begin + eu_stall_pipeline <= 1'b1; + + // For subroutine CALLs, store next opcode address + if (eu_opcode_jump_call==1'b1) + begin + eu_calling_address[51:0] <= {eu_calling_address[38:0] , eu_rom_address[12:0] }; // 4 deep calling addresses + end - case (eu_opcode_jump_src) // synthesis parallel_case - 3'h0 : eu_rom_address <= eu_opcode_immediate[12:0]; - 3'h1 : eu_rom_address <= { 4'b0 , 1'b1 , PFQ_TOP_BYTE }; // If only used for primary opcode jump, maybe make fixed prepend rather than immediate value prepend? - 3'h2 : eu_rom_address <= { eu_opcode_immediate[4:0], PFQ_TOP_BYTE[7:6] , PFQ_TOP_BYTE[2:0] , 3'b000 }; // Rearranged mod_reg_rm byte - imm,MOD,RM,000 - 3'h3 : begin - eu_rom_address <= eu_calling_address[12:0]; - eu_calling_address[38:0] <= eu_calling_address[51:13]; - end - 3'h4 : eu_rom_address <= { eu_opcode_immediate[7:0], eu_biu_dataout[3:0] , 1'b0 }; // Jump table for EA register fetch decoding. Jump Addresses decoded from biu_dataout. - 3'h5 : eu_rom_address <= { eu_opcode_immediate[6:0], eu_biu_dataout[3:0] , 2'b00 }; // Jump table for EA register writeback decoding. Jump Addresses decoded from biu_dataout. - 3'h6 : eu_rom_address <= { eu_opcode_immediate[12:3], eu_biu_dataout[5:3] }; // Jump table for instructions that share same opcode and decode using the REG field. - - default : ; - endcase - end - + case (eu_opcode_jump_src) // synthesis parallel_case + 3'h0 : eu_rom_address <= eu_opcode_immediate[12:0]; + 3'h1 : eu_rom_address <= { 4'b0 , 1'b1 , PFQ_TOP_BYTE }; // If only used for primary opcode jump, maybe make fixed prepend rather than immediate value prepend? + 3'h2 : eu_rom_address <= { eu_opcode_immediate[4:0], PFQ_TOP_BYTE[7:6] , PFQ_TOP_BYTE[2:0] , 3'b000 }; // Rearranged mod_reg_rm byte - imm,MOD,RM,000 + 3'h3 : begin + eu_rom_address <= eu_calling_address[12:0]; + eu_calling_address[38:0] <= eu_calling_address[51:13]; + end + 3'h4 : eu_rom_address <= { eu_opcode_immediate[7:0], eu_biu_dataout[3:0] , 1'b0 }; // Jump table for EA register fetch decoding. Jump Addresses decoded from biu_dataout. + 3'h5 : eu_rom_address <= { eu_opcode_immediate[6:0], eu_biu_dataout[3:0] , 2'b00 }; // Jump table for EA register writeback decoding. Jump Addresses decoded from biu_dataout. + 3'h6 : eu_rom_address <= { eu_opcode_immediate[12:3], eu_biu_dataout[5:3] }; // Jump table for instructions that share same opcode and decode using the REG field. + + default : ; + endcase + end + else begin - eu_stall_pipeline <= 1'b0; // Debounce the pipeline stall - eu_rom_address <= eu_rom_address + 1'b1; + eu_stall_pipeline <= 1'b0; // Debounce the pipeline stall + eu_rom_address <= eu_rom_address + 1'b1; end end diff --git a/MCLR5/Core/MCLR5.v b/MCLR5/Core/MCLR5.v index 25ca134..00b9b89 100644 --- a/MCLR5/Core/MCLR5.v +++ b/MCLR5/Core/MCLR5.v @@ -14,16 +14,28 @@ // //------------------------------------------------------------------------ // -// Copyright (C) 2018 by Ted Fried info@MicroCoreLabs.com +// Copyright (c) 2020 Ted Fried // -// Permission to use, copy, modify, and distribute this software and its -// documentation for any purpose and without fee is hereby granted, provided -// that the above copyright notice appear in all copies and that both that -// copyright notice and this permission notice appear in supporting documentation. -// This software is provided "as is" without express or implied warranty. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. // //------------------------------------------------------------------------ -// + // Modification History: // ===================== // @@ -36,14 +48,14 @@ module MCLR5 ( - input CORE_CLK, - input RST_n, + input CORE_CLK, + input RST_n, - output [31:0] LOAD_STORE_ADDRESS, - output [31:0] STORE_DATA, - input [31:0] LOAD_DATA, - output LOAD_REQ, - output STORE_REQ + output [31:0] LOAD_STORE_ADDRESS, + output [31:0] STORE_DATA, + input [31:0] LOAD_DATA, + output LOAD_REQ, + output STORE_REQ ); @@ -119,31 +131,31 @@ wire [4:0] alu3_opcode_rd; /* // For Xilinx FPGAs -DPROM_8Kx128 code_rom +DPROM_8Kx128 code_rom ( - .clka (CORE_CLK), - .addra (new_pc[14:2]), - .douta (program_rom_data[127:0]), + .clka (CORE_CLK), + .addra (new_pc[14:2]), + .douta (program_rom_data[127:0]), - .clkb (CORE_CLK), - .addrb (new_pc_plus1[14:2]), - .doutb (program_rom_data[255:128]) + .clkb (CORE_CLK), + .addrb (new_pc_plus1[14:2]), + .doutb (program_rom_data[255:128]) ); */ - DPROM_8Kx128 code_rom ( - .address_a (new_pc[14:2]), // input, width = 13, ram_input.address_a - .address_b (new_pc_plus1[14:2]), // input, width = 13, .address_b - .clock (CORE_CLK), // input, width = 1, .clock - .q_a (program_rom_data[127:0]), // output, width = 128, ram_output.q_a - .q_b (program_rom_data[255:128]) // output, width = 128, .q_b - ); + DPROM_8Kx128 code_rom ( + .address_a (new_pc[14:2]), // input, width = 13, ram_input.address_a + .address_b (new_pc_plus1[14:2]), // input, width = 13, .address_b + .clock (CORE_CLK), // input, width = 1, .clock + .q_a (program_rom_data[127:0]), // output, width = 128, ram_output.q_a + .q_b (program_rom_data[255:128]) // output, width = 128, .q_b + ); - + assign new_pc_plus1 = new_pc + 3'h4; @@ -158,25 +170,25 @@ assign alu3_pc = new_pc + 3; assign alu0_opcode = (new_pc[1:0]==2'h0) ? program_rom_data[31:0] : (new_pc[1:0]==2'h1) ? program_rom_data[63:32] : (new_pc[1:0]==2'h2) ? program_rom_data[95:64] : - program_rom_data[127:96] ; + program_rom_data[127:96] ; assign alu1_opcode = (new_pc[1:0]==2'h0) ? program_rom_data[63:32] : (new_pc[1:0]==2'h1) ? program_rom_data[95:64] : - (new_pc[1:0]==2'h2) ? program_rom_data[127:96] : + (new_pc[1:0]==2'h2) ? program_rom_data[127:96] : program_rom_data[159:128] ; - + assign alu2_opcode = (new_pc[1:0]==2'h0) ? program_rom_data[95:64] : - (new_pc[1:0]==2'h1) ? program_rom_data[127:96] : + (new_pc[1:0]==2'h1) ? program_rom_data[127:96] : (new_pc[1:0]==2'h2) ? program_rom_data[159:128] : - program_rom_data[191:160] ; - + program_rom_data[191:160] ; + assign alu3_opcode = (new_pc[1:0]==2'h0) ? program_rom_data[127:96] : (new_pc[1:0]==2'h1) ? program_rom_data[159:128] : - (new_pc[1:0]==2'h2) ? program_rom_data[191:160] : - program_rom_data[223:192] ; - - + (new_pc[1:0]==2'h2) ? program_rom_data[191:160] : + program_rom_data[223:192] ; + + // Register decodes from the opcode // @@ -214,7 +226,7 @@ assign alu0_rs1 = (alu0_opcode_rs1 == 5'h00) ? 32'h0 : (alu0_opcode_rs1 == 5'h01) ? register_1 : (alu0_opcode_rs1 == 5'h02) ? register_2 : (alu0_opcode_rs1 == 5'h03) ? register_3 : - register_4 ; + register_4 ; @@ -222,53 +234,53 @@ assign alu0_rs2 = (alu0_opcode_rs2 == 5'h00) ? 32'h0 : (alu0_opcode_rs2 == 5'h01) ? register_1 : (alu0_opcode_rs2 == 5'h02) ? register_2 : (alu0_opcode_rs2 == 5'h03) ? register_3 : - register_4 ; + register_4 ; - + //------------------------------------------------------------------------ - - + + assign alu1_rs1 = ( alu0_rd[32]==1'b1 && (alu1_opcode_rs1==alu0_opcode_rd) ) ? alu0_rd[31:0] : (alu1_opcode_rs1 == 5'h00) ? 32'h0 : (alu1_opcode_rs1 == 5'h01) ? register_1 : (alu1_opcode_rs1 == 5'h02) ? register_2 : (alu1_opcode_rs1 == 5'h03) ? register_3 : - register_4 ; - - - + register_4 ; + + + assign alu1_rs2 = ( alu0_rd[32]==1'b1 && (alu1_opcode_rs2==alu0_opcode_rd) ) ? alu0_rd[31:0] : (alu1_opcode_rs2 == 5'h00) ? 32'h0 : (alu1_opcode_rs2 == 5'h01) ? register_1 : (alu1_opcode_rs2 == 5'h02) ? register_2 : (alu1_opcode_rs2 == 5'h03) ? register_3 : - register_4 ; - + register_4 ; + //------------------------------------------------------------------------ - - + + assign alu2_rs1 = ( alu1_rd[32]==1'b1 && (alu2_opcode_rs1==alu1_opcode_rd) ) ? alu1_rd[31:0] : ( alu0_rd[32]==1'b1 && (alu2_opcode_rs1==alu0_opcode_rd) ) ? alu0_rd[31:0] : (alu2_opcode_rs1 == 5'h00) ? 32'h0 : (alu2_opcode_rs1 == 5'h01) ? register_1 : (alu2_opcode_rs1 == 5'h02) ? register_2 : (alu2_opcode_rs1 == 5'h03) ? register_3 : - register_4 ; - - - - + register_4 ; + + + + assign alu2_rs2 = ( alu1_rd[32]==1'b1 && (alu2_opcode_rs2==alu1_opcode_rd) ) ? alu1_rd[31:0] : ( alu0_rd[32]==1'b1 && (alu2_opcode_rs2==alu0_opcode_rd) ) ? alu0_rd[31:0] : (alu2_opcode_rs2 == 5'h00) ? 32'h0 : (alu2_opcode_rs2 == 5'h01) ? register_1 : (alu2_opcode_rs2 == 5'h02) ? register_2 : (alu2_opcode_rs2 == 5'h03) ? register_3 : - register_4 ; - + register_4 ; + //------------------------------------------------------------------------ - - + + assign alu3_rs1 = ( alu2_rd[32]==1'b1 && (alu3_opcode_rs1==alu2_opcode_rd) ) ? alu2_rd[31:0] : ( alu1_rd[32]==1'b1 && (alu3_opcode_rs1==alu1_opcode_rd) ) ? alu1_rd[31:0] : ( alu0_rd[32]==1'b1 && (alu3_opcode_rs1==alu0_opcode_rd) ) ? alu0_rd[31:0] : @@ -276,11 +288,11 @@ assign alu3_rs1 = ( alu2_rd[32]==1'b1 && (alu3_opcode_rs1==alu2_opcode_rd) ) ? a (alu3_opcode_rs1 == 5'h01) ? register_1 : (alu3_opcode_rs1 == 5'h02) ? register_2 : (alu3_opcode_rs1 == 5'h03) ? register_3 : - register_4 ; - - - - + register_4 ; + + + + assign alu3_rs2 = ( alu2_rd[32]==1'b1 && (alu3_opcode_rs2==alu2_opcode_rd) ) ? alu2_rd[31:0] : ( alu1_rd[32]==1'b1 && (alu3_opcode_rs2==alu1_opcode_rd) ) ? alu1_rd[31:0] : ( alu0_rd[32]==1'b1 && (alu3_opcode_rs2==alu0_opcode_rd) ) ? alu0_rd[31:0] : @@ -288,11 +300,11 @@ assign alu3_rs2 = ( alu2_rd[32]==1'b1 && (alu3_opcode_rs2==alu2_opcode_rd) ) ? a (alu3_opcode_rs2 == 5'h01) ? register_1 : (alu3_opcode_rs2 == 5'h02) ? register_2 : (alu3_opcode_rs2 == 5'h03) ? register_3 : - register_4 ; - - + register_4 ; + + - + //------------------------------------------------------------------------------------------ // // Register writebacks @@ -305,73 +317,73 @@ begin : REGISTER_WRITEBACKS if (RST_n==1'b0) begin alu0_load_req_d <= 'h0; - new_pc <= 32'hFFFF_FFFC; + new_pc <= 32'hFFFF_FFFC; end else begin - + if ( (loadstore_stall == 4'b0000 && (alu0_load_req==1'b1 || alu0_store_req==1'b1) ) || (loadstore_stall == 4'b0000 && (alu1_load_req==1'b1 || alu1_store_req==1'b1) ) || (loadstore_stall == 4'b0000 && (alu2_load_req==1'b1 || alu2_store_req==1'b1) ) || - (loadstore_stall == 4'b0000 && (alu3_load_req==1'b1 || alu3_store_req==1'b1) ) ) - begin - loadstore_stall <= 4'b1111; // new_pc_stall for three cycles + (loadstore_stall == 4'b0000 && (alu3_load_req==1'b1 || alu3_store_req==1'b1) ) ) + begin + loadstore_stall <= 4'b1111; // new_pc_stall for three cycles end - else - begin - loadstore_stall <= { 1'b0 , loadstore_stall[3:1] }; + else + begin + loadstore_stall <= { 1'b0 , loadstore_stall[3:1] }; end - - + + // Writeback register file // Only write back registers that have been updated. // Block register updates if a previous alu is taking a branch // if (new_pc_stall==1'b0 && ((loadstore_stall==4'b0001 || alu0_newpc[32]==1'b0) && alu1_newpc[32]==1'b0 && alu2_newpc[32]==1'b0) && alu3_rd[32]==1'b1) begin - case (alu3_opcode_rd) - 5'h01 : register_1 <= alu3_rd[31:0]; - 5'h02 : register_2 <= alu3_rd[31:0]; - 5'h03 : register_3 <= alu3_rd[31:0]; - 5'h04 : register_4 <= alu3_rd[31:0]; - default: ; + case (alu3_opcode_rd) + 5'h01 : register_1 <= alu3_rd[31:0]; + 5'h02 : register_2 <= alu3_rd[31:0]; + 5'h03 : register_3 <= alu3_rd[31:0]; + 5'h04 : register_4 <= alu3_rd[31:0]; + default: ; endcase - end - + end + else if (new_pc_stall==1'b0 && ((loadstore_stall==4'b0001 || alu0_newpc[32]==1'b0) && alu1_newpc[32]==1'b0) && alu2_rd[32]==1'b1) begin - case (alu2_opcode_rd) - 5'h01 : register_1 <= alu2_rd[31:0]; - 5'h02 : register_2 <= alu2_rd[31:0]; - 5'h03 : register_3 <= alu2_rd[31:0]; - 5'h04 : register_4 <= alu2_rd[31:0]; - default: ; + case (alu2_opcode_rd) + 5'h01 : register_1 <= alu2_rd[31:0]; + 5'h02 : register_2 <= alu2_rd[31:0]; + 5'h03 : register_3 <= alu2_rd[31:0]; + 5'h04 : register_4 <= alu2_rd[31:0]; + default: ; endcase - end + end else if (new_pc_stall==1'b0 && (loadstore_stall==4'b0001 || alu0_newpc[32]==1'b0) && alu1_rd[32]==1'b1) begin - case (alu1_opcode_rd) - 5'h01 : register_1 <= alu1_rd[31:0]; - 5'h02 : register_2 <= alu1_rd[31:0]; - 5'h03 : register_3 <= alu1_rd[31:0]; - 5'h04 : register_4 <= alu1_rd[31:0]; - default: ; + case (alu1_opcode_rd) + 5'h01 : register_1 <= alu1_rd[31:0]; + 5'h02 : register_2 <= alu1_rd[31:0]; + 5'h03 : register_3 <= alu1_rd[31:0]; + 5'h04 : register_4 <= alu1_rd[31:0]; + default: ; endcase - end - + end + else if (new_pc_stall==1'b0 && alu0_rd[32]==1'b1) begin - case (alu0_opcode_rd) - 5'h01 : register_1 <= alu0_rd[31:0]; - 5'h02 : register_2 <= alu0_rd[31:0]; - 5'h03 : register_3 <= alu0_rd[31:0]; - 5'h04 : register_4 <= alu0_rd[31:0]; - default: ; + case (alu0_opcode_rd) + 5'h01 : register_1 <= alu0_rd[31:0]; + 5'h02 : register_2 <= alu0_rd[31:0]; + 5'h03 : register_3 <= alu0_rd[31:0]; + 5'h04 : register_4 <= alu0_rd[31:0]; + default: ; endcase - end + end //------------------------------------------------------------------------ @@ -383,33 +395,33 @@ else if ((new_pc_stall==1'b0 && alu0_newpc[32]==1'b1) && loadstore_stall!=4'b0001) begin - new_pc_stall <= 1'b1; - new_pc <= alu0_newpc[31:0]; - end - + new_pc_stall <= 1'b1; + new_pc <= alu0_newpc[31:0]; + end + else if (new_pc_stall==1'b0 && alu1_newpc[32]==1'b1) begin - new_pc_stall <= 1'b1; - new_pc <= alu1_newpc[31:0]; - end - + new_pc_stall <= 1'b1; + new_pc <= alu1_newpc[31:0]; + end + else if (new_pc_stall==1'b0 && alu2_newpc[32]==1'b1) begin - new_pc_stall <= 1'b1; - new_pc <= alu2_newpc[31:0]; - end - + new_pc_stall <= 1'b1; + new_pc <= alu2_newpc[31:0]; + end + else if (new_pc_stall==1'b0 && alu3_newpc[32]==1'b1) begin - new_pc_stall <= 1'b1; - new_pc <= alu3_newpc[31:0]; - end - + new_pc_stall <= 1'b1; + new_pc <= alu3_newpc[31:0]; + end + else - begin - new_pc <= new_pc + 32'h0000_0004; - new_pc_stall <= 1'b0; - end + begin + new_pc <= new_pc + 32'h0000_0004; + new_pc_stall <= 1'b0; + end end end // Register writebacks @@ -422,68 +434,68 @@ end // Register writebacks // //------------------------------------------------------------------------ -MCLR5_alu mclr5_alu0 +MCLR5_alu mclr5_alu0 ( - .OPCODE (alu0_opcode), - .PC (alu0_pc), - .RS1 (alu0_rs1), - .RS2 (alu0_rs2), - .RD (alu0_rd), - .NEWPC (alu0_newpc), - .LOAD_DATA (alu0_load_data), - .STORE_DATA (alu0_store_data), - .LOAD_REQ (alu0_load_req), - .STORE_REQ (alu0_store_req), - .LOAD_STORE_ADDRESS (alu0_load_store_address) + .OPCODE (alu0_opcode), + .PC (alu0_pc), + .RS1 (alu0_rs1), + .RS2 (alu0_rs2), + .RD (alu0_rd), + .NEWPC (alu0_newpc), + .LOAD_DATA (alu0_load_data), + .STORE_DATA (alu0_store_data), + .LOAD_REQ (alu0_load_req), + .STORE_REQ (alu0_store_req), + .LOAD_STORE_ADDRESS (alu0_load_store_address) ); -MCLR5_alu mclr5_alu1 +MCLR5_alu mclr5_alu1 ( - .OPCODE (alu1_opcode), - .PC (alu1_pc), - .RS1 (alu1_rs1), - .RS2 (alu1_rs2), - .RD (alu1_rd), - .NEWPC (alu1_newpc), - .LOAD_DATA (), - .STORE_DATA (), - .LOAD_REQ (alu1_load_req), - .STORE_REQ (alu1_store_req), - .LOAD_STORE_ADDRESS () + .OPCODE (alu1_opcode), + .PC (alu1_pc), + .RS1 (alu1_rs1), + .RS2 (alu1_rs2), + .RD (alu1_rd), + .NEWPC (alu1_newpc), + .LOAD_DATA (), + .STORE_DATA (), + .LOAD_REQ (alu1_load_req), + .STORE_REQ (alu1_store_req), + .LOAD_STORE_ADDRESS () ); -MCLR5_alu mclr5_alu2 +MCLR5_alu mclr5_alu2 ( - .OPCODE (alu2_opcode), - .PC (alu2_pc), - .RS1 (alu2_rs1), - .RS2 (alu2_rs2), - .RD (alu2_rd), - .NEWPC (alu2_newpc), - .LOAD_DATA (), - .STORE_DATA (), - .LOAD_REQ (alu2_load_req), - .STORE_REQ (alu2_store_req), - .LOAD_STORE_ADDRESS () + .OPCODE (alu2_opcode), + .PC (alu2_pc), + .RS1 (alu2_rs1), + .RS2 (alu2_rs2), + .RD (alu2_rd), + .NEWPC (alu2_newpc), + .LOAD_DATA (), + .STORE_DATA (), + .LOAD_REQ (alu2_load_req), + .STORE_REQ (alu2_store_req), + .LOAD_STORE_ADDRESS () ); -MCLR5_alu mclr5_alu3 +MCLR5_alu mclr5_alu3 ( - .OPCODE (alu3_opcode), - .PC (alu3_pc), - .RS1 (alu3_rs1), - .RS2 (alu3_rs2), - .RD (alu3_rd), - .NEWPC (alu3_newpc), - .LOAD_DATA (), - .STORE_DATA (), - .LOAD_REQ (alu3_load_req), - .STORE_REQ (alu3_store_req), - .LOAD_STORE_ADDRESS () + .OPCODE (alu3_opcode), + .PC (alu3_pc), + .RS1 (alu3_rs1), + .RS2 (alu3_rs2), + .RD (alu3_rd), + .NEWPC (alu3_newpc), + .LOAD_DATA (), + .STORE_DATA (), + .LOAD_REQ (alu3_load_req), + .STORE_REQ (alu3_store_req), + .LOAD_STORE_ADDRESS () ); diff --git a/MCLR5/Core/MCLR5_alu.v b/MCLR5/Core/MCLR5_alu.v index cbf8c1d..2612342 100644 --- a/MCLR5/Core/MCLR5_alu.v +++ b/MCLR5/Core/MCLR5_alu.v @@ -14,16 +14,28 @@ // //------------------------------------------------------------------------ // -// Copyright (C) 2018 by Ted Fried info@MicroCoreLabs.com +// Copyright (c) 2020 Ted Fried // -// Permission to use, copy, modify, and distribute this software and its -// documentation for any purpose and without fee is hereby granted, provided -// that the above copyright notice appear in all copies and that both that -// copyright notice and this permission notice appear in supporting documentation. -// This software is provided "as is" without express or implied warranty. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. // //------------------------------------------------------------------------ -// + // Modification History: // ===================== // @@ -115,9 +127,9 @@ assign bge_taken = ($signed(RS1) >= $signed(RS2)) ? 1'b1 : 1'b0; assign bltu_taken = (RS1 < RS2) ? 1'b1 : 1'b0; assign bgeu_taken = (RS1 >= RS2) ? 1'b1 : 1'b0; - + assign pc_adjusted = PC - 4'h4; // Subtracts pipelined PC to the true PC - + assign STORE_DATA = RS2; @@ -126,48 +138,48 @@ always @* begin 32'b???????_?????_?????_???_?????_01101?? : RD = { 1'b1 , {u_immediate[31:12] , 12'b0 } } ; // LUI 32'b???????_?????_?????_???_?????_00101?? : RD = { 1'b1 , PC + {u_immediate[31:12] , 12'b0 } } ; // AUIPC - 32'b???????_?????_?????_???_?????_11011?? : RD = { 1'b1 , PC + 3'h4 } ; // JAL - 32'b???????_?????_?????_???_?????_11001?? : RD = { 1'b1 , PC + 3'h4 } ; // JALR - 32'b???????_?????_?????_000_?????_00100?? : RD = { 1'b1 , RS1 + i_immediate } ; // ADDI - 32'b???????_?????_?????_010_?????_00100?? : RD = { 1'b1 , slti_true } ; // SLTI - 32'b???????_?????_?????_011_?????_00100?? : RD = { 1'b1 , sltiu_true } ; // SLTIU - 32'b???????_?????_?????_100_?????_00100?? : RD = { 1'b1 , RS1 ^ i_immediate } ; // XORI - 32'b???????_?????_?????_110_?????_00100?? : RD = { 1'b1 , RS1 | i_immediate } ; // ORI - 32'b???????_?????_?????_111_?????_00100?? : RD = { 1'b1 , RS1 & i_immediate } ; // ANDI - 32'b???????_?????_?????_001_?????_00100?? : RD = { 1'b1 , slli_result } ; // SLLI - 32'b?0?????_?????_?????_101_?????_00100?? : RD = { 1'b1 , srli_result } ; // SRLI - 32'b?1?????_?????_?????_101_?????_00100?? : RD = { 1'b1 , srai_result } ; // SRAI - 32'b?0?????_?????_?????_000_?????_01100?? : RD = { 1'b1 , RS1 + RS2 } ; // ADD - 32'b?1?????_?????_?????_000_?????_01100?? : RD = { 1'b1 , RS1 - RS2 } ; // SUB - 32'b???????_?????_?????_001_?????_01100?? : RD = { 1'b1 , sll_result } ; // SLL - 32'b???????_?????_?????_010_?????_01100?? : RD = { 1'b1 , slt_true } ; // SLT - 32'b???????_?????_?????_011_?????_01100?? : RD = { 1'b1 , sltu_true } ; // SLTU - 32'b???????_?????_?????_100_?????_01100?? : RD = { 1'b1 , RS1 ^ RS2 } ; // XOR - 32'b?0?????_?????_?????_101_?????_01100?? : RD = { 1'b1 , srl_result } ; // SRL - 32'b?1?????_?????_?????_101_?????_01100?? : RD = { 1'b1 , sra_result } ; // SRA - 32'b???????_?????_?????_110_?????_01100?? : RD = { 1'b1 , RS1 | RS2 } ; // OR - 32'b???????_?????_?????_111_?????_01100?? : RD = { 1'b1 , RS1 & RS2 } ; // AND - - 32'b???????_?????_?????_010_?????_00000?? : RD = { 1'b1 , LOAD_DATA } ; // LW - default : RD = { 1'b0 , 32'h0000_0000 } ; - + 32'b???????_?????_?????_???_?????_11011?? : RD = { 1'b1 , PC + 3'h4 } ; // JAL + 32'b???????_?????_?????_???_?????_11001?? : RD = { 1'b1 , PC + 3'h4 } ; // JALR + 32'b???????_?????_?????_000_?????_00100?? : RD = { 1'b1 , RS1 + i_immediate } ; // ADDI + 32'b???????_?????_?????_010_?????_00100?? : RD = { 1'b1 , slti_true } ; // SLTI + 32'b???????_?????_?????_011_?????_00100?? : RD = { 1'b1 , sltiu_true } ; // SLTIU + 32'b???????_?????_?????_100_?????_00100?? : RD = { 1'b1 , RS1 ^ i_immediate } ; // XORI + 32'b???????_?????_?????_110_?????_00100?? : RD = { 1'b1 , RS1 | i_immediate } ; // ORI + 32'b???????_?????_?????_111_?????_00100?? : RD = { 1'b1 , RS1 & i_immediate } ; // ANDI + 32'b???????_?????_?????_001_?????_00100?? : RD = { 1'b1 , slli_result } ; // SLLI + 32'b?0?????_?????_?????_101_?????_00100?? : RD = { 1'b1 , srli_result } ; // SRLI + 32'b?1?????_?????_?????_101_?????_00100?? : RD = { 1'b1 , srai_result } ; // SRAI + 32'b?0?????_?????_?????_000_?????_01100?? : RD = { 1'b1 , RS1 + RS2 } ; // ADD + 32'b?1?????_?????_?????_000_?????_01100?? : RD = { 1'b1 , RS1 - RS2 } ; // SUB + 32'b???????_?????_?????_001_?????_01100?? : RD = { 1'b1 , sll_result } ; // SLL + 32'b???????_?????_?????_010_?????_01100?? : RD = { 1'b1 , slt_true } ; // SLT + 32'b???????_?????_?????_011_?????_01100?? : RD = { 1'b1 , sltu_true } ; // SLTU + 32'b???????_?????_?????_100_?????_01100?? : RD = { 1'b1 , RS1 ^ RS2 } ; // XOR + 32'b?0?????_?????_?????_101_?????_01100?? : RD = { 1'b1 , srl_result } ; // SRL + 32'b?1?????_?????_?????_101_?????_01100?? : RD = { 1'b1 , sra_result } ; // SRA + 32'b???????_?????_?????_110_?????_01100?? : RD = { 1'b1 , RS1 | RS2 } ; // OR + 32'b???????_?????_?????_111_?????_01100?? : RD = { 1'b1 , RS1 & RS2 } ; // AND + + 32'b???????_?????_?????_010_?????_00000?? : RD = { 1'b1 , LOAD_DATA } ; // LW + default : RD = { 1'b0 , 32'h0000_0000 } ; + endcase casex (OPCODE) - 32'b???????_?????_?????_010_?????_00000?? : LOAD_STORE_ADDRESS = RS1 + i_immediate ; // Loads - 32'b???????_?????_?????_010_?????_01000?? : LOAD_STORE_ADDRESS = RS1 + s_immediate ; // Stores - default : ; + 32'b???????_?????_?????_010_?????_00000?? : LOAD_STORE_ADDRESS = RS1 + i_immediate ; // Loads + 32'b???????_?????_?????_010_?????_01000?? : LOAD_STORE_ADDRESS = RS1 + s_immediate ; // Stores + default : ; endcase casex (OPCODE) 32'b???????_?????_?????_010_?????_00000?? : LOAD_REQ = 1'b1 ; - 32'b???????_?????_?????_010_?????_01000?? : STORE_REQ = 1'b1 ; + 32'b???????_?????_?????_010_?????_01000?? : STORE_REQ = 1'b1 ; default : begin LOAD_REQ = 1'b0 ; STORE_REQ = 1'b0; end - + endcase @@ -188,9 +200,9 @@ always @* begin 32'b???????_?????_?????_110_?????_11000?? : if (bltu_taken == 1'b1) NEWPC = { 1'b1 , pc_adjusted + b_immediate } ; // BLTU 32'b???????_?????_?????_111_?????_11000?? : if (bgeu_taken == 1'b1) NEWPC = { 1'b1 , pc_adjusted + b_immediate } ; // BGEU - - default : NEWPC = { 1'b0 , 32'h0000_0000 } ; // No Branch Taken - + + default : NEWPC = { 1'b0 , 32'h0000_0000 } ; // No Branch Taken + endcase @@ -199,7 +211,7 @@ always @* begin end - + diff --git a/Wheelwriter/Core/mclwr1.v b/Wheelwriter/Core/mclwr1.v index 22e0834..a0c4fa5 100644 --- a/Wheelwriter/Core/mclwr1.v +++ b/Wheelwriter/Core/mclwr1.v @@ -20,6 +20,28 @@ // // //------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ `timescale 1ns/100ps @@ -32,10 +54,10 @@ module mclwr1 output UART_TX, input UART_RX, - + output UART_TX2, input UART_RX2, - + output[8:0] SNOOP_OUT ); @@ -277,14 +299,14 @@ assign ibm_byte = always @(posedge clk_int) begin - uart_rx_d <= UART_RX & UART_RX2; // Either of the two serial ports can send data + uart_rx_d <= UART_RX & UART_RX2; // Either of the two serial ports can send data uart_rx_d1 <= uart_rx_d; uart_rx_d2 <= uart_rx_d1; rx_count <= rx_count + 1'b1; case (rx_count) - 16'h0000: if (uart_rx_d2!=1'b0) // Look for Start Bit + 16'h0000: if (uart_rx_d2!=1'b0) // Look for Start Bit begin rx_count <= 'h0; end diff --git a/Wheelwriter/Core/mclwr1.v.bak b/Wheelwriter/Core/mclwr1.v.bak new file mode 100644 index 0000000..22e0834 --- /dev/null +++ b/Wheelwriter/Core/mclwr1.v.bak @@ -0,0 +1,578 @@ +// +// +// File Name : mclwr1.v +// Author : Ted Fried, MicroCore Labs +// Creation : 11/3/2019 +// Code Type : Synthesizable +// +// Description: +// ============ +// +// FPGA version of the Printer Option for the IBM Wheelwriter +// +//------------------------------------------------------------------------ +// +// Version History: +// ================ +// +// Revision 1 11/3/19 +// Initial revision +// +// +//------------------------------------------------------------------------ + +`timescale 1ns/100ps + + + +module mclwr1 + ( + inout IBM_BUS, + output BUFFER_DIR, + + output UART_TX, + input UART_RX, + + output UART_TX2, + input UART_RX2, + + output[8:0] SNOOP_OUT + + ); + + +//------------------------------------------------------------------------ + + +// Internal Signals +reg rx_fifo_wr = 'h0; +reg rx_fifo_rd = 'h0; +reg tx_fifo_wr = 'h0; +reg tx_fifo_rd = 'h0; +reg ibm_clock = 'h0; +reg ibm_load_tx = 'h0; +reg ibm_clock_d = 'h0; +reg uart_rx_d = 1'b1; +reg uart_rx_d1 = 1'b1; +reg uart_rx_d2 = 1'b1; +reg uart_clock = 'h0; +reg uart_clock_d = 'h0; +reg ibm_bus_d = 1'b1; +reg ibm_bus_d1 = 1'b1; +reg ibm_bus_d2 = 1'b1; +reg rx_fifo_almost_full_d ='h0; +reg [8:0] uart_prescaler ='h0; +reg [10:0] uart_tx_shiftout = 11'b11111111111; +reg [15:0] rx_count = 'h0; +reg [7:0] main_count = 'h0; +reg [15:0] tx_bytes = 'h0; +reg [15:0] ibm_count = 'h0; +reg [7:0] prescaler = 'h0; +reg [8:0] tx_fifo_data_in = 'h0; +reg [9:0] ibm_shift_out = 10'b1111111111; +reg [7:0] uart_rx_byte = 'h0; +reg [15:0] snoop_count = 'h0; +reg [8:0] snoop_byte = 9'b111111111; +reg [8:0] snoop_byte_all = 9'b111111111; +wire clk_int; +wire tx_fifo_full; +wire tx_fifo_empty; +wire rx_fifo_full; +wire rx_fifo_almost_full; +wire rx_fifo_empty; +wire [8:0] rx_fifo_data_out; +wire [8:0] tx_fifo_data_out; +wire [8:0] ibm_byte; + + +//------------------------------------------------------------------------ +// OSCH - Internal clock oscillator for Lattice XO2 +//------------------------------------------------------------------------ + +defparam OSCILLATOR_INST.NOM_FREQ = "2.22"; +OSCH OSCILLATOR_INST + ( + .STDBY (1'b0), + .OSC (clk_int), + .SEDSTDBY () + ); + +//------------------------------------------------------------------------ +// RX FIFO - Holds 1K characters from the UART +//------------------------------------------------------------------------ + +rx_fifo RX_FIFO + ( + .Reset (1'b0 ), + .RPReset (1'b0 ), + + .WrClock (clk_int ), + .Data (ibm_byte), + .WrEn (rx_fifo_wr ), + .Full (rx_fifo_full ), + .AlmostFull (rx_fifo_almost_full ), + + .RdClock (clk_int ), + .Q (rx_fifo_data_out ), + .RdEn (rx_fifo_rd), + .Empty (rx_fifo_empty ), + .AlmostEmpty( ) + ); + +//------------------------------------------------------------------------ +// TX FIFO - Holds 1K commands to be sent to the IBM Wheelwriter +//------------------------------------------------------------------------ + +rx_fifo TX_FIFO + ( + .Reset (1'b0 ), + .RPReset (1'b0 ), + + .WrClock (clk_int ), + .Data (tx_fifo_data_in ), + .WrEn (tx_fifo_wr ), + .Full ( ), + .AlmostFull ( ), + + .RdClock (clk_int ), + .Q (tx_fifo_data_out ), + .RdEn (tx_fifo_rd), + .Empty (tx_fifo_empty ), + .AlmostEmpty( ) + ); + + +//------------------------------------------------------------------------ +// +// Combinationals +// +//------------------------------------------------------------------------ + +assign SNOOP_OUT = {8'h0 , rx_fifo_full, rx_fifo_almost_full }; +//assign SNOOP_OUT = snoop_byte_all; +//assign SNOOP_OUT = rx_fifo_data_out[7:0]; +//assign SNOOP_OUT = uart_rx_byte[7:0]; + +assign UART_TX = uart_tx_shiftout[0]; +assign UART_TX2 = uart_tx_shiftout[0]; + +assign BUFFER_DIR = ~ibm_shift_out[0]; + +assign IBM_BUS = (ibm_shift_out[0]==1'b0) ? 1'b0 : 1'bZ; // open collector + +assign ibm_byte = + (uart_rx_byte==8'h0D) ? 9'h099 : // Carriage Return + + (uart_rx_byte==8'h20) ? 9'h000 : // Space + (uart_rx_byte==8'h21) ? 9'h049 : // ! + (uart_rx_byte==8'h22) ? 9'h04b : // " + (uart_rx_byte==8'h23) ? 9'h038 : // # + (uart_rx_byte==8'h24) ? 9'h037 : // $ + (uart_rx_byte==8'h25) ? 9'h039 : // % + (uart_rx_byte==8'h26) ? 9'h03F : // & + (uart_rx_byte==8'h27) ? 9'h04C : // ` + (uart_rx_byte==8'h28) ? 9'h023 : // ( + (uart_rx_byte==8'h29) ? 9'h016 : // ) + (uart_rx_byte==8'h2A) ? 9'h036 : // * + (uart_rx_byte==8'h2B) ? 9'h03B : // + + (uart_rx_byte==8'h2C) ? 9'h00C : // , + (uart_rx_byte==8'h2D) ? 9'h00E : // - + (uart_rx_byte==8'h2E) ? 9'h057 : // . + (uart_rx_byte==8'h2F) ? 9'h028 : // / + + (uart_rx_byte==8'h30) ? 9'h030 : // 0 + (uart_rx_byte==8'h31) ? 9'h02E : // 1 + (uart_rx_byte==8'h32) ? 9'h02F : // 2 + (uart_rx_byte==8'h33) ? 9'h02C : // 3 + (uart_rx_byte==8'h34) ? 9'h032 : // 4 + (uart_rx_byte==8'h35) ? 9'h031 : // 5 + (uart_rx_byte==8'h36) ? 9'h033 : // 6 + (uart_rx_byte==8'h37) ? 9'h035 : // 7 + (uart_rx_byte==8'h38) ? 9'h034 : // 8 + (uart_rx_byte==8'h39) ? 9'h02A : // 9 + (uart_rx_byte==8'h3A) ? 9'h04E : // : + (uart_rx_byte==8'h3B) ? 9'h050 : // ; + // (uart_rx_byte==8'h3C) ? 9'h000 : // < + (uart_rx_byte==8'h3D) ? 9'h04D : // = + // (uart_rx_byte==8'h3E) ? 9'h000 : // > + (uart_rx_byte==8'h3F) ? 9'h04A : // ? + + (uart_rx_byte==8'h40) ? 9'h03D : // @ + (uart_rx_byte==8'h41) ? 9'h020 : // A + (uart_rx_byte==8'h42) ? 9'h012 : // B + (uart_rx_byte==8'h43) ? 9'h01B : // C + (uart_rx_byte==8'h44) ? 9'h01D : // D + (uart_rx_byte==8'h45) ? 9'h01E : // E + (uart_rx_byte==8'h46) ? 9'h011 : // F + (uart_rx_byte==8'h47) ? 9'h00F : // G + (uart_rx_byte==8'h48) ? 9'h014 : // H + (uart_rx_byte==8'h49) ? 9'h01F : // I + (uart_rx_byte==8'h4A) ? 9'h021 : // J + (uart_rx_byte==8'h4B) ? 9'h02B : // K + (uart_rx_byte==8'h4C) ? 9'h018 : // L + (uart_rx_byte==8'h4D) ? 9'h024 : // M + (uart_rx_byte==8'h4E) ? 9'h01A : // N + (uart_rx_byte==8'h4F) ? 9'h022 : // O + + (uart_rx_byte==8'h50) ? 9'h015 : // P + (uart_rx_byte==8'h51) ? 9'h03E : // Q + (uart_rx_byte==8'h52) ? 9'h017 : // R + (uart_rx_byte==8'h53) ? 9'h019 : // S + (uart_rx_byte==8'h54) ? 9'h01C : // T + (uart_rx_byte==8'h55) ? 9'h010 : // U + (uart_rx_byte==8'h56) ? 9'h00D : // V + (uart_rx_byte==8'h57) ? 9'h029 : // W + (uart_rx_byte==8'h58) ? 9'h02D : // X + (uart_rx_byte==8'h59) ? 9'h026 : // Y + (uart_rx_byte==8'h5A) ? 9'h013 : // Z + (uart_rx_byte==8'h5B) ? 9'h041 : // [ + // (uart_rx_byte==8'h5C) ? 9'h000 : // + (uart_rx_byte==8'h5D) ? 9'h040 : // ] + // (uart_rx_byte==8'h5E) ? 9'h000 : // ^ + (uart_rx_byte==8'h5F) ? 9'h04F : // _ + + (uart_rx_byte==8'h60) ? 9'h000 : // ` + (uart_rx_byte==8'h61) ? 9'h001 : // a + (uart_rx_byte==8'h62) ? 9'h059 : // b + (uart_rx_byte==8'h63) ? 9'h005 : // c + (uart_rx_byte==8'h64) ? 9'h007 : // d + (uart_rx_byte==8'h65) ? 9'h060 : // e + (uart_rx_byte==8'h66) ? 9'h00A : // f + (uart_rx_byte==8'h67) ? 9'h05A : // g + (uart_rx_byte==8'h68) ? 9'h008 : // h + (uart_rx_byte==8'h69) ? 9'h05D : // i + (uart_rx_byte==8'h6A) ? 9'h056 : // j + (uart_rx_byte==8'h6B) ? 9'h00B : // k + (uart_rx_byte==8'h6C) ? 9'h009 : // l + (uart_rx_byte==8'h6D) ? 9'h004 : // m + (uart_rx_byte==8'h6E) ? 9'h002 : // n + (uart_rx_byte==8'h6F) ? 9'h05F : // o + + (uart_rx_byte==8'h70) ? 9'h05C : // p + (uart_rx_byte==8'h71) ? 9'h052 : // q + (uart_rx_byte==8'h72) ? 9'h003 : // r + (uart_rx_byte==8'h73) ? 9'h006 : // s + (uart_rx_byte==8'h74) ? 9'h05E : // t + (uart_rx_byte==8'h75) ? 9'h05B : // u + (uart_rx_byte==8'h76) ? 9'h053 : // v + (uart_rx_byte==8'h77) ? 9'h055 : // w + (uart_rx_byte==8'h78) ? 9'h051 : // x + (uart_rx_byte==8'h79) ? 9'h058 : // y + (uart_rx_byte==8'h7A) ? 9'h054 : // z + //(uart_rx_byte==8'h7B) ? 9'h000 : // { + //(uart_rx_byte==8'h7C) ? 9'h000 : // | + //(uart_rx_byte==8'h7D) ? 9'h000 : // } + //(uart_rx_byte==8'h7E) ? 9'h000 : // ~ + //(uart_rx_byte==8'h7F) ? 9'h000 : // DEL + + 9'h000; + + +//------------------------------------------------------------------------ +// +// UART RX Controller +// +//------------------------------------------------------------------------ + +always @(posedge clk_int) + begin + + uart_rx_d <= UART_RX & UART_RX2; // Either of the two serial ports can send data + uart_rx_d1 <= uart_rx_d; + uart_rx_d2 <= uart_rx_d1; + + rx_count <= rx_count + 1'b1; + + case (rx_count) + 16'h0000: if (uart_rx_d2!=1'b0) // Look for Start Bit + begin + rx_count <= 'h0; + end + 16'h0100: uart_rx_byte[7:0] <= 8'h00; + 16'h019E: uart_rx_byte[0] <= uart_rx_d2; + 16'h027F: uart_rx_byte[1] <= uart_rx_d2; + 16'h0367: uart_rx_byte[2] <= uart_rx_d2; + 16'h0443: uart_rx_byte[3] <= uart_rx_d2; + 16'h0532: uart_rx_byte[4] <= uart_rx_d2; + 16'h0611: uart_rx_byte[5] <= uart_rx_d2; + 16'h06F9: uart_rx_byte[6] <= uart_rx_d2; + 16'h07DC: uart_rx_byte[7] <= uart_rx_d2; + 16'h07DD: rx_fifo_wr <= 1'b1; + 16'h07DE: rx_fifo_wr <= 1'b0; + 16'h08D0: rx_count <= 'h0; + default: ; + endcase + end + + +//------------------------------------------------------------------------ +// +// UART TX Controller +// +//------------------------------------------------------------------------ + +always @(posedge clk_int) + begin + + uart_prescaler <= uart_prescaler + 1'b1; + if (uart_prescaler[7:0]==8'h72) // 9600 baud + begin + uart_clock <= ~ uart_clock; + uart_prescaler <= 'h0; + end + + uart_clock_d <= uart_clock; + + + rx_fifo_almost_full_d <= rx_fifo_almost_full; + + if (rx_fifo_almost_full_d==1'b0 && rx_fifo_almost_full==1'b1) + begin + uart_tx_shiftout <= 11'b1_00010011_01; // XOFF + end + else if (rx_fifo_almost_full_d==1'b1 && rx_fifo_almost_full==1'b0) + begin + uart_tx_shiftout <= 11'b1_00010001_01; // XON + end + else + begin + if (uart_clock_d==1'b0 && uart_clock==1'b1) + begin + uart_tx_shiftout[10:0] <= {1'b1 , uart_tx_shiftout[10:1] }; + end + end + + + end + +//------------------------------------------------------------------------ +// +// Main Controller +// +//------------------------------------------------------------------------ + + +always @(posedge clk_int) + begin + + main_count <= main_count + 1'b1; + + case (main_count) + 8'h00: if (rx_fifo_empty==1'b1) // Poll the rx_fifo for a new character to send + begin + main_count <= 'h0; + end + 8'h01: rx_fifo_rd <= 1'b1; // Strobe the rx_fifo to get the next character + 8'h02: rx_fifo_rd <= 1'b0; + + 8'h03: if (rx_fifo_data_out[7:0]=='h99) // Check character for carriage return + begin + main_count <= 8'h10; + end + + 8'h04: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h121; end // Fill the TX_FIFO with the commands to send a character + 8'h05: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h00B; end + 8'h06: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h0A6; end // Delay + 8'h07: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h121; end + 8'h08: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h003; end + 8'h09: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= rx_fifo_data_out; end // Letter to send + 8'h0A: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h00A; end + 8'h0B: tx_fifo_wr <= 1'b0; + 8'h0C: begin + if (tx_bytes==16'h8000) + begin + tx_bytes <= 16'h000A; + end + else + begin + tx_bytes <= tx_bytes + 4'hA; // Keep track of how many characters have been printed so far for this row + end + end + 8'h0D: if (tx_fifo_empty==1'b0) // Dont add to the TX_FIFO until previous command sequence has completed + begin + main_count <= main_count; + end + 8'h0E: main_count <= 'h0; + + + 8'h10: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h121; end // Fill the TX_FIFO with the carriage return commands + 8'h11: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h00B; end + 8'h12: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h0A6; end // Delay + 8'h13: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h121; end + 8'h14: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h00D; end + 8'h15: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h007; end + 8'h16: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h121; end + 8'h17: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h006; end + 8'h18: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= { 1'b0 , tx_bytes[15:8] }; end + 8'h19: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= { 1'b0 , tx_bytes[07:0] }; end + 8'h1A: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h0A6; end // Delay + 8'h1B: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h121; end + 8'h1C: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h005; end + 8'h1D: begin tx_fifo_wr <= 1'b1; tx_fifo_data_in <= 9'h090; end + 8'h1E: tx_fifo_wr <= 1'b0; + 8'h1F: tx_bytes <= 16'h8000; // Zero out the character count for this row + 8'h20: if (tx_fifo_empty==1'b0) // Dont add to the TX_FIFO until previous command sequence has completed + begin + main_count <= main_count; + end + 8'h21: main_count <= 'h0; + + default: ; + endcase + end + +//------------------------------------------------------------------------ +// +// IBM Bus Controller +// +//------------------------------------------------------------------------ + +always @(posedge clk_int) + begin + + ibm_bus_d <= IBM_BUS; + ibm_bus_d1 <= ibm_bus_d; + ibm_bus_d2 <= ibm_bus_d1; + + prescaler <= prescaler + 1'b1; + + if (prescaler[7:0]==8'h05) // IBM Serial Bus clock period = 5.34uS + begin + ibm_clock <= ~ ibm_clock; + prescaler <= 'h0; + end + + ibm_clock_d <= ibm_clock; + + // IBM Serial Bus shift register + if (ibm_load_tx==1'b1) + begin + ibm_shift_out[9:0] <= { tx_fifo_data_out[8:0] , 1'b0 }; + end + else if (ibm_clock_d==1'b0 && ibm_clock==1'b1) + begin + ibm_shift_out[9:0] <= { 1'b1 , ibm_shift_out[9:1] }; + end + + + + ibm_count <= ibm_count + 1'b1; + + case (ibm_count) + 16'h0000: if (tx_fifo_empty==1'b1) // Poll the tx_fifo + begin + ibm_count <= 'h0; + end + 16'h0001: tx_fifo_rd <= 1'b1; // Strobe the tx_fifo to get the next character to print + 16'h0002: tx_fifo_rd <= 1'b0; + + 16'h0003: if (tx_fifo_data_out[7:0]==8'hA6) // Check character for the DELAY command byte + begin + ibm_count <= 16'h0600; + end + + 16'h0004: if (ibm_clock_d==1'b0 && ibm_clock==1'b1) + begin + ibm_load_tx <= 1'b1; + end + else + begin + ibm_count <= ibm_count; + end + + 16'h0005: ibm_load_tx <= 1'b0; + + + + // + // Wait n clocks for end of the sequence to shift out + // + + 16'h007A: if (ibm_bus_d2!=1'b1) // Check for ACK from IBM + begin + ibm_count <= ibm_count; + end + 16'h007C: if (ibm_bus_d2!=1'b0) // Check for ACK from IBM + begin + ibm_count <= ibm_count; + end + 16'h007E: if (ibm_bus_d2!=1'b1) // Check for ACK from IBM + begin + ibm_count <= ibm_count; + end + 16'h00EC: ibm_count <= 'h0; + + + 16'h0600: ; // Start of Delay + 16'h1050: ibm_count <= 'h0; // End of Delay + + + default: ; + endcase + +end + + + + +//------------------------------------------------------------------------ +// +// IBM Bus Snooper +// +//------------------------------------------------------------------------ + + +always @(posedge clk_int) + begin + + snoop_count <= snoop_count + 1'b1; + + case (snoop_count) + 16'h0000: if (ibm_bus_d2!=1'b0) + begin + snoop_count <= 'h0; + end + 16'h0012: snoop_byte[0] <= ibm_bus_d2; + 16'h001E: snoop_byte[1] <= ibm_bus_d2; + 16'h002A: snoop_byte[2] <= ibm_bus_d2; + 16'h0036: snoop_byte[3] <= ibm_bus_d2; + + 16'h0041: snoop_byte[4] <= ibm_bus_d2; + 16'h004D: snoop_byte[5] <= ibm_bus_d2; + 16'h0059: snoop_byte[6] <= ibm_bus_d2; + 16'h0065: snoop_byte[7] <= ibm_bus_d2; + + 16'h0071: snoop_byte[8] <= ibm_bus_d2; + 16'h0072: snoop_byte_all <= snoop_byte; + + 16'h0075: if (ibm_bus_d2!=1'b1) + begin + snoop_count <= snoop_count; + end + 16'h0077: if (ibm_bus_d2!=1'b0) + begin + snoop_count <= snoop_count; + end + 16'h0079: if (ibm_bus_d2!=1'b1) + begin + snoop_count <= snoop_count; + end + 16'h009D: snoop_count <= 'h0; + + default: ; + endcase + end + + + + + +//------------------------------------------------------------------------ + +endmodule + + +//------------------------------------------------------------------------ + + + diff --git a/Wheelwriter2/wheel.c b/Wheelwriter2/wheel.c index c4d4624..75c1495 100644 --- a/Wheelwriter2/wheel.c +++ b/Wheelwriter2/wheel.c @@ -32,6 +32,28 @@ // //------------------------------------------------------------------------ //------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ byte array_in_pointer=0; @@ -162,4 +184,4 @@ void loop() } } - \ No newline at end of file +