1
0
mirror of https://github.com/pConst/basic_verilog.git synced 2025-01-28 07:02:55 +08:00

Removed obsolete files. Updated scripts

This commit is contained in:
Konstantin Pavlov 2022-06-01 17:53:44 +03:00
parent 5bba1d2b7e
commit 2388fd3d54
13 changed files with 18 additions and 1713 deletions

View File

@ -1,97 +0,0 @@
//--------------------------------------------------------------------------------
// NDivide.v
// Konstantin Pavlov, pavlovconst@gmail.com
//--------------------------------------------------------------------------------
// INFO --------------------------------------------------------------------------------
// Primitive integer divider
// Unsigned inputs, y should be < or == x
/* --- INSTANTIATION TEMPLATE BEGIN ---
NDivide ND1 (
.clk( ),
.nrst( 1'b1 ),
.d_start( ),
.d_busy( ),
.d_done( ),
.x( ),
.y( ),
.q( ),
.r( )
);
defparam ND1.XBITS = 32;
defparam ND1.YBITS = 32;
--- INSTANTIATION TEMPLATE END ---*/
module NDivide(clk,nrst,d_start,d_busy,d_done,x,y,q,r);
parameter XBITS = 32;
parameter YBITS = 32;
input wire clk;
input wire nrst;
input wire d_start;
output reg d_busy = 0;
output wire d_done;
input wire [(XBITS-1):0] x;
input wire [(YBITS-1):0] y;
output reg [(XBITS-1):0] q = 0;
output wire [(YBITS-1):0] r;
reg [(XBITS+YBITS-1):0] x_buf = 0;
reg [(YBITS-1):0] y_buf = 0;
reg [31:0] i = 0;
wire [(YBITS+XBITS-1):0] shift_y;
wire [(YBITS+XBITS-1):0] x_buf_sub_shift_y;
assign
shift_y[(YBITS+XBITS-1):0] = y_buf[(YBITS-1):0] << i[31:0],
x_buf_sub_shift_y[(YBITS+XBITS-1):0] = x_buf[(YBITS+XBITS-1):0] - shift_y[(YBITS+XBITS-1):0];
always @ (posedge clk) begin
if (~nrst) begin
q[(XBITS-1):0] <= 0;
i[31:0] <= 0;
x_buf[(XBITS+YBITS-1):0] <= 0;
y_buf[(YBITS-1):0] <= 0;
d_busy <= 0;
end else begin
if (~d_busy) begin
if (d_start) begin
i[31:0] <= (XBITS-1);
x_buf[(XBITS+YBITS-1):0] <= x[(XBITS-1):0];
y_buf[(YBITS-1):0] <= y[(YBITS-1):0];
d_busy <= 1;
end // d_start
end else begin
// this condition means crossing of zero boundary
if (x_buf_sub_shift_y[(YBITS+XBITS-1):0] > x_buf[(XBITS+YBITS-1):0]) begin
q[i[31:0]] <= 0;
end else begin
q[i[31:0]] <= 1;
x_buf[(XBITS+YBITS-1):0] <= x_buf_sub_shift_y[(YBITS+XBITS-1):0];
end
if (i[31:0] != 0) begin
i[31:0] <= i[31:0] - 1;
end else begin
d_busy <= 0;
end
end // ~d_busy
end // ~nrst
end
assign
d_done = d_busy && ( i[31:0] == 0 ),
r[(XBITS-1):0] = x_buf[(XBITS+YBITS-1):0];
endmodule

109
UartRx.v
View File

@ -1,109 +0,0 @@
//--------------------------------------------------------------------------------
// UartRx.v
// Konstantin Pavlov, pavlovconst@gmail.com
//--------------------------------------------------------------------------------
// INFO --------------------------------------------------------------------------------
// Straightforward yet simple UART receiver implementation for FPGA written in Verilog
// Expects at least one stop bit
// Features continuous data aquisition at BAUD levels up to CLK_HZ / 2
// Features early asynchronous 'busy' reset
CAUTION !
THIS CODE IS OBSOLETE NOW. PLEASE USE "uart_rx.sv" VERSION INSTEAD
/* --- INSTANTIATION TEMPLATE BEGIN ---
UartRx UR1 (
.clk(),
.nrst( 1'b1 ),
.rx_data(),
.rx_busy(),
.rx_done(),
.rx_err(),
.rxd()
);
defparam UR1.CLK_HZ = 200_000_000;
defparam UR1.BAUD = 9600; // max. BAUD is CLK_HZ / 2
--- INSTANTIATION TEMPLATE END ---*/
module UartRx(clk, nrst, rx_data, rx_busy, rx_done, rx_err, rxd);
parameter CLK_HZ = 200_000_000;
parameter BAUD = 9600;
parameter BAUD_DIVISOR_2 = CLK_HZ / BAUD / 2;
input wire clk;
input wire nrst;
output reg [7:0] rx_data = 0;
reg rx_data_9th_bit = 0; // {rx_data[7:0],rx_data_9th_bit} is actually a shift register
output reg rx_busy = 0;
output wire rx_done; // read strobe
output wire rx_err;
input wire rxd;
StaticDelay SD (
.clk(clk),
.nrst(nrst),
.in(rxd),
.out(s_rxd) // Synchronized rxd
);
defparam SD.LENGTH = 2;
defparam SD.WIDTH = 1;
reg rxd_prev = 0;
always @ (posedge clk) begin
if (~nrst) begin
rxd_prev <= 0;
end else begin
rxd_prev <= s_rxd;
end
end
wire start_bit_strobe = ~s_rxd & rxd_prev;
reg [15:0] rx_sample_cntr = (BAUD_DIVISOR_2 - 1);
wire rx_do_sample = (rx_sample_cntr[15:0] == 0);
always @ (posedge clk) begin
if (~nrst) begin
rx_busy <= 0;
end else begin
if (~rx_busy) begin
if (start_bit_strobe) begin
rx_sample_cntr[15:0] <= (BAUD_DIVISOR_2 * 3 - 1); // wait for 1,5-bit period till next sample
{rx_data[7:0],rx_data_9th_bit} <= 9'b100000000;
rx_busy <= 1;
end // start_bit_strobe
end else begin
if (rx_sample_cntr[15:0] == 0) begin
rx_sample_cntr[15:0] <= (BAUD_DIVISOR_2 * 2 - 1); // wait for 1-bit-period till next sample
end else begin
rx_sample_cntr[15:0] <= rx_sample_cntr[15:0] - 1; // counting and sampling only when 'busy'
end
if (rx_do_sample) begin
if (rx_data_9th_bit == 1) begin
rx_busy <= 0; // early asynchronous 'busy' reset
end else begin
{rx_data[7:0],rx_data_9th_bit} <= {s_rxd, rx_data[7:0]};
end //
end // rx_do_sample
end // ~rx_busy
end // ~nrst
end
assign
rx_done = rx_data_9th_bit && rx_do_sample && s_rxd, // rx_done and rx_busy fall simultaneously
rx_err = rx_data_9th_bit && rx_do_sample && ~s_rxd;
endmodule

View File

@ -1,83 +0,0 @@
//--------------------------------------------------------------------------------
// UartRxExtreme.v
// Konstantin Pavlov, pavlovconst@gmail.com
//--------------------------------------------------------------------------------
// INFO --------------------------------------------------------------------------------
// Extreme minimal UART receiver optimized for 20MHz/115200 data rate
//
// CAUTION:
// optimized for 20MHz/115200
// rx_sample_cntr[7:0] does never stop, but reloads on sequense start condition
// initial rx_sample_cntr[7:0] value has been made 255 instead of 257 to save one precious counter register
// rx_busy and rx_done fall simultaneously 0,5 bit before stop bit time end
/* --- INSTANTIATION TEMPLATE BEGIN ---
UartRxExtreme UR1 (
.clk(),
.rx_data(),
.rx_busy(),
.rx_done(),
.rxd()
);
--- INSTANTIATION TEMPLATE END ---*/
module UartRxExtreme(clk, rx_data, rx_busy, rx_done, rxd);
input wire clk;
output reg [7:0] rx_data = 0;
reg rx_data_9th_bit = 0; // {rx_data[7:0],rx_data_9th_bit} is actually a shift register
output reg rx_busy = 0; // sequence control is done by rx_busy and unique high logic state of rx_data_9th_bit register
output wire rx_done;
input wire rxd;
// Falling edge detector
reg rxd_prev = 0;
always @ (posedge clk) begin
rxd_prev <= rxd;
end
wire start_bit_strobe = ~rx_busy && (~rxd & rxd_prev);
// Sample counter
reg [7:0] rx_sample_cntr = 0;
always @ (posedge clk) begin
if (start_bit_strobe) begin
rx_sample_cntr[7:0] <= (86 * 3 - 1) - 2;
end else begin
if (rx_sample_cntr[7:0] == 0) begin
rx_sample_cntr[7:0] <= (86 * 2 - 1);
end else begin
rx_sample_cntr[7:0] <= rx_sample_cntr[7:0] - 1;
end // rx_sample_cntr
end // start_bit_strobe
end
wire rx_do_sample = (rx_sample_cntr[7:0] == 0);
// Data shifting
always @ (posedge clk) begin
if (start_bit_strobe) begin
{rx_data[7:0],rx_data_9th_bit} <= 9'b100000000;
rx_busy <= 1;
end // start_bit_strobe
if (rx_busy && rx_do_sample) begin
if (rx_data_9th_bit) begin
rx_busy <= 0;
end else begin
{rx_data[7:0],rx_data_9th_bit} <= {rxd,rx_data[7:0]};
end
end // (rx_busy && rx_do_sample)
end
assign
rx_done = (rx_busy && rx_do_sample && rx_data_9th_bit) && rxd;
endmodule

View File

@ -1,88 +0,0 @@
//--------------------------------------------------------------------------------
// UartTx.v
// Konstantin Pavlov, pavlovconst@gmail.com
//--------------------------------------------------------------------------------
// INFO --------------------------------------------------------------------------------
// Straightforward yet simple UART transmitter implementation for FPGA written in Verilog
// One stop bit setting is hardcoded
// Features continuous data output at BAUD levels up to CLK_HZ / 2
// Features early asynchronous 'busy' set and reset to gain time to prepare new data
// If multiple UartTX instances should be inferred - make tx_sample_cntr logic common for all TX instances for effective chip area usage
CAUTION !
THIS CODE IS OBSOLETE NOW. PLEASE USE "uart_tx.sv" VERSION INSTEAD
/* --- INSTANTIATION TEMPLATE BEGIN ---
UartTx UT1 (
.clk(),
.nrst( 1'b1 ),
//.tx_do_sample(),
.tx_data(),
.tx_start(),
.tx_busy(),
.txd()
);
defparam UT1.CLK_HZ = 200_000_000;
defparam UT1.BAUD = 9600; // max. BAUD is CLK_HZ / 2
--- INSTANTIATION TEMPLATE END ---*/
module UartTx(clk, nrst, tx_data, tx_start, tx_busy, txd);
//module UartTx(clk, nrst, tx_do_sample, tx_data, tx_start, tx_busy, txd);
parameter CLK_HZ = 200_000_000;
parameter BAUD = 9600;
parameter BAUD_DIVISOR = CLK_HZ / BAUD;
input wire clk;
input wire nrst;
//input wire tx_do_sample;
input wire [7:0] tx_data;
input wire tx_start; // write strobe
output reg tx_busy = 0;
output reg txd = 1;
reg [9:0] tx_shifter = 0;
reg [15:0] tx_sample_cntr = 0;
always @ (posedge clk) begin
if ((~nrst) || (tx_sample_cntr[15:0] == 0)) begin
tx_sample_cntr[15:0] <= (BAUD_DIVISOR-1);
end else begin
tx_sample_cntr[15:0] <= tx_sample_cntr[15:0] - 1;
end
end
wire tx_do_sample = (tx_sample_cntr[15:0] == 0);
always @ (posedge clk) begin
if (~nrst) begin
tx_busy <= 0;
tx_shifter[9:0] <= 0;
txd <= 1;
end else begin
if (~tx_busy) begin
if (tx_start) begin // asynchronous data load and 'busy' set
tx_shifter[9:0] <= {1'b1,tx_data[7:0],1'b0};
tx_busy <= 1;
end
end else begin
if (tx_do_sample) begin // next bit
{tx_shifter[9:0],txd} <= {tx_shifter[9:0],txd} >> 1; // txd MUST change only on tx_do_sample although data may be loaded earlier
if (~|tx_shifter[9:1]) begin // early asynchronous 'busy' reset
tx_busy <= 0; // txd still holds data, but shifter is ready to get new info
end
end // tx_do_sample
end // ~tx_busy
end // ~nrst
end
endmodule

View File

@ -1,65 +0,0 @@
//--------------------------------------------------------------------------------
// UartTxExtreme.v
// Konstantin Pavlov, pavlovconst@gmail.com
//--------------------------------------------------------------------------------
// INFO --------------------------------------------------------------------------------
// Extreme minimal UART transmitter
//
// CAUTION:
// optimized for 20MHz/115200
// tx_busy has been made asynchronous to tx_do_sample
// tx_start has no internal protection and should be rised only when tx_busy is low
/* --- INSTANTIATION TEMPLATE BEGIN ---
reg [7:0] tx_sample_cntr = 0;
always @ (posedge clk20) begin
if (tx_sample_cntr[7:0] == 0) begin
tx_sample_cntr[7:0] <= (173-1);
end else begin
tx_sample_cntr[7:0] <= tx_sample_cntr[7:0] - 1;
end
end
wire tx_do_sample = (tx_sample_cntr[7:0] == 0);
UartTxExtreme UT1 (
.clk(),
//.tx_do_sample(),
.tx_data(),
.tx_start(),
.tx_busy(),
.txd()
);
--- INSTANTIATION TEMPLATE END ---*/
module UartTxExtreme(clk, tx_do_sample, tx_data, tx_start, tx_busy, txd);
input wire clk;
input wire tx_do_sample;
input wire [7:0] tx_data;
input wire tx_start;
output wire tx_busy;
output reg txd = 1;
reg [9:0] tx_shifter = 0;
always @ (posedge clk) begin
if (tx_start && ~tx_busy) begin
tx_shifter[9:0] <= {1'b1,tx_data[7:0],1'b0};
end // tx_start
if (tx_do_sample && tx_busy) begin
{tx_shifter[9:0],txd} <= {tx_shifter[9:0],txd} >> 1;
end // tx_do_sample
end
assign
tx_busy = (tx_shifter[9:0] != 0);
endmodule

View File

@ -1,109 +0,0 @@
//--------------------------------------------------------------------------------
// SimWrapper.v
// Konstantin Pavlov, pavlovconst@gmail.com
//--------------------------------------------------------------------------------
// INFO --------------------------------------------------------------------------------
//
//
`timescale 1ns / 1ps
module SimWrapper();
reg clk200;
initial begin
#0 clk200 = 1;
forever
#2.5 clk200 = ~clk200;
end
reg rst;
initial begin
#10.2 rst = 1;
#5 rst = 0;
//#10000;
forever begin
#9985 rst = ~rst;
#5 rst = ~rst;
end
end
wire nrst = ~rst;
reg rst_once;
initial begin // initializing non-X data before PLL starts
#10.2 rst_once = 1;
#5 rst_once = 0;
end
initial begin
#510.2 rst_once = 1; // PLL starts at 500ns, clock appears, so doing the reset for modules
#5 rst_once = 0;
end
wire nrst_once = ~rst_once;
wire [31:0] DerivedClocks;
ClkDivider CD1 (
.clk(clk200),
.nrst(nrst_once),
.out(DerivedClocks[31:0]));
defparam CD1.WIDTH = 32;
wire [31:0] E_DerivedClocks;
EdgeDetect ED1 (
.clk(clk200),
.nrst(nrst_once),
.in(DerivedClocks[31:0]),
.rising(E_DerivedClocks[31:0]),
.falling(),
.both()
);
defparam ED1.WIDTH = 32;
wire [15:0] RandomNumber1;
c_rand RNG1 (
.clk(clk200),
.rst(rst_once),
.reseed(1'b0),
.seed_val(DerivedClocks[31:0]),
.out(RandomNumber1[15:0]));
reg start;
initial begin
#100.2 start = 1;
#5 start = 0;
end
reg [7:0] tx_sample_cntr = 0;
always @ (posedge clk200) begin
if (tx_sample_cntr[7:0] == 0) begin
tx_sample_cntr[7:0] <= (173-1);
end else begin
tx_sample_cntr[7:0] <= tx_sample_cntr[7:0] - 1;
end
end
wire tx_do_sample = (tx_sample_cntr[7:0] == 0);
wire txd_pin;
wire txbusy_pin;
UartTxExtreme UT1 (
.clk(clk200),
.tx_do_sample(tx_do_sample),
.tx_data(RandomNumber1[7:0]),
.tx_start(start),
.tx_busy(txbusy_pin),
.txd(txd_pin)
);
UartRxExtreme UR1 (
.clk(clk200),
.rx_data(),
.rx_busy(),
.rx_done(),
.rxd(txd_pin)
);
endmodule

View File

@ -1,109 +0,0 @@
//--------------------------------------------------------------------------------
// SimWrapper.v
// Konstantin Pavlov, pavlovconst@gmail.com
//--------------------------------------------------------------------------------
// INFO --------------------------------------------------------------------------------
//
CAUTION !
THIS CODE IS OBSOLETE NOW. PLEASE USE "uart_tx.sv", "uart_rx.sv" BLOCKS
AND THEIR TESTBENCHES INSTEAD
`timescale 1ns / 1ps
module SimWrapper();
reg clk200;
initial begin
#0 clk200 = 1;
forever
#2.5 clk200 = ~clk200;
end
reg rst;
initial begin
#10.2 rst = 1;
#5 rst = 0;
//#10000;
forever begin
#9985 rst = ~rst;
#5 rst = ~rst;
end
end
wire nrst = ~rst;
reg rst_once;
initial begin // initializing non-X data before PLL starts
#10.2 rst_once = 1;
#5 rst_once = 0;
end
initial begin
#510.2 rst_once = 1; // PLL starts at 500ns, clock appears, so doing the reset for modules
#5 rst_once = 0;
end
wire nrst_once = ~rst_once;
wire [31:0] DerivedClocks;
ClkDivider CD1 (
.clk(clk200),
.nrst(nrst_once),
.out(DerivedClocks[31:0]));
defparam CD1.WIDTH = 32;
wire [31:0] E_DerivedClocks;
EdgeDetect ED1 (
.clk(clk200),
.nrst(nrst_once),
.in(DerivedClocks[31:0]),
.rising(E_DerivedClocks[31:0]),
.falling(),
.both()
);
defparam ED1.WIDTH = 32;
wire [15:0] RandomNumber1;
c_rand RNG1 (
.clk(clk200),
.rst(rst_once),
.reseed(1'b0),
.seed_val(DerivedClocks[31:0]),
.out(RandomNumber1[15:0]));
reg start;
initial begin
#100.2 start = 1;
#5 start = 0;
end
wire txd_pin;
wire txbusy_pin;
UartTx UT1 (
.clk(clk200),
.nrst(nrst),
.tx_data(RandomNumber1[7:0]),
.tx_start(1'b1), // .tx_start(~|RandomNumber1[15:10]),
.tx_busy(txbusy_pin),
.txd(txd_pin)
);
defparam UT1.CLK_HZ = 200_000_000;
defparam UT1.BAUD = 100_000_000;
UartRx UR1 (
.clk(clk200),
.nrst(nrst),
.rx_data(),
.rx_busy(),
.rx_done(),
.rxd(txd_pin)
);
defparam UR1.CLK_HZ = 200_000_000;
defparam UR1.BAUD = 100_000_000;
endmodule

View File

@ -1,31 +0,0 @@
@echo off
rem ------------------------------------------------------------------------------
rem clean.bat
rem Konstantin Pavlov, pavlovconst@gmail.com
rem ------------------------------------------------------------------------------
rem Use this file as a boilerplate for your custom clean script
rem for Vivado/Vitis projects
SET PROJ=test
del /s /f /q .\%PROJ%.cache\*
rmdir /s /q .\%PROJ%.cache\
del /s /f /q .\%PROJ%.hw\*
rmdir /s /q .\%PROJ%.hw\
del /s /f /q .\%PROJ%.runs\*
rmdir /s /q .\%PROJ%.runs\
del /s /f /q .\%PROJ%.sim\*
rmdir /s /q .\%PROJ%.sim\
del /s /f /q .\.Xil\*
rmdir /s /q .\.Xil\
del /s /f /q .\*.jou
del /s /f /q .\*.log
pause
exit

View File

@ -1,31 +0,0 @@
@echo off
rem ------------------------------------------------------------------------------
rem clean.bat
rem Konstantin Pavlov, pavlovconst@gmail.com
rem ------------------------------------------------------------------------------
rem Use this file as a boilerplate for your custom clean script
rem for Vivado/Vitis projects
SET PROJ=test
del /s /f /q .\%PROJ%.cache\*
rmdir /s /q .\%PROJ%.cache\
del /s /f /q .\%PROJ%.hw\*
rmdir /s /q .\%PROJ%.hw\
del /s /f /q .\%PROJ%.runs\*
rmdir /s /q .\%PROJ%.runs\
del /s /f /q .\%PROJ%.sim\*
rmdir /s /q .\%PROJ%.sim\
del /s /f /q .\.Xil\*
rmdir /s /q .\.Xil\
del /s /f /q .\*.jou
del /s /f /q .\*.log
pause
exit

View File

@ -17,4 +17,5 @@
*.jou
*.log
*.str

View File

@ -93,3 +93,9 @@ proc fmax {target_clock} {
puts ""
}
# export hardware for Vitis IDE
proc eh {} {
write_hw_platform -fixed -force -include_bit -file ./main.xsa
puts ""
}

View File

@ -1,60 +1,34 @@
@echo off
rem ------------------------------------------------------------------------------
rem clean_recursively.bat
rem published as part of https://github.com/pConst/basic_verilog
rem Konstantin Pavlov, pavlovconst@gmail.com
rem ------------------------------------------------------------------------------
rem Use this script to walk through all subdirs and execute cleaning scripts
rem there. Place cleaning script in every sybdir that requires cleaning.
rem Cleaning script names supported
rem - clean.bat (custom one)
rem - clean.bat (generic one)
rem - clean_quartus.bat (special script for quartus project dirs)
rem - clean_vivado.bat (special script for vivado project dirs)
rem - clean_gowin.bat (special script for gowin project dirs)
rem - clean_modelsim.bat (special script for modelsim testbench dirs)
echo INFO: =====================================================================
echo INFO: clean_recursively.bat
echo INFO: The script may sometimes take a long time to complete
for /R %%f in (*) do (
echo %%f | findstr /C:".git" >nul & if ERRORLEVEL 1 (
echo %%f | findstr /C:"clean\.bat" >nul & if ERRORLEVEL 1 (
rem
) else (
pushd %%~df%%~pf
echo %%~df%%~pf
@echo | call %%f
popd
)
for /R /d %%D in (*) do (
echo %%f | findstr /C:"clean\_quartus\.bat" >nul & if ERRORLEVEL 1 (
rem
) else (
pushd %%~df%%~pf
echo %%~df%%~pf
@echo | call %%f
popd
)
echo %%~fD
cd %%~fD
echo %%f | findstr /C:"clean\_vivado\.bat" >nul & if ERRORLEVEL 1 (
rem
) else (
pushd %%~df%%~pf
echo %%~df%%~pf
@echo | call %%f
popd
)
echo %%f | findstr /C:"clean\_modelsim\.bat" >nul & if ERRORLEVEL 1 (
rem
) else (
pushd %%~df%%~pf
echo %%~df%%~pf
@echo | call %%f
popd
)
)
if exist clean.bat @echo | call clean.bat
if exist clean_quartus.bat @echo | call clean_quartus.bat
if exist clean_vivado.bat @echo | call clean_vivado.bat
if exist clean_gowin.bat @echo | call clean_gowin.bat
if exist clean_modelsim.bat @echo | call clean_madelsim.bat
)
pause

954
vm80a.v
View File

@ -1,954 +0,0 @@
//
// copyright (c) 2014 by 1801BM1@gmail.com
// Licensed under CC-BY 3.0 (https://creativecommons.org/licenses/by/3.0/)
//
//______________________________________________________________________________
//
`timescale 1ns / 1ns
module vm80a
(
input pin_clk, // global module clock (no in original 8080)
input pin_f1, // clock phase 1 (used as clock enable)
input pin_f2, // clock phase 2 (used as clock enable)
input pin_reset, // module reset
output[15:0] pin_a, // address bus outputs
inout [7:0] pin_d, //
input pin_hold, //
output pin_hlda, //
input pin_ready, //
output pin_wait, //
input pin_int, //
output pin_inte, //
output pin_sync, //
output pin_dbin, //
output pin_wr_n
);
wire pin_aena, pin_dena;
wire [7:0] pin_din, pin_dout;
wire [15:0] pin_addr;
reg f1_core, f2_core;
assign pin_a = pin_aena ? pin_addr : 16'hZZZZ;
assign pin_d = pin_dena ? pin_dout : 8'hZZ;
assign pin_din = pin_d;
always @(posedge pin_clk)
begin
f1_core <= pin_f1;
f2_core <= pin_f2;
end
vm80a_core core
(
.pin_clk (pin_clk),
.pin_f1 (f1_core),
.pin_f2 (f2_core),
.pin_reset (pin_reset),
.pin_a (pin_addr),
.pin_dout (pin_dout),
.pin_din (pin_din),
.pin_aena (pin_aena),
.pin_dena (pin_dena),
.pin_hold (pin_hold),
.pin_hlda (pin_hlda),
.pin_ready (pin_ready),
.pin_wait (pin_wait),
.pin_int (pin_int),
.pin_inte (pin_inte),
.pin_sync (pin_sync),
.pin_dbin (pin_dbin),
.pin_wr_n (pin_wr_n)
);
endmodule
module vm80a_core
(
input pin_clk, // global module clock (no in original 8080)
input pin_f1, // clock phase 1 (used as clock enable)
input pin_f2, // clock phase 2 (used as clock enable)
input pin_reset, // module reset
output[15:0] pin_a, // address bus outputs
output[7:0] pin_dout, // data bus output
input [7:0] pin_din, // data bus input
output pin_aena, // address outputs enable
output pin_dena, // data outputs enable
input pin_hold, //
output pin_hlda, //
input pin_ready, //
output pin_wait, //
input pin_int, //
output pin_inte, //
output pin_sync, //
output pin_dbin, //
output pin_wr_n
);
//______________________________________________________________________________
//
wire [7:0] d;
reg [7:0] db, di;
reg [15:0] a;
wire clk, f1, f2;
reg abufena, db_ena, db_stb, dbin_pin, dbinf2;
reg reset;
wire ready;
wire dbin_ext;
reg t851, t404, t382, t383, t712, t735, t773;
reg hold, hlda_pin;
wire hlda, h889;
reg wr_n, t1124, t1011, sync;
wire ready_int;
reg [15:0] r16_pc, r16_hl, r16_de, r16_bc, r16_sp, r16_wz, mxo;
wire [15:0] mxi;
wire mxr0, mxr1, mxr2, mxr3, mxr4, mxr5;
wire mxwh, mxwl, mxrh, mxrl, mxw16, mxwadr;
wire dec16, inc16, iad16;
reg xchg_dh, xchg_tt, t3144;
wire t1460, t1467, t1513, t1514, t1519;
wire sy_inta, sy_wo_n, sy_hlta, sy_out, sy_m1, sy_inp, sy_memr;
reg sy_stack;
wire thalt, twt2;
reg t1, t2, tw, t3, t4, t5;
reg t1f1, t2f1, twf1, t3f1, t4f1, t5f1;
reg m1, m2, m3, m4, m5;
reg m1f1, m2f1, m3f1, m4f1, m5f1;
wire start, ms0, ms1, m836, m839, m871;
reg eom, t789, t887, t953, t976, t980;
reg intr, inta, inte, mstart, minta;
wire irq;
reg [7:0] i;
reg i25, i14, i03;
wire imx, acc_sel;
wire id_op, id_io, id_in, id_popsw, id_pupsw,
id_nop, id_lxi, id_inx, id_inr, id_dcr, id_idr, id_mvi, id_dad,
id_dcx, id_opa, id_idm, id_hlt, id_mov, id_opm, id_pop, id_rst,
id_cxx, id_jxx, id_rxx, id_ret, id_jmp, id_opi, id_out, id_11x,
id_rlc, id_rxc, id_rar, id_sha, id_daa, id_cma, id_stc, id_cmc,
id_add, id_adc, id_sub, id_sbb, id_ana, id_xra, id_ora, id_cmp,
id_lsax, id_mvim, id_shld, id_lhld, id_mvmr, id_mvrm, id_push,
id_xthl, id_sphl, id_pchl, id_xchg, id_call, id_eidi, id_stlda;
wire id80, id81, id82, id83, id84, id85, id86, id00, id01,
id02, id03, id04, id05, id06, id07, id08, id09, id10;
wire goto, jmpflag;
reg jmptake, tree0, tree1, tree2;
reg t2806, t2817, t2819, t3047, t2998, t3363, t3403, t3335, t3361;
reg [7:0] xr, r, acc;
wire [7:0] x, s, c;
wire cl, ch, daa, daa_6x, daa_x6;
wire a398;
reg a327, a357, a358;
wire alu_xout, alu_xwr, alu_xrd, alu_ald, alu_awr, alu_ard,
alu_rld, alu_r00, alu_rwr, alu_srd, alu_zrd, alu_frd;
reg psw_z, psw_s, psw_p, psw_c, psw_ac, tmp_c;
reg t2222, t1375, t1497, t1698, t1668, t1780, t1993, t1994;
reg psw_ld, psw_wr, t2046, t2133, t2175;
//_____________________________________________________________________________
//
assign clk = pin_clk;
assign f1 = pin_f1;
assign f2 = pin_f2;
assign pin_a = a;
assign pin_aena = abufena;
assign pin_dout = db;
assign pin_dena = db_ena;
assign dbin_ext = dbinf2;
assign d[7] = ~reset & ~alu_zrd &
( dbin_ext & di[7]
| mxrl & mxo[7]
| mxrh & mxo[15]
| t1f1 & sy_memr
| alu_xrd & xr[7]
| alu_ard & acc[7]
| alu_frd & psw_s
| alu_srd & s[7] );
assign d[6] = ~reset & ~alu_zrd &
( dbin_ext & di[6]
| mxrl & mxo[6]
| mxrh & mxo[14]
| t1f1 & sy_inp
| alu_xrd & xr[6]
| alu_ard & acc[6]
| alu_frd & psw_z
| alu_srd & s[6] );
assign d[5] = ~reset & ~alu_zrd &
( dbin_ext & di[5]
| mxrl & mxo[5]
| mxrh & mxo[13]
| t1f1 & sy_m1
| alu_xrd & xr[5]
| alu_ard & acc[5]
| alu_frd & 1'b0
| alu_srd & s[5] );
assign d[4] = ~reset & ~alu_zrd &
( dbin_ext & di[4]
| mxrl & mxo[4]
| mxrh & mxo[12]
| t1f1 & sy_out
| alu_xrd & xr[4]
| alu_ard & acc[4]
| alu_frd & psw_ac
| alu_srd & s[4] );
assign d[3] = ~reset & ~alu_zrd &
( dbin_ext & di[3]
| mxrl & mxo[3]
| mxrh & mxo[11]
| t1f1 & sy_hlta
| alu_xrd & xr[3]
| alu_ard & acc[3]
| alu_frd & 1'b0
| alu_srd & s[3] );
assign d[2] = ~reset & ~alu_zrd &
( dbin_ext & di[2]
| mxrl & mxo[2]
| mxrh & mxo[10]
| t1f1 & sy_stack
| alu_xrd & xr[2]
| alu_ard & acc[2]
| alu_frd & psw_p
| alu_srd & s[2] );
assign d[1] = ~reset & ~alu_zrd &
( dbin_ext & di[1]
| mxrl & mxo[1]
| mxrh & mxo[9]
| t1f1 & sy_wo_n
| alu_xrd & xr[1]
| alu_ard & acc[1]
| alu_frd & 1'b1
| alu_srd & s[1] );
assign d[0] = ~reset & ~alu_zrd &
( dbin_ext & di[0]
| mxrl & mxo[0]
| mxrh & mxo[8]
| t1f1 & sy_inta
| alu_xrd & xr[0]
| alu_ard & acc[0]
| alu_frd & psw_c
| alu_srd & s[0] );
always @(posedge clk)
begin
if (f2 & db_stb) db <= d;
if (f2) abufena <= (~twt2 | ~thalt) & ~hlda_pin;
if (f1) db_stb <= t1 | (~sy_wo_n & t2);
if (f1) t851 <= t1 | (~sy_wo_n & (t2 | tw | t3));
if (f2) db_ena <= ~reset & t851;
end
//______________________________________________________________________________
//
// reset input buffer
//
always @(posedge clk)
begin
if (f1) t404 <= pin_reset;
if (f2) reset <= t404;
end
//______________________________________________________________________________
//
// hold input buffer
//
assign pin_hlda = hlda_pin;
assign hlda = hold & (t773 | (t3 & sy_wo_n) | (~m1 & sy_hlta) | t735);
assign h889 = t2f1 | twf1;
always @(posedge clk)
begin
if (f1) t712 <= ~sy_wo_n & t3;
if (f2) t735 <= t712;
if (~f2) t382 <= pin_hold;
if (f2) t383 <= ((~t382 & hold) | t383); // extend the front detector pulse for entire F2 duration
if (~f2) t383 <= 1'b0;
if (f2) t773 <= hlda_pin;
if (f1) hlda_pin <= hlda;
end
always @(posedge clk)
begin
if (reset)
hold <= 1'b0;
else
if (f2)
begin
if (t382)
begin
if (~sy_inta & h889) hold <= 1'b1;
end
else
hold <= 1'b0;
end
end
//______________________________________________________________________________
//
assign pin_dbin = dbin_pin;
assign pin_wr_n = wr_n;
assign pin_sync = sync;
always @(posedge clk)
begin
dbinf2 <= (f2 | dbin_pin) & ((t1124 & (m1f1 | ~sy_hlta)) | dbinf2);
if (dbin_pin) di <= pin_din;
if (f2) dbin_pin <= t1124 & (m1f1 | ~sy_hlta);
if (f2) sync <= ~ready_int & t1011;
if (f1) t1011 <= t1 & ~reset;
if (f1) t1124 <= (t2 | tw) & sy_wo_n;
if (f1) wr_n <= ~(t3 | tw) | ready_int | sy_wo_n;
end
//______________________________________________________________________________
//
// ready pin and internal circuits
//
assign ready_int = (m4 | m5) & id_dad;
assign ready = ready_int | pin_ready;
assign pin_wait = twf1;
//______________________________________________________________________________
//
// register unit - 6 16-bit registers
//
// r0 - pc
// r1 - hl, de
// r2 - de, hl
// r3 - bc
// r4 - sp
// r5 - wz
//
assign t1467 = tree1 | (id04 & t4f1 & ~id_xthl);
assign t1519 = tree2 | (id00 & t4f1 & ~id_xthl);
assign mxi = inc16 ? (a + 16'h0001)
: dec16 ? (a - 16'h0001)
: a;
assign inc16 = iad16 & ~dec16;
assign dec16 = iad16 & id05 & (t4f1 | t5f1 | m4f1 | m5f1);
assign iad16 = ~(id00 & (t4f1 | t5f1)) & (~minta | m5 | t3144);
assign mxw16 = t3403;
assign mxwadr = t3363 | (t4f1 & ~id_dad & ~id_hlt);
assign t1513 = (t4f1 & id07) | t3335;
assign t1514 = (t4f1 & id08) | t3361;
assign mxrh = t2998 | (id08 & t4f1 & ~i03);
assign mxrl = t3047 | (id08 & t4f1 & i03);
assign mxwh = t2817 | (t2806 & ~i03);
assign mxwl = t2819 | (t2806 & i03);
assign mxr0 = tree0;
assign mxr1 = xchg_dh & (((t1513 | t1514) & (~i14 & i25)) | t1519)
| ~xchg_dh & (t1513 | t1514) & (i14 & ~i25);
assign mxr2 = xchg_dh & (t1513 | t1514) & (i14 & ~i25)
| ~xchg_dh & (((t1513 | t1514) & (~i14 & i25)) | t1519);
assign mxr3 = (t1513 | t1514) & (~i14 & ~i25);
assign mxr4 = t1467 | (t1513 & i14 & i25);
assign mxr5 = ~(t1467 | t1513 | t1514 | t1519 | mxr0);
always @ (posedge clk)
begin
if (f1) t3144 <= t4 | t5 | (m4 & ~id02);
xchg_tt <= id_xchg & t2;
xchg_dh <= ~reset & ((xchg_tt & ~(id_xchg & t2)) ? ~xchg_dh : xchg_dh);
end
always @ (*)
case ({mxr0, mxr1, mxr2, mxr3, mxr4, mxr5})
6'b100000: mxo = r16_pc;
6'b010000: mxo = r16_hl;
6'b001000: mxo = r16_de;
6'b000100: mxo = r16_bc;
6'b000010: mxo = r16_sp;
6'b000001: mxo = r16_wz;
default: mxo = 16'h0000;
endcase
always @ (posedge clk)
if (f2)
begin
if (mxwadr) a <= mxo;
if (mxw16)
begin
if (mxr0) r16_pc <= mxi;
if (mxr1) r16_hl <= mxi;
if (mxr2) r16_de <= mxi;
if (mxr3) r16_bc <= mxi;
if (mxr4) r16_sp <= mxi;
if (mxr5) r16_wz <= mxi;
end
else
begin
if (mxwl)
begin
if (mxr0) r16_pc[7:0] <= d;
if (mxr1) r16_hl[7:0] <= d;
if (mxr2) r16_de[7:0] <= d;
if (mxr3) r16_bc[7:0] <= d;
if (mxr4) r16_sp[7:0] <= d;
if (mxr5) r16_wz[7:0] <= d;
end
if (mxwh)
begin
if (mxr0) r16_pc[15:8] <= d;
if (mxr1) r16_hl[15:8] <= d;
if (mxr2) r16_de[15:8] <= d;
if (mxr3) r16_bc[15:8] <= d;
if (mxr4) r16_sp[15:8] <= d;
if (mxr5) r16_wz[15:8] <= d;
end
end
end
//______________________________________________________________________________
//
// processor state
//
assign sy_hlta = id_hlt;
assign sy_m1 = m1;
assign sy_inp = m5 & id_in;
assign sy_out = m5 & id_out;
assign sy_inta = inta;
assign sy_memr = sy_wo_n & ~sy_inp & ~minta;
assign sy_wo_n = m1 | m2 | m3 | (((m4 & ~id86) | (m5 & ~id85)) & ~ready_int);
always @(posedge clk)
begin
if (f1)
begin
sy_stack <= (t1 & t1460)
| (t3 & m3 & id_cxx & ~jmptake)
| (t5 & m1 & id_rxx & ~jmptake);
end
end
//______________________________________________________________________________
//
// ticks state machine
//
assign twt2 = (t2f1 | twf1) & ~start;
assign thalt = ~m1 & sy_hlta;
always @(posedge clk)
begin
if (f1)
begin
t1f1 <= t1 & ~reset; // ensure the reliable start after reset
t2f1 <= t2;
twf1 <= tw;
t3f1 <= t3;
t4f1 <= t4;
t5f1 <= t5;
end
if (f2)
begin
t1 <= start;
t2 <= ~start & t1f1;
tw <= ~start & (t2f1 | twf1) & (~ready | thalt);
t3 <= ~start & (t2f1 | twf1) & ready & ~thalt;
t4 <= ~start & t3f1 & ms0 & ~ms1;
t5 <= ~start & t4f1 & ms0 & ~ms1;
end
end
//______________________________________________________________________________
//
assign m836 = m1f1 & id82;
assign m839 = ~t976 | ~sy_hlta;
assign m871 = t789 | id81;
assign start = ~m839
| t953
| (eom & ~(hold & t887))
| (f2 & ((~t382 & hold) | t383) & ~(twf1 | t3f1 | t4f1 | t5f1));
assign ms0 = ~reset & m839 & ~(sy_stack & ~t1f1) & ~(eom & ~m836);
assign ms1 = ~reset & m839 & ~(sy_stack & ~t1f1) & ~(m871 & ~m836) & eom;
always @(posedge clk)
begin
if (f1)
begin
t789 <= (id84 & m3) | (id83 & ~id_mvim & m4) | m5;
t887 <= hold;
t953 <= reset;
t976 <= t980 & m4;
eom <= t5
| t4 & m1 & id80
| t3 & m2
| t3 & m3
| t3 & m4
| t3 & m5 & ~id_xthl;
end
if (f2)
begin
t980 <= sy_inta;
end
end
//______________________________________________________________________________
//
// processor cycles state machine
//
always @(posedge clk)
begin
if (f1)
begin
m1f1 <= m1;
m2f1 <= m2;
m3f1 <= m3;
m4f1 <= m4;
m5f1 <= m5;
end
if (f2)
begin
m1 <= (~ms0 & ~ms1) | (~ms1 & m1f1);
m2 <= (~ms0 | ~ms1) & ((ms0 & m2f1) | (ms1 & m1f1));
m3 <= (ms0 & m3f1) | (ms1 & m2f1);
m4 <= (ms0 & m4f1) | (ms1 & m3f1) | (ms0 & ms1);
m5 <= (ms0 & m5f1) | (ms1 & m4f1);
end
end
//______________________________________________________________________________
//
// interrupt logic
//
assign irq = intr & inte & ~reset & ~hold;
assign pin_inte = inte;
always @(posedge clk)
begin
if (f2) intr <= pin_int;
if (f2) mstart <= ~ms0 & ~ms1;
if (sy_inta) minta <= 1;
if (f1 & t1 & m1) minta <= 0;
end
always @(posedge clk or posedge reset)
begin
if (reset)
begin
inta <= 0;
inte <= 0;
end
else
begin
if (f1)
begin
if (irq & ((tw & sy_hlta) | (mstart & ~id_eidi))) inta <= 1;
if (~intr | id_eidi | (t5 & id_rst)) inta <= 0;
end
if (f2)
begin
if (t1f1 & id_eidi) inte <= i[3];
if (t1f1 & sy_inta) inte <= 0;
end
end
end
//______________________________________________________________________________
//
// instruction register and decoder
//
function cmp
(
input [7:0] i,
input [7:0] c,
input [7:0] m
);
cmp = &(~(i ^ c) | m);
endfunction
assign imx = ~(id_op | (id_mov & t4));
assign acc_sel = imx ? (i[5:3] == 3'b111) : (i[2:0] == 3'b111);
assign jmpflag = (psw_c & i14 & ~i25) // Intel original: d[0] instead of psw_c
| (psw_p & ~i14 & i25) // Intel original: d[2] instead of psw_p
| (psw_z & ~i14 & ~i25) // Intel original: d[6] instead of psw_z
| (psw_s & i14 & i25); // Intel original: d[7] instead of psw_s
always @(posedge clk)
begin
//
// Simplify the D-bus multiplexer and feed the I-register by input pins directly
//
if (~f2 & (reset | (m1 & t3))) i <= pin_din;
if (f1)
begin
i25 <= imx ? i[5] : i[2];
i14 <= imx ? i[4] : i[1];
i03 <= imx ? i[3] : i[0];
end
end
assign goto = id_rst | id_jmp | id_call | (jmptake & (id_cxx | id_jxx));
assign t1460 = (t1 & ( (m2 & id00)
| (m3 & id00)
| (m4 & (id01 | id04))
| (m5 & (id01 | id04)))
| t2 & ( (m2 & id00)
| (m4 & id01)
| (m5 & id01))
| t3 & ( (m4 & (id04 | id_sphl)))
| t5 & ( (m1 & (id04 | id_sphl)))) & ~(~jmptake & id_cxx & t5);
always @(posedge clk)
begin
if (f2 & t4f1)
begin
jmptake <= i03 ? jmpflag : ~jmpflag;
end
if (f1)
begin
tree0 <= t1 & ( (m1 & ~goto)
| (m2 & ~id_xthl)
| (m3 & ~id_xthl)
| (m4 & id02))
| t2 & ( m1
| (m2 & ~id_xthl)
| (m3 & ~id_xthl)
| (m4 & (id02 | id_rst | id_cxx | id_call))
| (m5 & (id_rst | id_cxx | id_call)))
| t3 & ( (m4 & (id_ret | id_rxx))
| (m5 & (id_ret | id_rxx)))
| t5 & id_pchl;
tree1 <= t1460;
tree2 <= t1 & ( (m4 & (id_mov | id_idr | id_op))
| (m5 & id08))
| t2 & ( (m4 & (id_shld | id00 | id_dad))
| (m5 & (id_shld | id00 | id_dad)))
| t3 & ( (m4 & (id_lhld | id_dad))
| (m5 & (id_lhld | id_dad)))
| t5 & m5;
t2806 <= id08 & ((t3 & m4) | (t5 & m1));
t2817 <= reset | (t3 & (m1 | m3 | (m4 & id_io) | (m5 & id06)));
t2819 <= reset | (t3 & (m2 | (m4 & id06) | (m5 & id_rst)));
t3047 <= m4 & (t1 | t2) & id_dad
| t2 & ((m4 & id_shld) | (m5 & id03));
t2998 <= (t1 | t2) & m5 & id_dad
| t2 & ((m5 & id_shld) | (m4 & id03));
t3403 <= t2 & ( (m1 | m2)
| (m3 & ~id_xthl)
| ((m4 | m5) & ~id_dad & ~id09))
| t3 & m4 & id09
| t5 & (m5 | (m1 & ~id08));
t3363 <= t1 & (m1 | m2 | m3 | ((m4 | m5) & ~id_hlt & ~id_dad));
t3335 <= id07 & ((t1 & (m4 | m5)) | (t3 & (m2 | m3)) | t5);
t3361 <= t1 & m4 & id_lsax
| t2 & id10 & ~sy_wo_n
| t3 & id10 & sy_wo_n & (m4 | m5)
| t5 & id08 & m1;
end
end
assign id_nop = cmp(i, 8'b00xxx000, 8'b00111000);
assign id_lxi = cmp(i, 8'b00xx0001, 8'b00110000);
assign id_lsax = cmp(i, 8'b000xx010, 8'b00011000);
assign id_inx = cmp(i, 8'b00xx0011, 8'b00110000);
assign id_inr = cmp(i, 8'b00xxx100, 8'b00111000);
assign id_dcr = cmp(i, 8'b00xxx101, 8'b00111000);
assign id_idr = cmp(i, 8'b00xxx10x, 8'b00111001);
assign id_mvi = cmp(i, 8'b00xxx110, 8'b00111000);
assign id_dad = cmp(i, 8'b00xx1001, 8'b00110000);
assign id_dcx = cmp(i, 8'b00xx1011, 8'b00110000);
assign id_opa = cmp(i, 8'b00xxx111, 8'b00111000);
assign id_idm = cmp(i, 8'b0011010x, 8'b00000001);
assign id_stlda = cmp(i, 8'b0011x010, 8'b00001000);
assign id_mvim = cmp(i, 8'b00110110, 8'b00000000);
assign id_shld = cmp(i, 8'b00100010, 8'b00000000);
assign id_lhld = cmp(i, 8'b00101010, 8'b00000000);
assign id_mvmr = cmp(i, 8'b01110xxx, 8'b00000111) & ~id_hlt;
assign id_mvrm = cmp(i, 8'b01xxx110, 8'b00111000) & ~id_hlt;
assign id_hlt = cmp(i, 8'b01110110, 8'b00000000);
assign id_mov = cmp(i, 8'b01xxxxxx, 8'b00111111);
assign id_op = cmp(i, 8'b10xxxxxx, 8'b00111111);
assign id_opm = cmp(i, 8'b10xxx110, 8'b00111000);
assign id_pop = cmp(i, 8'b11xx0001, 8'b00110000);
assign id_push = cmp(i, 8'b11xx0101, 8'b00110000);
assign id_rst = cmp(i, 8'b11xxx111, 8'b00111000);
assign id_xthl = cmp(i, 8'b11100011, 8'b00000000);
assign id_sphl = cmp(i, 8'b11111001, 8'b00000000);
assign id_pchl = cmp(i, 8'b11101001, 8'b00000000);
assign id_xchg = cmp(i, 8'b11101011, 8'b00000000);
assign id_cxx = cmp(i, 8'b11xxx100, 8'b00111000);
assign id_jxx = cmp(i, 8'b11xxx010, 8'b00111000);
assign id_rxx = cmp(i, 8'b11xxx000, 8'b00111000);
assign id_ret = cmp(i, 8'b110x1001, 8'b00010000);
assign id_call = cmp(i, 8'b11xx1101, 8'b00110000);
assign id_eidi = cmp(i, 8'b1111x011, 8'b00001000);
assign id_jmp = cmp(i, 8'b1100x011, 8'b00001000);
assign id_io = cmp(i, 8'b1101x011, 8'b00001000);
assign id_opi = cmp(i, 8'b11xxx110, 8'b00111000);
assign id_in = cmp(i, 8'b11011011, 8'b00000000);
assign id_popsw = cmp(i, 8'b11110001, 8'b00000000);
assign id_out = cmp(i, 8'b11010011, 8'b00000000);
assign id_11x = cmp(i, 8'b11xxxxxx, 8'b00111111);
assign id_pupsw = cmp(i, 8'b11110101, 8'b00000000);
assign id_rxc = ~i[5] & i[3] & id_opa;
assign id_sha = ~i[5] & id_opa;
assign id_rlc = (i[5:3] == 3'b000) & id_opa;
assign id_rar = (i[5:3] == 3'b011) & id_opa;
assign id_daa = (i[5:3] == 3'b100) & id_opa;
assign id_cma = (i[5:3] == 3'b101) & id_opa;
assign id_stc = (i[5:3] == 3'b110) & id_opa;
assign id_cmc = (i[5:3] == 3'b111) & id_opa;
assign id_add = (i[5:3] == 3'b000) & (id_op | id_opi);
assign id_adc = (i[5:3] == 3'b001) & (id_op | id_opi);
assign id_sub = (i[5:3] == 3'b010) & (id_op | id_opi);
assign id_sbb = (i[5:3] == 3'b011) & (id_op | id_opi);
assign id_ana = (i[5:3] == 3'b100) & (id_op | id_opi);
assign id_xra = (i[5:3] == 3'b101) & (id_op | id_opi);
assign id_ora = (i[5:3] == 3'b110) & (id_op | id_opi);
assign id_cmp = (i[5:3] == 3'b111) & (id_op | id_opi);
assign id80 = id_lxi | id_pop | id_opm | id_idm | id_dad
| id_xthl | id_xchg | id_jxx | id_ret | id_eidi
| id_nop | id_stlda | id_mvmr | id_mvrm | id_hlt
| id_opa | id_mvim | id_jmp | id_io | id_opi
| id_mvi | id_lsax | id_lhld | id_shld | id_op;
assign id81 = id_dcx | id_inx | id_sphl | id_pchl | id_xchg
| id_eidi | id_nop | id_opa | id_op | id_mov
| (id_idr & ~id82);
assign id82 = id_pop | id_push | id_opm | id_idm | id_dad
| id_rst | id_ret | id_rxx | id_mvrm | id_mvmr
| id_hlt | id_mvim | id_io | id_opi | id_mvi
| id_lsax;
assign id83 = id_opm | id_stlda | id_mvmr | id_mvrm | id_opi
| id_mvi | id_lsax;
assign id84 = id_lxi | id_jxx | id_jmp;
assign id85 = id_push | id_idm | id_rst | id_xthl | id_cxx
| id_call | id_mvim | id_shld | (id_io & ~i[3]);
assign id86 = id_push | id_rst | id_xthl | id_cxx | id_call
| id_mvmr | id_shld | (~i[3] & (id_lsax | id_stlda));
assign id00 = id_xthl | id_pchl | id_sphl;
assign id01 = id_pop | id_rxx | id_ret;
assign id02 = id_mvi | id_opi | id_io;
assign id03 = id_rst | id_push | id_xthl | id_cxx | id_call;
assign id04 = id_rst | id_push | id_xthl | id_cxx | id_call;
assign id05 = id_rst | id_push | id_xthl | id_cxx | id_call | id_dcx;
assign id06 = id_pop | id_rxx | id_ret | id_dad | id_lhld | id_io;
assign id07 = id_dcx | id_inx | id_lxi | id_dad;
assign id08 = id_mov | id_mvi | id_idr | id_op;
assign id09 = id_rst | id_push | id_xthl | id_cxx | id_call | id_shld;
assign id10 = id_pop | id_push | id_mvrm | id_mvi;
//______________________________________________________________________________
//
// function alu
// (
// input rxc,
// input ora,
// input ana,
// input xra,
// input x,
// input r,
// input nc,
// input rn,
// input cp
// );
// alu = x & r & cp & ~(rxc | ora | ana | xra)
// | nc & (cp | x | r) & ~(rxc | ora | ana | xra)
// | rxc & rn
// | ora & (x | r)
// | ana & (x & r)
// | xra & (x ^ r);
// endfunction
//
//
// assign s[0] = alu(id_rxc, id_ora, id_ana, id_xra, x[0], r[0], ~c[0], r[1], cl) | (id_rlc & c[7]);
// assign s[1] = alu(id_rxc, id_ora, id_ana, id_xra, x[1], r[1], ~c[1], r[2], c[0]);
// assign s[2] = alu(id_rxc, id_ora, id_ana, id_xra, x[2], r[2], ~c[2], r[3], c[1]);
// assign s[3] = alu(id_rxc, id_ora, id_ana, id_xra, x[3], r[3], ~c[3], r[4], c[2]);
// assign s[4] = alu(id_rxc, id_ora, id_ana, id_xra, x[4], r[4], ~c[4], r[5], c[3]);
// assign s[5] = alu(id_rxc, id_ora, id_ana, id_xra, x[5], r[5], ~c[5], r[6], c[4]);
// assign s[6] = alu(id_rxc, id_ora, id_ana, id_xra, x[6], r[6], ~c[6], r[7], c[5]);
// assign s[7] = alu(id_rxc, id_ora, id_ana, id_xra, x[7], r[7], ~c[7], ch, c[6]);
//
//
//______________________________________________________________________________
//
// arithmetic and logic unit
//
// assign alu_xwr = (f1 & m1 & t3) | (f2 & (a327 | t4f1 & (id_out | ~id_11x)));
//
assign alu_xwr = (a327 | t4f1 & (id_rst | id_out | ~id_11x));
assign alu_xout = ~(id_sub | id_sbb | id_cmp | id_cma);
assign alu_xrd = t1698 | a358;
assign x = alu_xout ? xr : ~xr;
assign alu_ald = t2222 & ( id_adc | id_add | id_daa | id_xra | id_sbb
| id_sub | id_ana | id_ora | id_sha | id_cma);
assign alu_ard = t1375 | a398;
assign alu_awr = t1497 | a357;
assign alu_r00 = id_dcr & t4f1;
assign alu_srd = t1668;
assign alu_rwr = t1780;
assign alu_rld = t4f1 & (id_sha | id_op | id_opi);
assign daa = id_daa & t4f1;
assign daa_x6 = (acc[3] & (acc[2] | acc[1])) | psw_ac;
assign daa_6x = ((acc[3] & (acc[2] | acc[1])) & acc[4] & acc[7])
| (acc[7] & (acc[6] | acc[5])) | tmp_c;
assign s = {7'b0000000, id_rlc & c[7]}
| ((id_rxc | id_ora | id_ana | id_xra) ? 8'h00 : (x + r + cl))
| (id_rxc ? {ch, r[7:1]} : 8'h00)
| (id_ora ? (x | r) : 8'h00)
| (id_ana ? (x & r) : 8'h00)
| (id_xra ? (x ^ r) : 8'h00);
assign cl = tmp_c & ~id_daa & ~id_rlc & ~id_ora & ~id_xra & ~id_rxc;
assign ch = tmp_c & id_rar | r[0] & ~id_rar;
//
// wire ca0_n, ca2_n, ca1, ca3;
// assign ca0_n = ~(cl & (x[0] | r[0])) & ~(x[0] & r[0]) & ~(id_ana & id_rxc);
// assign ca2_n = ~(ca1 & (x[2] | r[2])) & ~(x[2] & r[2]) & ~(id_ana & id_rxc);
// assign ca1 = ~(~x[1] & ~r[1]) & ~(ca0_n & (~x[1] | ~r[1])) & ~(id_ora | id_rxc | id_xra);
// assign ca3 = ~(~x[3] & ~r[3]) & ~(ca2_n & (~x[3] | ~r[3])) & ~(id_ora | id_rxc | id_xra);
//
assign c[0] = (r[0] & x[0]) | (cl & (r[0] | x[0]));
assign c[1] = (r[1] & x[1]) | (c[0] & (r[1] | x[1]));
assign c[2] = (r[2] & x[2]) | (c[1] & (r[2] | x[2]));
assign c[3] = (r[3] & x[3]) | (c[2] & (r[3] | x[3]));
assign c[4] = (r[4] & x[4]) | (c[3] & (r[4] | x[4]));
assign c[5] = (r[5] & x[5]) | (c[4] & (r[5] | x[5]));
assign c[6] = (r[6] & x[6]) | (c[5] & (r[6] | x[6]));
assign c[7] = (r[7] & x[7]) | (c[6] & (r[7] | x[7]));
assign alu_frd = t2046; /* | t4f1 & (id_11x & ~id_out); */
assign alu_zrd = m1f1 & t3f1;
assign a398 = t1993 & ((t1994 & id08) | id_opa | id_stlda | id_lsax | id_io);
always @(posedge clk)
begin
if (f1)
begin
t1375 <= t2 & m4 & id_pupsw;
t1497 <= t3 & m5 & id_popsw;
t1698 <= t5 & m1 & ~id_inr & ~id_dcr
| t3 & m5 & id_rst;
t1668 <= t2 & m5 & (id_inr | id_dcr)
| t3 & m5 & id_dad
| t3 & m4 & id_dad
| t5 & m1 & (id_inr | id_dcr);
t1780 <= t3 & m1
| t1 & (m4 | m5) & id_dad;
t2222 <= (t2 & m1) | (t1 & m5);
a327 <= t3 & m4 & ~(id_dad | id_out | id_rst)
| t2 & (m4 | m5) & id_dad;
a357 <= t3 & m5 & (id_io | id_mvim) & sy_wo_n
| t3 & m4 & (id_stlda | id_lsax | id_mvmr) & sy_wo_n
| acc_sel & id08 & (t5 & m1 | t3 & m4);
a358 <= t2 & ~sy_wo_n & (id_io | id_mvim | id_stlda | id_lsax | id_mvmr);
psw_ld <= t3 & m4 & id_popsw;
psw_wr <= t2 & m1 & (id_opi | id_inr | id_dcr | id_daa | id_op);
t2046 <= t2 & m5 & id_pupsw; /* | reset | t3 & m1; */
//
// t2047 <= reset
// | t3 & m1
// | t3 & m5 & id_rst;
//
t1993 <= t4 & m1;
t1994 <= acc_sel;
t2133 <= ~id_rxc & c[7];
t2175 <= t3 & m1
| t2 & m5 & id_dad;
end
end
always @(posedge clk)
begin
if (f2)
begin
if (alu_xwr) xr <= id_rst ? (i & 8'b00111000) : d;
if (alu_awr) acc <= d;
if (alu_ald) acc <= s;
if (alu_rld) r <= acc;
if (alu_rwr) r <= d;
if (alu_r00) r <= 8'hff;
if (daa)
begin
r[1] <= daa_x6;
r[2] <= daa_x6;
r[5] <= daa_6x;
r[6] <= daa_6x;
end
if (psw_ld)
begin
psw_c <= d[0]; // x register was in original Intel design
psw_p <= d[2];
psw_ac <= d[4];
psw_z <= d[6];
psw_s <= d[7];
end
if (psw_wr)
begin
psw_p <= ~(^s);
psw_ac <= (c[3] & ~id_xra & ~id_ora & ~id_rxc) | (id_ana & (x[3] | r[3]));
psw_z <= ~(|s);
psw_s <= s[7];
end
if (t2222)
begin
if (id_xra | id_stc | id_ora | id_ana | id_cmc)
psw_c <= ~tmp_c;
if (id_cmp | id_sbb | id_sub)
psw_c <= ~(t2133 | id_rxc & x[0]);
if (id_dad | id_sha | id_adc | id_add)
psw_c <= t2133 | id_rxc & x[0];
end
if (daa & daa_6x)
psw_c <= 1'b1;
if (t2175)
tmp_c <= psw_c;
if (t4f1)
begin
if (id_sbb)
tmp_c <= ~psw_c;
if (id_inr | id_ora | id_xra | id_ana | id_cmp | id_sub)
tmp_c <= 1'b1;
if (id_dad | id_cma | id_dcr | id_add | id_stc)
tmp_c <= 1'b0;
end
end
end
//______________________________________________________________________________
//
endmodule