From 74c6c043fa2c01e6c4bd622b2ba7e57714cc7aaa Mon Sep 17 00:00:00 2001 From: dwf1m12 <d.w.flynn@soton.ac.uk> Date: Sun, 26 Mar 2023 21:43:10 +0100 Subject: [PATCH] dev version of example AES128 accelerator , simulates, but FPGA build problem? --- .../ip_repo/ADPcontrol_1.0/component.xml | 31 +- .../soclabs.org_user_ADPcontrol_1.0.zip | Bin 17477 -> 17528 bytes .../ip_repo/ADPcontrol_1.0/src/ADPmanager.v | 1597 +++++---- .../ip_repo/axi_stream_io_1.0/component.xml | 54 +- .../soclabs.org_user_axi_stream_io_1.0.zip | Bin 16165 -> 16438 bytes .../fpga_imp/scripts/build_mcu_fpga_ip.tcl | 1 + .../target_fpga_zcu104/design_1_wrapper.v | 92 +- .../target_fpga_zcu104/fpga_pinmap.xdc | 74 +- Cortex-M0/nanosoc/systems/mcu/rtl_sim/adp.cmd | 42 +- .../nanosoc/systems/mcu/rtl_sim/makefile | 2 +- .../systems/mcu/verilog/nanosoc_chip.v | 70 +- .../mcu/verilog/soclabs_ahb_aes128_ctrl.v | 3015 +++++++++++++++++ IPLIB/ADPcontrol_v1_0/ADPmanager.v | 4 +- 13 files changed, 4059 insertions(+), 923 deletions(-) create mode 100644 Cortex-M0/nanosoc/systems/mcu/verilog/soclabs_ahb_aes128_ctrl.v diff --git a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0/component.xml b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0/component.xml index 8b10546..d347000 100755 --- a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0/component.xml +++ b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0/component.xml @@ -346,7 +346,7 @@ <spirit:parameters> <spirit:parameter> <spirit:name>viewChecksum</spirit:name> - <spirit:value>e4d9de63</spirit:value> + <spirit:value>d49cf1f2</spirit:value> </spirit:parameter> </spirit:parameters> </spirit:view> @@ -362,7 +362,7 @@ <spirit:parameters> <spirit:parameter> <spirit:name>viewChecksum</spirit:name> - <spirit:value>e4d9de63</spirit:value> + <spirit:value>d49cf1f2</spirit:value> </spirit:parameter> </spirit:parameters> </spirit:view> @@ -882,8 +882,8 @@ </xilinx:taxonomies> <xilinx:displayName>ADPcontrol_v1.0</xilinx:displayName> <xilinx:autoFamilySupportLevel>level_1</xilinx:autoFamilySupportLevel> - <xilinx:coreRevision>28</xilinx:coreRevision> - <xilinx:coreCreationDateTime>2023-03-17T11:11:19Z</xilinx:coreCreationDateTime> + <xilinx:coreRevision>30</xilinx:coreRevision> + <xilinx:coreCreationDateTime>2023-03-26T20:12:13Z</xilinx:coreCreationDateTime> <xilinx:tags> <xilinx:tag xilinx:name="ui.data.coregen.dd@1d457846_ARCHIVE_LOCATION">c:/Users/dflynn/pynq/ip_repo/ADPcontrol_1.0</xilinx:tag> <xilinx:tag xilinx:name="ui.data.coregen.dd@37c19d7d_ARCHIVE_LOCATION">c:/Users/dflynn/pynq/ip_repo/ADPcontrol_1.0</xilinx:tag> @@ -1405,13 +1405,34 @@ <xilinx:tag xilinx:name="ui.data.coregen.df@5f536198_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> <xilinx:tag xilinx:name="ui.data.coregen.df@59f8726d_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> <xilinx:tag xilinx:name="ui.data.coregen.df@3a228f4c_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@4b62686b_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@22cf5990_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@2dc36876_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@755c78e0_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@7e696db_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@2487a8ea_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@239bc11f_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@19bc8965_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@4dd7a85f_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@3188363f_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@1bdf84f9_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@42836bd1_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@7ab99bfa_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@7c0521da_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@207e0ff9_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@10fe6d44_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@3030bfdb_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@636c2387_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@50f99d3_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@2383ab98_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@7ff47a8_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0</xilinx:tag> </xilinx:tags> </xilinx:coreExtensions> <xilinx:packagingInfo> <xilinx:xilinxVersion>2021.1</xilinx:xilinxVersion> <xilinx:checksum xilinx:scope="busInterfaces" xilinx:value="cf8749a1"/> <xilinx:checksum xilinx:scope="addressSpaces" xilinx:value="2ed9224a"/> - <xilinx:checksum xilinx:scope="fileGroups" xilinx:value="6203a1ee"/> + <xilinx:checksum xilinx:scope="fileGroups" xilinx:value="b17660f5"/> <xilinx:checksum xilinx:scope="ports" xilinx:value="2212c402"/> <xilinx:checksum xilinx:scope="hdlParameters" xilinx:value="cd165264"/> <xilinx:checksum xilinx:scope="parameters" xilinx:value="35656c35"/> diff --git a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0/soclabs.org_user_ADPcontrol_1.0.zip b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0/soclabs.org_user_ADPcontrol_1.0.zip index 3abb2fcb7d874d62c253813441c291e06284c7ab..04eb1f8079b4c7eaab525013d43dac28bac7d6ee 100644 GIT binary patch delta 15062 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 delta 14970 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 diff --git a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0/src/ADPmanager.v b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0/src/ADPmanager.v index 5c6ec0b..f056b75 100755 --- a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0/src/ADPmanager.v +++ b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/ADPcontrol_1.0/src/ADPmanager.v @@ -1,800 +1,797 @@ -//----------------------------------------------------------------------------- -// soclabs ASCII Debug Protocol controller -// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license. -// -// Contributors -// -// David Flynn (d.w.flynn@soton.ac.uk) -// -// Copyright © 2021-3, SoC Labs (www.soclabs.org) -//----------------------------------------------------------------------------- - -//`define ADPBASIC 1 - -module ADPmanager // AHB initiator interface - #(parameter PROMPT_CHAR = "]" - ) - ( input wire HCLK, - input wire HRESETn, - output wire [31:0] HADDR32_o, - output wire [ 2:0] HBURST3_o, - output wire HMASTLOCK_o, - output wire [ 3:0] HPROT4_o, - output wire [ 2:0] HSIZE3_o, - output wire [ 1:0] HTRANS2_o, - output wire [31:0] HWDATA32_o, - output wire HWRITE_o, - input wire [31:0] HRDATA32_i, - input wire HREADY_i, - input wire HRESP_i, -// COMIO interface - output wire [ 7:0] GPO8_o, - input wire [ 7:0] GPI8_i, -// input wire COM_RXE_i, - input wire [ 7:0] COMRX_TDATA_i, - input wire COMRX_TVALID_i, - output wire COMRX_TREADY_o, -// input wire COM_TXF_i, - output wire [ 7:0] COMTX_TDATA_o, - output wire COMTX_TVALID_o, - input wire COMTX_TREADY_i, -// STDIO interface -// input wire STDOUT_RXE_i, - input wire [ 7:0] STDRX_TDATA_i, - input wire STDRX_TVALID_i, - output wire STDRX_TREADY_o, -// input wire STDIN_TXF_i - output wire [ 7:0] STDTX_TDATA_o, - output wire STDTX_TVALID_o, - input wire STDTX_TREADY_i -); - -wire COM_RXE_i = !COMRX_TVALID_i; -wire COM_TXF_i = !COMTX_TREADY_i; - -//wire adp_rx_req = COMRX_TVALID_i & COMRX_TREADY_o; -//wire std_rx_req = STDRX_TVALID_i & STDRX_TREADY_o; - - -wire STD_TXF_i = !STDTX_TREADY_i; -wire STD_RXE_i = !STDRX_TVALID_i; - -`ifdef ADPBASIC - localparam BANNERHEX = 32'h50c1ab01; -`else - localparam BANNERHEX = 32'h50c1ab03; -`endif - -localparam CMD_bad = 4'b0000; -localparam CMD_A = 4'b0001; // set Address -localparam CMD_C = 4'b0010; // Control -localparam CMD_R = 4'b0011; // Read word, addr++ -localparam CMD_S = 4'b0100; // Status/STDIN -localparam CMD_W = 4'b0100; // Write word, addr++ -localparam CMD_X = 4'b0101; // eXit -`ifndef ADPBASIC -localparam CMD_F = 4'b1000; // Fill (wordocunt) from addr++ -localparam CMD_M = 4'b1001; // set read Mask -localparam CMD_P = 4'b1010; // Poll hardware (count) -localparam CMD_U = 4'b1011; // (Binary) Upload (wordocunt) from addr++ -localparam CMD_V = 4'b1100; // match Value -`endif - - -function FNvalid_adp_entry; // Escape char -input [7:0] char8; - FNvalid_adp_entry = (char8[7:0] == 8'h1b); -endfunction - -function [3:0] FNvalid_cmd; -input [7:0] char8; -case (char8[7:0]) -"A": FNvalid_cmd = CMD_A; -"a": FNvalid_cmd = CMD_A; -"C": FNvalid_cmd = CMD_C; -"c": FNvalid_cmd = CMD_C; -"R": FNvalid_cmd = CMD_R; -"r": FNvalid_cmd = CMD_R; -"S": FNvalid_cmd = CMD_S; -"s": FNvalid_cmd = CMD_S; -"W": FNvalid_cmd = CMD_W; -"w": FNvalid_cmd = CMD_W; -"X": FNvalid_cmd = CMD_X; -"x": FNvalid_cmd = CMD_X; -`ifndef ADPBASIC -"F": FNvalid_cmd = CMD_F; -"f": FNvalid_cmd = CMD_F; -"M": FNvalid_cmd = CMD_M; -"m": FNvalid_cmd = CMD_M; -"P": FNvalid_cmd = CMD_P; -"p": FNvalid_cmd = CMD_P; -"U": FNvalid_cmd = CMD_U; -"u": FNvalid_cmd = CMD_U; -"V": FNvalid_cmd = CMD_V; -"v": FNvalid_cmd = CMD_V; -`endif -default: - FNvalid_cmd = 0; -endcase -endfunction - -function FNvalid_space; // space or tab char -input [7:0] char8; - FNvalid_space = ((char8[7:0] == 8'h20) || (char8[7:0] == 8'h09)); -endfunction - -function FNnull; // space or tab char -input [7:0] char8; - FNnull = (char8[7:0] == 8'h00); -endfunction - -function FNexit; // EOF -input [7:0] char8; - FNexit = ((char8[7:0] == 8'h04) || (char8[7:0] == 8'h00)); -endfunction - -function FNvalid_EOL; // CR or LF -input [7:0] char8; - FNvalid_EOL = ((char8[7:0] == 8'h0a) || (char8[7:0] == 8'h0d)); -endfunction - -function FNuppercase; -input [7:0] char8; - FNuppercase = (char8[6]) ? (char8 & 8'h5f) : (char8); -endfunction - -function [63:0] FNBuild_param64_hexdigit; -input [63:0] param64; -input [7:0] char8; -case (char8[7:0]) -"\t":FNBuild_param64_hexdigit = 64'b0; // tab starts new (zeroed) param64 -" ": FNBuild_param64_hexdigit = 64'b0; // space starts new (zeroed) param64 -"x": FNBuild_param64_hexdigit = 64'b0; // hex prefix starts new (zeroed) param64 -"X": FNBuild_param64_hexdigit = 64'b0; // hex prefix starts new (zeroed) param64 -"0": FNBuild_param64_hexdigit = {param64[59:0],4'b0000}; -"1": FNBuild_param64_hexdigit = {param64[59:0],4'b0001}; -"2": FNBuild_param64_hexdigit = {param64[59:0],4'b0010}; -"3": FNBuild_param64_hexdigit = {param64[59:0],4'b0011}; -"4": FNBuild_param64_hexdigit = {param64[59:0],4'b0100}; -"5": FNBuild_param64_hexdigit = {param64[59:0],4'b0101}; -"6": FNBuild_param64_hexdigit = {param64[59:0],4'b0110}; -"7": FNBuild_param64_hexdigit = {param64[59:0],4'b0111}; -"8": FNBuild_param64_hexdigit = {param64[59:0],4'b1000}; -"9": FNBuild_param64_hexdigit = {param64[59:0],4'b1001}; -"A": FNBuild_param64_hexdigit = {param64[59:0],4'b1010}; -"B": FNBuild_param64_hexdigit = {param64[59:0],4'b1011}; -"C": FNBuild_param64_hexdigit = {param64[59:0],4'b1100}; -"D": FNBuild_param64_hexdigit = {param64[59:0],4'b1101}; -"E": FNBuild_param64_hexdigit = {param64[59:0],4'b1110}; -"F": FNBuild_param64_hexdigit = {param64[59:0],4'b1111}; -"a": FNBuild_param64_hexdigit = {param64[59:0],4'b1010}; -"b": FNBuild_param64_hexdigit = {param64[59:0],4'b1011}; -"c": FNBuild_param64_hexdigit = {param64[59:0],4'b1100}; -"d": FNBuild_param64_hexdigit = {param64[59:0],4'b1101}; -"e": FNBuild_param64_hexdigit = {param64[59:0],4'b1110}; -"f": FNBuild_param64_hexdigit = {param64[59:0],4'b1111}; -default: FNBuild_param64_hexdigit = param64; // EOL etc returns param64 unchanged -endcase -endfunction - -function [63:0] FNBuild_param64_byte; -input [63:0] param64; -input [7:0] byte; - FNBuild_param64_byte = {byte[7:0], param64[63:08]}; -endfunction - -function [31:0] FNBuild_param32_hexdigit; -input [31:0] param32; -input [7:0] char8; -case (char8[7:0]) -"\t":FNBuild_param32_hexdigit = 32'b0; // tab starts new (zeroed) param32 -" ": FNBuild_param32_hexdigit = 32'b0; // space starts new (zeroed) param32 -"x": FNBuild_param32_hexdigit = 32'b0; // hex prefix starts new (zeroed) param32 -"X": FNBuild_param32_hexdigit = 32'b0; // hex prefix starts new (zeroed) param32 -"0": FNBuild_param32_hexdigit = {param32[27:0],4'b0000}; -"1": FNBuild_param32_hexdigit = {param32[27:0],4'b0001}; -"2": FNBuild_param32_hexdigit = {param32[27:0],4'b0010}; -"3": FNBuild_param32_hexdigit = {param32[27:0],4'b0011}; -"4": FNBuild_param32_hexdigit = {param32[27:0],4'b0100}; -"5": FNBuild_param32_hexdigit = {param32[27:0],4'b0101}; -"6": FNBuild_param32_hexdigit = {param32[27:0],4'b0110}; -"7": FNBuild_param32_hexdigit = {param32[27:0],4'b0111}; -"8": FNBuild_param32_hexdigit = {param32[27:0],4'b1000}; -"9": FNBuild_param32_hexdigit = {param32[27:0],4'b1001}; -"A": FNBuild_param32_hexdigit = {param32[27:0],4'b1010}; -"B": FNBuild_param32_hexdigit = {param32[27:0],4'b1011}; -"C": FNBuild_param32_hexdigit = {param32[27:0],4'b1100}; -"D": FNBuild_param32_hexdigit = {param32[27:0],4'b1101}; -"E": FNBuild_param32_hexdigit = {param32[27:0],4'b1110}; -"F": FNBuild_param32_hexdigit = {param32[27:0],4'b1111}; -"a": FNBuild_param32_hexdigit = {param32[27:0],4'b1010}; -"b": FNBuild_param32_hexdigit = {param32[27:0],4'b1011}; -"c": FNBuild_param32_hexdigit = {param32[27:0],4'b1100}; -"d": FNBuild_param32_hexdigit = {param32[27:0],4'b1101}; -"e": FNBuild_param32_hexdigit = {param32[27:0],4'b1110}; -"f": FNBuild_param32_hexdigit = {param32[27:0],4'b1111}; -default: FNBuild_param32_hexdigit = param32; // EOL etc returns param32 unchanged -endcase -endfunction - -function [31:0] FNBuild_param32_byte; -input [31:0] param32; -input [7:0] byte; - FNBuild_param32_byte = {byte[7:0], param32[31:08]}; -endfunction - - - -function [7:0] FNmap_hex_digit; -input [3:0] nibble; -case (nibble[3:0]) -4'b0000: FNmap_hex_digit = "0"; -4'b0001: FNmap_hex_digit = "1"; -4'b0010: FNmap_hex_digit = "2"; -4'b0011: FNmap_hex_digit = "3"; -4'b0100: FNmap_hex_digit = "4"; -4'b0101: FNmap_hex_digit = "5"; -4'b0110: FNmap_hex_digit = "6"; -4'b0111: FNmap_hex_digit = "7"; -4'b1000: FNmap_hex_digit = "8"; -4'b1001: FNmap_hex_digit = "9"; -4'b1010: FNmap_hex_digit = "a"; -4'b1011: FNmap_hex_digit = "b"; -4'b1100: FNmap_hex_digit = "c"; -4'b1101: FNmap_hex_digit = "d"; -4'b1110: FNmap_hex_digit = "e"; -4'b1111: FNmap_hex_digit = "f"; -default: FNmap_hex_digit = "0"; -endcase -endfunction - - -// as per Vivado synthesis mapping -`ifdef ADPFSMDESIGN -localparam ADP_WRITEHEX = 6'b000000 ; -localparam ADP_WRITEHEXS = 6'b000001 ; -localparam ADP_WRITEHEX9 = 6'b000010 ; -localparam ADP_WRITEHEX8 = 6'b000011 ; -localparam ADP_WRITEHEX7 = 6'b000100 ; -localparam ADP_WRITEHEX6 = 6'b000101 ; -localparam ADP_WRITEHEX5 = 6'b000110 ; -localparam ADP_WRITEHEX4 = 6'b000111 ; -localparam ADP_WRITEHEX3 = 6'b001000 ; -localparam ADP_WRITEHEX2 = 6'b001001 ; -localparam ADP_WRITEHEX1 = 6'b001010 ; -localparam ADP_WRITEHEX0 = 6'b001011 ; -localparam ADP_LINEACK = 6'b001100 ; -localparam ADP_LINEACK2 = 6'b001101 ; -localparam ADP_PROMPT = 6'b001110 ; -localparam ADP_IOCHK = 6'b001111 ; -localparam ADP_STDOUT = 6'b010000 ; -localparam ADP_STDOUT1 = 6'b010001 ; -localparam ADP_STDOUT2 = 6'b010010 ; -localparam ADP_STDOUT3 = 6'b010011 ; -localparam ADP_RXCMD = 6'b010100 ; -localparam ADP_RXPARAM = 6'b010101 ; -localparam ADP_ACTION = 6'b010110 ; -localparam ADP_SYSCTL = 6'b010111 ; -localparam ADP_READ = 6'b011000 ; -localparam ADP_SYSCHK = 6'b011001 ; -localparam ADP_STDIN = 6'b011010 ; -localparam ADP_WRITE = 6'b011011 ; -localparam ADP_EXIT = 6'b011100 ; -localparam STD_IOCHK = 6'b011101 ; -localparam STD_RXD1 = 6'b011110 ; -localparam STD_RXD2 = 6'b011111 ; -localparam STD_TXD1 = 6'b100000 ; -localparam STD_TXD2 = 6'b100001 ; -localparam ADP_UCTRL = 6'b100010 ; -localparam ADP_UREADB0 = 6'b100011 ; -localparam ADP_UREADB1 = 6'b100100 ; -localparam ADP_UREADB2 = 6'b100101 ; -localparam ADP_UREADB3 = 6'b100110 ; -localparam ADP_UWRITE = 6'b100111 ; -localparam ADP_POLL = 6'b101000 ; -localparam ADP_POLL1 = 6'b101001 ; -localparam ADP_POLL2 = 6'b101010 ; -localparam ADP_FCTRL = 6'b101011 ; -localparam ADP_FWRITE = 6'b101100 ; -localparam ADP_ECHOCMD = 6'b101101 ; -localparam ADP_ECHOBUS = 6'b101110 ; -localparam ADP_UNKNOWN = 6'b101111 ; -reg [5:0] adp_state ; -`else -// one-hot encoded explicitly -localparam ADP_WRITEHEX = 48'b000000000000000000000000000000000000000000000001 ; // = 6'b000000 -localparam ADP_WRITEHEXS = 48'b000000000000000000000000000000000000000000000010 ; // = 6'b000001 -localparam ADP_WRITEHEX9 = 48'b000000000000000000000000000000000000000000000100 ; // = 6'b000010 -localparam ADP_WRITEHEX8 = 48'b000000000000000000000000000000000000000000001000 ; // = 6'b000011 -localparam ADP_WRITEHEX7 = 48'b000000000000000000000000000000000000000000010000 ; // = 6'b000100 -localparam ADP_WRITEHEX6 = 48'b000000000000000000000000000000000000000000100000 ; // = 6'b000101 -localparam ADP_WRITEHEX5 = 48'b000000000000000000000000000000000000000001000000 ; // = 6'b000110 -localparam ADP_WRITEHEX4 = 48'b000000000000000000000000000000000000000010000000 ; // = 6'b000111 -localparam ADP_WRITEHEX3 = 48'b000000000000000000000000000000000000000100000000 ; // = 6'b001000 -localparam ADP_WRITEHEX2 = 48'b000000000000000000000000000000000000001000000000 ; // = 6'b001001 -localparam ADP_WRITEHEX1 = 48'b000000000000000000000000000000000000010000000000 ; // = 6'b001010 -localparam ADP_WRITEHEX0 = 48'b000000000000000000000000000000000000100000000000 ; // = 6'b001011 -localparam ADP_LINEACK = 48'b000000000000000000000000000000000001000000000000 ; // = 6'b001100 -localparam ADP_LINEACK2 = 48'b000000000000000000000000000000000010000000000000 ; // = 6'b001101 -localparam ADP_PROMPT = 48'b000000000000000000000000000000000100000000000000 ; // = 6'b001110 -localparam ADP_IOCHK = 48'b000000000000000000000000000000001000000000000000 ; // = 6'b001111 -localparam ADP_STDOUT = 48'b000000000000000000000000000000010000000000000000 ; // = 6'b010000 -localparam ADP_STDOUT1 = 48'b000000000000000000000000000000100000000000000000 ; // = 6'b010001 -localparam ADP_STDOUT2 = 48'b000000000000000000000000000001000000000000000000 ; // = 6'b010010 -localparam ADP_STDOUT3 = 48'b000000000000000000000000000010000000000000000000 ; // = 6'b010011 -localparam ADP_RXCMD = 48'b000000000000000000000000000100000000000000000000 ; // = 6'b010100 -localparam ADP_RXPARAM = 48'b000000000000000000000000001000000000000000000000 ; // = 6'b010101 -localparam ADP_ACTION = 48'b000000000000000000000000010000000000000000000000 ; // = 6'b010110 -localparam ADP_SYSCTL = 48'b000000000000000000000000100000000000000000000000 ; // = 6'b010111 -localparam ADP_READ = 48'b000000000000000000000001000000000000000000000000 ; // = 6'b011000 -localparam ADP_SYSCHK = 48'b000000000000000000000010000000000000000000000000 ; // = 6'b011001 -localparam ADP_STDIN = 48'b000000000000000000000100000000000000000000000000 ; // = 6'b011010 -localparam ADP_WRITE = 48'b000000000000000000001000000000000000000000000000 ; // = 6'b011011 -localparam ADP_EXIT = 48'b000000000000000000010000000000000000000000000000 ; // = 6'b011100 -localparam STD_IOCHK = 48'b000000000000000000100000000000000000000000000000 ; // = 6'b011101 -localparam STD_RXD1 = 48'b000000000000000001000000000000000000000000000000 ; // = 6'b011110 -localparam STD_RXD2 = 48'b000000000000000010000000000000000000000000000000 ; // = 6'b011111 -localparam STD_TXD1 = 48'b000000000000000100000000000000000000000000000000 ; // = 6'b100000 -localparam STD_TXD2 = 48'b000000000000001000000000000000000000000000000000 ; // = 6'b100001 -localparam ADP_UCTRL = 48'b000000000000010000000000000000000000000000000000 ; // = 6'b100010 -localparam ADP_UREADB0 = 48'b000000000000100000000000000000000000000000000000 ; // = 6'b100011 -localparam ADP_UREADB1 = 48'b000000000001000000000000000000000000000000000000 ; // = 6'b100100 -localparam ADP_UREADB2 = 48'b000000000010000000000000000000000000000000000000 ; // = 6'b100101 -localparam ADP_UREADB3 = 48'b000000000100000000000000000000000000000000000000 ; // = 6'b100110 -localparam ADP_UWRITE = 48'b000000001000000000000000000000000000000000000000 ; // = 6'b100111 -localparam ADP_POLL = 48'b000000010000000000000000000000000000000000000000 ; // = 6'b101000 -localparam ADP_POLL1 = 48'b000000100000000000000000000000000000000000000000 ; // = 6'b101001 -localparam ADP_POLL2 = 48'b000001000000000000000000000000000000000000000000 ; // = 6'b101010 -localparam ADP_FCTRL = 48'b000010000000000000000000000000000000000000000000 ; // = 6'b101011 -localparam ADP_FWRITE = 48'b000100000000000000000000000000000000000000000000 ; // = 6'b101100 -localparam ADP_ECHOCMD = 48'b001000000000000000000000000000000000000000000000 ; // = 6'b101101 -localparam ADP_ECHOBUS = 48'b010000000000000000000000000000000000000000000000 ; // = 6'b101110 -localparam ADP_UNKNOWN = 48'b100000000000000000000000000000000000000000000000 ; // = 6'b101111 -reg [47:0] adp_state ; -`endif - -reg [31:0] adp_bus_data; -reg banner ; -reg com_tx_req ; -reg [7:0] com_tx_byte ; -reg com_rx_ack ; -reg std_tx_req ; -reg [ 7:0] std_tx_byte; -reg std_rx_ack ; -reg adp_bus_req ; -reg adp_bus_write ; -reg adp_bus_err ; -reg [7:0] adp_cmd ; -reg [32:0] adp_param ; -reg [31:0] adp_addr ; -reg adp_addr_inc; -reg [31:0] adp_sys ; - -assign GPO8_o = adp_sys[7:0]; - -// ADP RX stream -wire com_rx_req = COMRX_TVALID_i; -wire [ 7:0] com_rx_byte = COMRX_TDATA_i; -assign COMRX_TREADY_o = com_rx_ack; -// ADP TX stream -wire com_tx_ack = COMTX_TREADY_i; -assign COMTX_TDATA_o = com_tx_byte; -assign COMTX_TVALID_o = com_tx_req; -// STD RX stream (from STDOUT) -wire std_rx_req = STDRX_TVALID_i; -wire [ 7:0] std_rx_byte = STDRX_TDATA_i; -assign STDRX_TREADY_o = std_rx_ack; -// STD TX stream (to STDIN) -wire std_tx_ack = STDTX_TREADY_i; -assign STDTX_TDATA_o = std_tx_byte; -assign STDTX_TVALID_o = std_tx_req; - -//AMBA AHB master as "stream" interface -reg ahb_dphase; -wire ahb_aphase = adp_bus_req & !ahb_dphase; -wire adp_bus_ack = ahb_dphase & HREADY_i; -// control pipe -always @(posedge HCLK or negedge HRESETn) - if(!HRESETn) - ahb_dphase <= 0; - else if (HREADY_i) - ahb_dphase <= (ahb_aphase); - -assign HADDR32_o = adp_addr; -assign HBURST3_o = 3'b001; // "INCR" burst signalled whenever transfer; -assign HMASTLOCK_o = 1'b0; -assign HPROT4_o[3:0] = {1'b0, 1'b0, 1'b1, 1'b1}; -assign HSIZE3_o[2:0] = {1'b0, 2'b10}; -assign HTRANS2_o = {ahb_aphase,1'b0}; // non-seq -assign HWDATA32_o = adp_bus_data; -assign HWRITE_o = adp_bus_write; - - -`ifndef ADPBASIC -reg [31:0] adp_val; -reg [31:0] adp_mask; -reg [31:0] adp_poll; -reg [31:0] adp_count; -reg adp_count_dec ; -wire adp_delay_done; -wire poll2_loop_next; -`endif - -// ADP_control flags in the 'C' control field -wire adp_disable; -wire adp_stdin_wait; - -// commnon interface handshake terms -wire com_rx_done = COMRX_TVALID_i & COMRX_TREADY_o; -wire com_tx_done = COMTX_TVALID_o & COMTX_TREADY_i; -wire std_rx_done = STDRX_TVALID_i & STDRX_TREADY_o; -wire std_tx_done = STDTX_TVALID_o & STDTX_TREADY_i; -wire adp_bus_done = (adp_bus_req & adp_bus_ack); - -// common task to set up for next state -task ADP_LINEACK_next; // prepare newline TX (and cancel any startup banner) -// begin com_tx_req <= 1; com_tx_byte <= 8'h0A; banner <= 0; adp_state <= ADP_LINEACK; end - begin com_tx_req <= 1; com_tx_byte <= 8'h0A; adp_state <= ADP_LINEACK; end -endtask -task ADP_PROMPT_next; // prepare prompt TX - begin com_tx_req <= 1; com_tx_byte <= PROMPT_CHAR; adp_state <= ADP_PROMPT; end -endtask -task ADP_BUSWRITEINC_next; // prepare bus write and addr++ on completion - begin adp_bus_req <=1; adp_bus_write <=1; adp_addr_inc <=1; end -endtask -task ADP_BUSREADINC_next; // prepare bus read and addr++ on completion - begin adp_bus_req <=1; adp_bus_write <=0; adp_addr_inc <=1; end -endtask - -task ADP_hexdigit_next; // output nibble -input [3:0] nibble; - begin com_tx_req <= 1; com_tx_byte <= FNmap_hex_digit(nibble[3:0]); end -endtask -task ADP_txchar_next; // output char -input [7:0] byte; - begin com_tx_req<= 1; com_tx_byte <= byte; end -endtask - -task com_rx_nxt; com_rx_ack <=1; endtask - -function FNcount_down_zero_next; // param about to be zero -input [31:0] counter; - FNcount_down_zero_next = !(|counter[31:1]); -endfunction - -always @(posedge HCLK or negedge HRESETn) - if(!HRESETn) begin - adp_state <= ADP_WRITEHEX ; - adp_bus_data <= BANNERHEX; - banner <= 1; // start-up HEX message - com_tx_req <= 0; // default no TX req - com_rx_ack <= 0; // default no RX ack - std_tx_req <= 0; // default no TX req - std_rx_ack <= 0; // default no RX ack - adp_bus_req <= 0; // default no bus transaction - adp_bus_err <= 0; // default no bus error - adp_cmd <= 0; - adp_param <= 0; - adp_addr <= 0; - adp_addr_inc <= 0; - adp_bus_write<= 0; -`ifndef ADPBASIC - adp_count <= 0; - adp_count_dec<= 0; - adp_val <= 0; - adp_mask <= 0; - adp_sys <= 0; -`endif - end else begin // default states - adp_state <= adp_state; // default to hold current state - com_tx_req <= 0; // default no TX req - com_rx_ack <= 0; // default no RX ack - std_tx_req <= 0; // default no TX req - std_rx_ack <= 0; // default no RX ack - adp_bus_req <= 0; // default no bus transaction - adp_addr <= (adp_addr_inc & adp_bus_done) ? adp_addr + 4 : adp_addr; // address++ - adp_addr_inc <= 0; -`ifndef ADPBASIC - adp_count <= (adp_count_dec & adp_bus_done & |adp_count) ? adp_count - 1 : adp_count; // param-- - adp_count_dec<= 0; -`endif - case (adp_state) -// >>>>>>>>>>>>>>>> STDIO BYPASS >>>>>>>>>>>>>>>>>>>>>> - STD_IOCHK: // check for commsrx or STDOUT and not busy service, else loop back - if (com_rx_req) begin com_rx_ack <= 1; adp_state <= STD_RXD1; end // input char pending for STDIN -// else if (com_tx_ack & std_rx_req) begin std_rx_ack <= 1; adp_state <= STD_TXD1; end // STDOUT char pending and not busy - else if (std_rx_req) begin std_rx_ack <= 1; adp_state <= STD_TXD1; end // STDOUT char pending - STD_TXD1: // get STD out char - if (std_rx_done) - begin com_tx_byte <= std_rx_byte; com_tx_req <= 1; adp_state <= STD_TXD2; end - else std_rx_ack <= 1; // extend - STD_TXD2: // output char to ADP channel - if (com_tx_done) begin adp_state <= STD_IOCHK; end - else com_tx_req <= 1; // extend - STD_RXD1: // read rx char and check for ADP entry else STDIN ** - if (com_rx_done) begin - if (FNvalid_adp_entry(com_rx_byte)) - begin ADP_txchar_next(8'h0A); adp_state <= ADP_LINEACK; end // ADP prompt - else if (std_tx_ack) - begin std_tx_byte <= com_rx_byte; std_tx_req <= 1; adp_state <= STD_RXD2; end - else adp_state <= STD_IOCHK; // otherwise discard STDIN char and process OP data if blocked - end else com_rx_ack <= 1; // extend - STD_RXD2: // get STD in char - if (std_tx_done) begin adp_state <= STD_IOCHK; end - else std_tx_req <= 1; // extend - -// >>>>>>>>>>>>>>>> ADP Monitor >>>>>>>>>>>>>>>>>>>>>> - ADP_PROMPT: // transition after reset deassertion - if (com_tx_done) begin adp_state <= ADP_IOCHK; end - else com_tx_req <= 1; // extend - - ADP_IOCHK: // check for commsrx or STDOUT and not busy service, else loop back - if (std_rx_req) begin com_tx_byte <= "<"; com_tx_req <= 1; adp_state <= ADP_STDOUT; end - else if (com_rx_req) begin com_rx_ack <= 1; adp_state <= ADP_RXCMD; end - -// if (com_rx_req) begin com_rx_ack <= 1; adp_state <= ADP_RXCMD; end -// else if (com_tx_ack & std_rx_req) begin com_tx_byte <= "<"; com_tx_req <= 1; adp_state <= ADP_STDOUT; end -//// else if (std_rx_req) begin com_tx_byte <= "<"; com_tx_req <= 1; adp_state <= ADP_STDOUT; end - -// >>>>>>>>>>>>>>>> ADP <STDOUT> >>>>>>>>>>>>>>>>>>>>>> - ADP_STDOUT: // output "<" - if (com_tx_done) begin std_rx_ack <= 1; adp_state <= ADP_STDOUT1; end - else com_tx_req <= 1; // extend stream request if not ready - ADP_STDOUT1: // get STD out char - if (std_rx_done) begin com_tx_byte <= std_rx_byte; com_tx_req <= 1; adp_state <= ADP_STDOUT2; end - else std_rx_ack <= 1; // else extend - ADP_STDOUT2: // output char - if (com_tx_done) begin com_tx_byte <= ">"; com_tx_req <= 1; adp_state <= ADP_STDOUT3; end - else com_tx_req <= 1; // else extend - ADP_STDOUT3: // output ">" - if (com_tx_done) begin if (com_rx_req) begin com_rx_ack <= 1; adp_state <= ADP_RXCMD; end else adp_state <= ADP_IOCHK; end - else com_tx_req <= 1; // else extend - -// >>>>>>>>>>>>>>>> ADP COMMAND PARSING >>>>>>>>>>>>>>>>>>>>>> - ADP_RXCMD: // read and save ADP command - if (com_rx_done) begin - if (FNexit(com_rx_byte)) adp_state <= STD_IOCHK; // immediate exit - else if (FNvalid_space(com_rx_byte)) com_rx_ack <= 1; // retry for a command - else if (FNvalid_EOL(com_rx_byte)) begin adp_cmd <= "?"; adp_state <= ADP_ACTION; end // no command, skip param - else begin adp_cmd <= com_rx_byte; adp_param <= 33'h1_00000000; com_rx_ack <= 1; adp_state <= ADP_RXPARAM; end // get optional parameter - end - else com_rx_ack <= 1; // extend stream request if not ready - ADP_RXPARAM: // read and build hex parameter - if (com_rx_done) begin // RX byte - if (FNexit(com_rx_byte)) adp_state <= STD_IOCHK; // exit - else if (FNvalid_EOL(com_rx_byte)) -`ifndef ADPBASIC - begin adp_count <= adp_param[31:0]; adp_state <= ADP_ACTION; end // parameter complete on EOL -`else - begin adp_state <= ADP_ACTION; end // parameter complete on EOL -`endif - else - begin adp_param <= {1'b0,FNBuild_param32_hexdigit(adp_param[31:0], com_rx_byte)}; com_rx_ack <= 1; end // build parameter - end - else com_rx_ack <= 1; - - ADP_ACTION: // parse command and action with parameter - if (FNexit(com_rx_byte)) - adp_state <= STD_IOCHK; - else if (FNvalid_cmd(adp_cmd) == CMD_A) - begin if (adp_param[32] == 1'b1) adp_param <= {1'b0, adp_addr}; else adp_addr <= adp_param[31:0]; - adp_state <= ADP_ECHOCMD; end - else if (FNvalid_cmd(adp_cmd) == CMD_C) begin - if (adp_param[32]) // report GPO - begin adp_state <= ADP_SYSCTL; end - else if (adp_param[31:8] == 1) // clear selected bits in GPO - begin adp_sys[7:0] <= adp_sys[7:0] & ~adp_param[7:0]; adp_state <= ADP_SYSCTL; end - else if (adp_param[31:8] == 2) // set selected bits in GPO - begin adp_sys[7:0] <= adp_sys[7:0] | adp_param[7:0]; adp_state <= ADP_SYSCTL; end - else if (adp_param[31:8] == 3) // overwrite bits in GPO - begin adp_sys[7:0] <= adp_param[7:0]; adp_state <= ADP_SYSCTL; end - else // 4 etc, report GPO - begin adp_state <= ADP_SYSCTL; end - end - else if (FNvalid_cmd(adp_cmd) == CMD_R) - begin ADP_BUSREADINC_next(); adp_state <= ADP_READ; -`ifndef ADPBASIC - adp_count_dec <= 1'b1; // optional loop param -`endif - end // no param required - else if (FNvalid_cmd(adp_cmd) == CMD_S) - begin adp_state <= ADP_SYSCHK; end - else if (FNvalid_cmd(adp_cmd) == CMD_W) - begin adp_bus_data <= adp_param[31:0]; ADP_BUSWRITEINC_next(); adp_state <= ADP_WRITE; end - else if (FNvalid_cmd(adp_cmd) == CMD_X) - begin com_tx_byte <= 8'h0a; com_tx_req <= 1; adp_state <= ADP_EXIT; end -`ifndef ADPBASIC - else if (FNvalid_cmd(adp_cmd) == CMD_U) - if (FNcount_down_zero_next(adp_param[31:0])) adp_state <= ADP_ECHOCMD; else adp_state <= ADP_UCTRL; // non-zero count - else if (FNvalid_cmd(adp_cmd) == CMD_M) - begin if (adp_param[32] == 1'b1) adp_param <= {1'b0,adp_mask}; else adp_mask <= adp_param[31:0]; - adp_state <= ADP_ECHOCMD; end - else if (FNvalid_cmd(adp_cmd) == CMD_P) - if (FNcount_down_zero_next(adp_param[31:0])) adp_state <= ADP_ECHOCMD; else adp_state <= ADP_POLL; // non-zero count - else if (FNvalid_cmd(adp_cmd) == CMD_V) - begin if (adp_param[32] == 1'b1) adp_param <= {1'b0,adp_val}; else adp_val <= adp_param[31:0]; - adp_state <= ADP_ECHOCMD; end - else if (FNvalid_cmd(adp_cmd) == CMD_F) - if (FNcount_down_zero_next(adp_param[31:0])) adp_state <= ADP_ECHOCMD; else adp_state <= ADP_FCTRL; // non-zero count -`endif - else - begin ADP_txchar_next("?"); adp_state <= ADP_UNKNOWN; end // unrecognised/invald - -// >>>>>>>>>>>>>>>> ADP BUS WRITE and READ >>>>>>>>>>>>>>>>>>>>>> - - ADP_WRITE: // perform bus write at current address pointer (and auto increment) - if (adp_bus_done) begin adp_state <= ADP_ECHOCMD; adp_bus_err <= HRESP_i; end - else begin ADP_BUSWRITEINC_next(); end // extend request - - ADP_READ: // perform bus read at current adp address (and auto increment) - and report in hex - if (adp_bus_done) begin adp_bus_data <= HRDATA32_i; adp_bus_err <= HRESP_i; ADP_txchar_next("R"); adp_state <= ADP_ECHOBUS; end - else begin - ADP_BUSREADINC_next(); -`ifndef ADPBASIC - adp_count_dec<= 1'b1; -`endif - end // extend request - -`ifndef ADPBASIC - -// >>>>>>>>>>>>>>>> ADP BINARY UPLOAD >>>>>>>>>>>>>>>>>>>>>> - ADP_UCTRL: // set control value - begin com_rx_ack <= 1; adp_state <= ADP_UREADB0; end // read next 4 bytes - ADP_UREADB0: // read raw binary byte - if (com_rx_done) begin com_rx_ack <= 1; adp_bus_data[31:24] <= com_rx_byte; adp_state <= ADP_UREADB1; end - else com_rx_ack <= 1; // extend stream request if not ready - ADP_UREADB1: // read raw binary byte - if (com_rx_done) begin com_rx_ack <= 1; adp_bus_data[23:16] <= com_rx_byte; adp_state <= ADP_UREADB2; end - else com_rx_ack <= 1; // extend stream request if not ready - ADP_UREADB2: // read raw binary byte 0 - if (com_rx_done) begin com_rx_ack <= 1; adp_bus_data[15: 8] <= com_rx_byte; adp_state <= ADP_UREADB3; end - else com_rx_ack <= 1; // extend stream request if not ready - ADP_UREADB3: // read raw binary byte 0 - if (com_rx_done) - begin adp_bus_data[ 7: 0] <= com_rx_byte; ADP_BUSWRITEINC_next(); adp_count_dec <= 1; adp_state <= ADP_UWRITE; end - else com_rx_ack <= 1; // extend stream request if not ready - ADP_UWRITE: // Write word to Addr++ - if (adp_bus_done) begin // auto address++, count-- - if (FNcount_down_zero_next(adp_count)) adp_state <= ADP_ECHOCMD; else begin adp_state <= ADP_UREADB0; adp_bus_err <= adp_bus_err | HRESP_i; end - end else begin ADP_BUSWRITEINC_next(); adp_count_dec <= 1; end // extend request - -// >>>>>>>>>>>>>>>> ADP BUS READ LOOP >>>>>>>>>>>>>>>>>>>>>> - ADP_POLL: // set poll value - begin adp_bus_req <= 1; adp_bus_write <= 0; adp_state <= ADP_POLL1; end - ADP_POLL1: // wait for read data, no addr++ - if (adp_bus_done) begin adp_bus_data <= HRDATA32_i; adp_count_dec <=1; adp_state <= ADP_POLL2; adp_bus_err <= adp_bus_err | HRESP_i; end - else begin adp_bus_req <= 1; adp_count_dec <=1; end - ADP_POLL2: - if (FNcount_down_zero_next(adp_count)) begin adp_state <= ADP_ECHOCMD; adp_bus_err <= 1'b1; end // timeout - else if (((adp_bus_data & adp_mask) ^ adp_val) == 0) begin adp_state <= ADP_ECHOCMD; adp_param <= {1'b0, (adp_param[31:0] - adp_count)}; end // exact match - else adp_state <= ADP_POLL; - -// >>>>>>>>>>>>>>>> ADP (ZERO) FILL MEMORY >>>>>>>>>>>>>>>>>>>>>> - ADP_FCTRL: // set control value - begin adp_bus_data <= adp_val; ADP_BUSWRITEINC_next(); adp_count_dec <= 1; adp_state <= ADP_FWRITE; end - ADP_FWRITE: // Write word to Addr++ - if (adp_bus_done) begin // auto address++, count-- - if (FNcount_down_zero_next(adp_count)) adp_state <= ADP_ECHOCMD; else begin adp_state <= ADP_FCTRL; adp_bus_err <= adp_bus_err | HRESP_i; end - end else begin ADP_BUSWRITEINC_next(); adp_count_dec <= 1; end // extend request -`endif - - // >>>>>>>>>>>>>>>> ADP MISC >>>>>>>>>>>>>>>>>>>>>> - - ADP_UNKNOWN: // output "?" - if (com_tx_done) begin ADP_LINEACK_next(); end - else com_tx_req <= 1; // extend stream request if not ready - - ADP_EXIT: // exit ADP mode - if (com_tx_done) adp_state <= STD_IOCHK; - else com_tx_req <= 1; // extend stream request if not ready - - ADP_SYSCHK: // check STDIN fifo - begin // no upper flags so STDIN char - if (std_tx_ack) begin std_tx_req <=1; std_tx_byte <= adp_param[7:0]; adp_state <= ADP_STDIN; end - else begin adp_bus_err <= 1'b1; adp_state <= ADP_ECHOCMD; end // signal error then echo comand - end - ADP_STDIN: // push char into STDIN - if (std_tx_done) begin adp_bus_data <= {24'b0,adp_param[7:0]}; ADP_txchar_next("S"); adp_state <= ADP_ECHOBUS; end - else std_tx_req <= 1; // extend - - ADP_SYSCTL: // read current status - and report in hex - begin adp_bus_data <= {GPI8_i[7:0],adp_sys[7:0],adp_param[15:0]}; ADP_txchar_next("C"); adp_state <= ADP_ECHOBUS; end - - ADP_ECHOCMD: // output command and (param) data - begin ADP_txchar_next(adp_cmd & 8'h5f); adp_bus_data <= adp_param[31:0]; adp_state <= ADP_ECHOBUS; end // output command char - ADP_ECHOBUS: // output command space and (bus) data - if (com_tx_done) begin adp_state <= ADP_WRITEHEXS; ADP_txchar_next(adp_bus_err ? "!" : " "); end // output space char, or "!" on bus error - else com_tx_req <= 1; // extend - - ADP_WRITEHEX: // output hex word with prefix - begin adp_state <= ADP_WRITEHEXS; ADP_txchar_next(adp_bus_err ? "!" : " "); end // output space char, or "!" on bus error - - ADP_WRITEHEXS: - if (com_tx_done) begin adp_state <= ADP_WRITEHEX9; ADP_txchar_next("0"); end // output "0" hex prefix - else com_tx_req <= 1; // extend - ADP_WRITEHEX9: - if (com_tx_done) begin adp_state <= ADP_WRITEHEX8; ADP_txchar_next("x"); end // output "x" hex prefix - else com_tx_req <= 1; // extend - ADP_WRITEHEX8: - if (com_tx_done) begin adp_state <= ADP_WRITEHEX7; ADP_hexdigit_next(adp_bus_data[31:28]); end // hex nibble 7 - else com_tx_req <= 1; // extend - ADP_WRITEHEX7: // output hex nibble 7 - if (com_tx_done) begin adp_state <= ADP_WRITEHEX6; ADP_hexdigit_next(adp_bus_data[27:24]); end // hex nibble 6 - else com_tx_req <= 1; // extend - ADP_WRITEHEX6: // output hex nibble 6 - if (com_tx_done) begin adp_state <= ADP_WRITEHEX5; ADP_hexdigit_next(adp_bus_data[23:20]); end // hex nibble 5 - else com_tx_req <= 1; // extend - ADP_WRITEHEX5: // output hex nibble 5 - if (com_tx_done) begin adp_state <= ADP_WRITEHEX4; ADP_hexdigit_next(adp_bus_data[19:16]); end // hex nibble 4 - else com_tx_req <= 1; // extend - ADP_WRITEHEX4: // output hex nibble 4 - if (com_tx_done) begin adp_state <= ADP_WRITEHEX3; ADP_hexdigit_next(adp_bus_data[15:12]); end // hex nibble 3 - else com_tx_req <= 1; // extend - ADP_WRITEHEX3: // output hex nibble 3 - if (com_tx_done) begin adp_state <= ADP_WRITEHEX2; ADP_hexdigit_next(adp_bus_data[11: 8]); end // hex nibble 2 - else com_tx_req <= 1; // extend - ADP_WRITEHEX2: // output hex nibble 2 - if (com_tx_done) begin adp_state <= ADP_WRITEHEX1; ADP_hexdigit_next(adp_bus_data[ 7: 4]); end // hex nibble 1 - else com_tx_req <= 1; // extend - ADP_WRITEHEX1: // output hex nibble 1 - if (com_tx_done) begin adp_state <= ADP_WRITEHEX0; ADP_hexdigit_next(adp_bus_data[ 3: 0]); end // hex nibble 0 - else com_tx_req <= 1; // extend - ADP_WRITEHEX0: // output hex nibble 0 (if not startup banner then scan to end of line before lineack - if (com_tx_done) begin - adp_bus_err <= 1'b0; // clear sticky bus error flag - if (banner) begin ADP_LINEACK_next(); end - else begin ADP_txchar_next(8'h0A); com_tx_req <= 1; adp_state <= ADP_LINEACK; end // newline and prompt - end else com_tx_req <= 1; // extend - - ADP_LINEACK: // write EOLN - if (com_tx_done) begin - begin ADP_txchar_next(8'h0D); adp_state <= ADP_LINEACK2; end - end else com_tx_req <= 1; // extend - ADP_LINEACK2: // CR - if (com_tx_done) begin - if (banner) begin banner <= 0; adp_state <= STD_IOCHK; end -`ifndef ADPBASIC - else if ((FNvalid_cmd(adp_cmd) == CMD_R) & |adp_count) //// non-zero count - begin ADP_BUSREADINC_next(); adp_count_dec <= 1'b1; adp_state <= ADP_READ; end // -`endif - else begin ADP_txchar_next(PROMPT_CHAR); adp_state <= ADP_PROMPT; end - end else com_tx_req <= 1; // extend - default: - begin ADP_txchar_next("#"); adp_state <= ADP_UNKNOWN; end // default error - endcase - end - -endmodule - -////AHBLITE_ADPMASTER instancing -//ADPmaster -// #(.PROMPT_CHAR ("]")) -// ADPmaster( -// .HCLK (ahb_hclk ), -// .HRESETn (ahb_hrestn ), -// .HADDR32_o (ahb_haddr ), -// .HBURST3_o (ahb_hburst ), -// .HMASTLOCK_o (ahb_hmastlock ), -// .HPROT4_o (ahb_hprot ), -// .HSIZE3_o (ahb_hsize ), -// .HTRANS2_o (ahb_htrans ), -// .HWDATA32_o (ahb_hwdata ), -// .HWRITE_o (ahb_hwrite ), -// .HRDATA32_i (ahb_hrdata ), -// .HREADY_i (ahb_hready ), -// .HRESP_i (ahb_hresp ), - -// .COMRX_TREADY_o(com_rx_tready), -// .COMRX_TDATA_i(com_rx_tdata), -// .COMRX_TVALID_i(com_rx_tvalid), -// .STDRX_TREADY_o(std_rx_tready), -// .STDRX_TDATA_i(std_rx_tdata), -// .STDRX_TVALID_i(std_rx_tvalid), -// .COMTX_TVALID_o(com_tx_tvalid), -// .COMTX_TDATA_o(com_tx_tdata), -// .COMTX_TREADY_i(com_tx_tready), -// .STDTX_TVALID_o(std_tx_tvalid), -// .STDTX_TDATA_o(std_tx_tdata), -// .STDTX_TREADY_i(std_tx_tready) - -// ); +//----------------------------------------------------------------------------- +// soclabs ASCII Debug Protocol controller +// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license. +// +// Contributors +// +// David Flynn (d.w.flynn@soton.ac.uk) +// +// Copyright (C) 2021-3, SoC Labs (www.soclabs.org) +//----------------------------------------------------------------------------- + + +//`define ADPBASIC 1 + +module ADPmanager // AHB initiator interface + #(parameter PROMPT_CHAR = "]" + ) + ( input wire HCLK, + input wire HRESETn, + output wire [31:0] HADDR32_o, + output wire [ 2:0] HBURST3_o, + output wire HMASTLOCK_o, + output wire [ 3:0] HPROT4_o, + output wire [ 2:0] HSIZE3_o, + output wire [ 1:0] HTRANS2_o, + output wire [31:0] HWDATA32_o, + output wire HWRITE_o, + input wire [31:0] HRDATA32_i, + input wire HREADY_i, + input wire HRESP_i, +// COMIO interface + output wire [ 7:0] GPO8_o, + input wire [ 7:0] GPI8_i, +// input wire COM_RXE_i, + input wire [ 7:0] COMRX_TDATA_i, + input wire COMRX_TVALID_i, + output wire COMRX_TREADY_o, +// input wire COM_TXF_i, + output wire [ 7:0] COMTX_TDATA_o, + output wire COMTX_TVALID_o, + input wire COMTX_TREADY_i, +// STDIO interface +// input wire STDOUT_RXE_i, + input wire [ 7:0] STDRX_TDATA_i, + input wire STDRX_TVALID_i, + output wire STDRX_TREADY_o, +// input wire STDIN_TXF_i + output wire [ 7:0] STDTX_TDATA_o, + output wire STDTX_TVALID_o, + input wire STDTX_TREADY_i +); + +wire COM_RXE_i = !COMRX_TVALID_i; +wire COM_TXF_i = !COMTX_TREADY_i; + +//wire adp_rx_req = COMRX_TVALID_i & COMRX_TREADY_o; +//wire std_rx_req = STDRX_TVALID_i & STDRX_TREADY_o; + + +wire STD_TXF_i = !STDTX_TREADY_i; +wire STD_RXE_i = !STDRX_TVALID_i; + +`ifdef ADPBASIC + localparam BANNERHEX = 32'h50c1ab01; +`else + localparam BANNERHEX = 32'h50c1ab03; +`endif + +localparam CMD_bad = 4'b0000; +localparam CMD_A = 4'b0001; // set Address +localparam CMD_C = 4'b0010; // Control +localparam CMD_R = 4'b0011; // Read word, addr++ +localparam CMD_S = 4'b0100; // Status/STDIN +localparam CMD_W = 4'b0101; // Write word, addr++ +localparam CMD_X = 4'b0110; // eXit +`ifndef ADPBASIC +localparam CMD_F = 4'b1000; // Fill (wordocunt) from addr++ +localparam CMD_M = 4'b1001; // set read Mask +localparam CMD_P = 4'b1010; // Poll hardware (count) +localparam CMD_U = 4'b1011; // (Binary) Upload (wordocunt) from addr++ +localparam CMD_V = 4'b1100; // match Value +`endif + + +function FNvalid_adp_entry; // Escape char +input [7:0] char8; + FNvalid_adp_entry = (char8[7:0] == 8'h1b); +endfunction + +function [3:0] FNvalid_cmd; +input [7:0] char8; +case (char8[7:0]) +"A": FNvalid_cmd = CMD_A; +"a": FNvalid_cmd = CMD_A; +"C": FNvalid_cmd = CMD_C; +"c": FNvalid_cmd = CMD_C; +"R": FNvalid_cmd = CMD_R; +"r": FNvalid_cmd = CMD_R; +"S": FNvalid_cmd = CMD_S; +"s": FNvalid_cmd = CMD_S; +"W": FNvalid_cmd = CMD_W; +"w": FNvalid_cmd = CMD_W; +"X": FNvalid_cmd = CMD_X; +"x": FNvalid_cmd = CMD_X; +`ifndef ADPBASIC +"F": FNvalid_cmd = CMD_F; +"f": FNvalid_cmd = CMD_F; +"M": FNvalid_cmd = CMD_M; +"m": FNvalid_cmd = CMD_M; +"P": FNvalid_cmd = CMD_P; +"p": FNvalid_cmd = CMD_P; +"U": FNvalid_cmd = CMD_U; +"u": FNvalid_cmd = CMD_U; +"V": FNvalid_cmd = CMD_V; +"v": FNvalid_cmd = CMD_V; +`endif +default: + FNvalid_cmd = 0; +endcase +endfunction + +function FNvalid_space; // space or tab char +input [7:0] char8; + FNvalid_space = ((char8[7:0] == 8'h20) || (char8[7:0] == 8'h09)); +endfunction + +function FNnull; // space or tab char +input [7:0] char8; + FNnull = (char8[7:0] == 8'h00); +endfunction + +function FNexit; // EOF +input [7:0] char8; + FNexit = ((char8[7:0] == 8'h04) || (char8[7:0] == 8'h00)); +endfunction + +function FNvalid_EOL; // CR or LF +input [7:0] char8; + FNvalid_EOL = ((char8[7:0] == 8'h0a) || (char8[7:0] == 8'h0d)); +endfunction + +function FNuppercase; +input [7:0] char8; + FNuppercase = (char8[6]) ? (char8 & 8'h5f) : (char8); +endfunction + +function [63:0] FNBuild_param64_hexdigit; +input [63:0] param64; +input [7:0] char8; +case (char8[7:0]) +"\t":FNBuild_param64_hexdigit = 64'b0; // tab starts new (zeroed) param64 +" ": FNBuild_param64_hexdigit = 64'b0; // space starts new (zeroed) param64 +"x": FNBuild_param64_hexdigit = 64'b0; // hex prefix starts new (zeroed) param64 +"X": FNBuild_param64_hexdigit = 64'b0; // hex prefix starts new (zeroed) param64 +"0": FNBuild_param64_hexdigit = {param64[59:0],4'b0000}; +"1": FNBuild_param64_hexdigit = {param64[59:0],4'b0001}; +"2": FNBuild_param64_hexdigit = {param64[59:0],4'b0010}; +"3": FNBuild_param64_hexdigit = {param64[59:0],4'b0011}; +"4": FNBuild_param64_hexdigit = {param64[59:0],4'b0100}; +"5": FNBuild_param64_hexdigit = {param64[59:0],4'b0101}; +"6": FNBuild_param64_hexdigit = {param64[59:0],4'b0110}; +"7": FNBuild_param64_hexdigit = {param64[59:0],4'b0111}; +"8": FNBuild_param64_hexdigit = {param64[59:0],4'b1000}; +"9": FNBuild_param64_hexdigit = {param64[59:0],4'b1001}; +"A": FNBuild_param64_hexdigit = {param64[59:0],4'b1010}; +"B": FNBuild_param64_hexdigit = {param64[59:0],4'b1011}; +"C": FNBuild_param64_hexdigit = {param64[59:0],4'b1100}; +"D": FNBuild_param64_hexdigit = {param64[59:0],4'b1101}; +"E": FNBuild_param64_hexdigit = {param64[59:0],4'b1110}; +"F": FNBuild_param64_hexdigit = {param64[59:0],4'b1111}; +"a": FNBuild_param64_hexdigit = {param64[59:0],4'b1010}; +"b": FNBuild_param64_hexdigit = {param64[59:0],4'b1011}; +"c": FNBuild_param64_hexdigit = {param64[59:0],4'b1100}; +"d": FNBuild_param64_hexdigit = {param64[59:0],4'b1101}; +"e": FNBuild_param64_hexdigit = {param64[59:0],4'b1110}; +"f": FNBuild_param64_hexdigit = {param64[59:0],4'b1111}; +default: FNBuild_param64_hexdigit = param64; // EOL etc returns param64 unchanged +endcase +endfunction + +function [63:0] FNBuild_param64_byte; +input [63:0] param64; +input [7:0] byte; + FNBuild_param64_byte = {byte[7:0], param64[63:08]}; +endfunction + +function [31:0] FNBuild_param32_hexdigit; +input [31:0] param32; +input [7:0] char8; +case (char8[7:0]) +"\t":FNBuild_param32_hexdigit = 32'b0; // tab starts new (zeroed) param32 +" ": FNBuild_param32_hexdigit = 32'b0; // space starts new (zeroed) param32 +"x": FNBuild_param32_hexdigit = 32'b0; // hex prefix starts new (zeroed) param32 +"X": FNBuild_param32_hexdigit = 32'b0; // hex prefix starts new (zeroed) param32 +"0": FNBuild_param32_hexdigit = {param32[27:0],4'b0000}; +"1": FNBuild_param32_hexdigit = {param32[27:0],4'b0001}; +"2": FNBuild_param32_hexdigit = {param32[27:0],4'b0010}; +"3": FNBuild_param32_hexdigit = {param32[27:0],4'b0011}; +"4": FNBuild_param32_hexdigit = {param32[27:0],4'b0100}; +"5": FNBuild_param32_hexdigit = {param32[27:0],4'b0101}; +"6": FNBuild_param32_hexdigit = {param32[27:0],4'b0110}; +"7": FNBuild_param32_hexdigit = {param32[27:0],4'b0111}; +"8": FNBuild_param32_hexdigit = {param32[27:0],4'b1000}; +"9": FNBuild_param32_hexdigit = {param32[27:0],4'b1001}; +"A": FNBuild_param32_hexdigit = {param32[27:0],4'b1010}; +"B": FNBuild_param32_hexdigit = {param32[27:0],4'b1011}; +"C": FNBuild_param32_hexdigit = {param32[27:0],4'b1100}; +"D": FNBuild_param32_hexdigit = {param32[27:0],4'b1101}; +"E": FNBuild_param32_hexdigit = {param32[27:0],4'b1110}; +"F": FNBuild_param32_hexdigit = {param32[27:0],4'b1111}; +"a": FNBuild_param32_hexdigit = {param32[27:0],4'b1010}; +"b": FNBuild_param32_hexdigit = {param32[27:0],4'b1011}; +"c": FNBuild_param32_hexdigit = {param32[27:0],4'b1100}; +"d": FNBuild_param32_hexdigit = {param32[27:0],4'b1101}; +"e": FNBuild_param32_hexdigit = {param32[27:0],4'b1110}; +"f": FNBuild_param32_hexdigit = {param32[27:0],4'b1111}; +default: FNBuild_param32_hexdigit = param32; // EOL etc returns param32 unchanged +endcase +endfunction + +function [31:0] FNBuild_param32_byte; +input [31:0] param32; +input [7:0] byte; + FNBuild_param32_byte = {byte[7:0], param32[31:08]}; +endfunction + + + +function [7:0] FNmap_hex_digit; +input [3:0] nibble; +case (nibble[3:0]) +4'b0000: FNmap_hex_digit = "0"; +4'b0001: FNmap_hex_digit = "1"; +4'b0010: FNmap_hex_digit = "2"; +4'b0011: FNmap_hex_digit = "3"; +4'b0100: FNmap_hex_digit = "4"; +4'b0101: FNmap_hex_digit = "5"; +4'b0110: FNmap_hex_digit = "6"; +4'b0111: FNmap_hex_digit = "7"; +4'b1000: FNmap_hex_digit = "8"; +4'b1001: FNmap_hex_digit = "9"; +4'b1010: FNmap_hex_digit = "a"; +4'b1011: FNmap_hex_digit = "b"; +4'b1100: FNmap_hex_digit = "c"; +4'b1101: FNmap_hex_digit = "d"; +4'b1110: FNmap_hex_digit = "e"; +4'b1111: FNmap_hex_digit = "f"; +default: FNmap_hex_digit = "0"; +endcase +endfunction + + +// as per Vivado synthesis mapping +`ifdef ADPFSMDESIGN +localparam ADP_WRITEHEX = 6'b000000 ; +localparam ADP_WRITEHEXS = 6'b000001 ; +localparam ADP_WRITEHEX9 = 6'b000010 ; +localparam ADP_WRITEHEX8 = 6'b000011 ; +localparam ADP_WRITEHEX7 = 6'b000100 ; +localparam ADP_WRITEHEX6 = 6'b000101 ; +localparam ADP_WRITEHEX5 = 6'b000110 ; +localparam ADP_WRITEHEX4 = 6'b000111 ; +localparam ADP_WRITEHEX3 = 6'b001000 ; +localparam ADP_WRITEHEX2 = 6'b001001 ; +localparam ADP_WRITEHEX1 = 6'b001010 ; +localparam ADP_WRITEHEX0 = 6'b001011 ; +localparam ADP_LINEACK = 6'b001100 ; +localparam ADP_LINEACK2 = 6'b001101 ; +localparam ADP_PROMPT = 6'b001110 ; +localparam ADP_IOCHK = 6'b001111 ; +localparam ADP_STDOUT = 6'b010000 ; +localparam ADP_STDOUT1 = 6'b010001 ; +localparam ADP_STDOUT2 = 6'b010010 ; +localparam ADP_STDOUT3 = 6'b010011 ; +localparam ADP_RXCMD = 6'b010100 ; +localparam ADP_RXPARAM = 6'b010101 ; +localparam ADP_ACTION = 6'b010110 ; +localparam ADP_SYSCTL = 6'b010111 ; +localparam ADP_READ = 6'b011000 ; +localparam ADP_SYSCHK = 6'b011001 ; +localparam ADP_STDIN = 6'b011010 ; +localparam ADP_WRITE = 6'b011011 ; +localparam ADP_EXIT = 6'b011100 ; +localparam STD_IOCHK = 6'b011101 ; +localparam STD_RXD1 = 6'b011110 ; +localparam STD_RXD2 = 6'b011111 ; +localparam STD_TXD1 = 6'b100000 ; +localparam STD_TXD2 = 6'b100001 ; +localparam ADP_UCTRL = 6'b100010 ; +localparam ADP_UREADB0 = 6'b100011 ; +localparam ADP_UREADB1 = 6'b100100 ; +localparam ADP_UREADB2 = 6'b100101 ; +localparam ADP_UREADB3 = 6'b100110 ; +localparam ADP_UWRITE = 6'b100111 ; +localparam ADP_POLL = 6'b101000 ; +localparam ADP_POLL1 = 6'b101001 ; +localparam ADP_POLL2 = 6'b101010 ; +localparam ADP_FCTRL = 6'b101011 ; +localparam ADP_FWRITE = 6'b101100 ; +localparam ADP_ECHOCMD = 6'b101101 ; +localparam ADP_ECHOBUS = 6'b101110 ; +localparam ADP_UNKNOWN = 6'b101111 ; +reg [5:0] adp_state ; +`else +// one-hot encoded explicitly +localparam ADP_WRITEHEX = 48'b000000000000000000000000000000000000000000000001 ; // = 6'b000000 +localparam ADP_WRITEHEXS = 48'b000000000000000000000000000000000000000000000010 ; // = 6'b000001 +localparam ADP_WRITEHEX9 = 48'b000000000000000000000000000000000000000000000100 ; // = 6'b000010 +localparam ADP_WRITEHEX8 = 48'b000000000000000000000000000000000000000000001000 ; // = 6'b000011 +localparam ADP_WRITEHEX7 = 48'b000000000000000000000000000000000000000000010000 ; // = 6'b000100 +localparam ADP_WRITEHEX6 = 48'b000000000000000000000000000000000000000000100000 ; // = 6'b000101 +localparam ADP_WRITEHEX5 = 48'b000000000000000000000000000000000000000001000000 ; // = 6'b000110 +localparam ADP_WRITEHEX4 = 48'b000000000000000000000000000000000000000010000000 ; // = 6'b000111 +localparam ADP_WRITEHEX3 = 48'b000000000000000000000000000000000000000100000000 ; // = 6'b001000 +localparam ADP_WRITEHEX2 = 48'b000000000000000000000000000000000000001000000000 ; // = 6'b001001 +localparam ADP_WRITEHEX1 = 48'b000000000000000000000000000000000000010000000000 ; // = 6'b001010 +localparam ADP_WRITEHEX0 = 48'b000000000000000000000000000000000000100000000000 ; // = 6'b001011 +localparam ADP_LINEACK = 48'b000000000000000000000000000000000001000000000000 ; // = 6'b001100 +localparam ADP_LINEACK2 = 48'b000000000000000000000000000000000010000000000000 ; // = 6'b001101 +localparam ADP_PROMPT = 48'b000000000000000000000000000000000100000000000000 ; // = 6'b001110 +localparam ADP_IOCHK = 48'b000000000000000000000000000000001000000000000000 ; // = 6'b001111 +localparam ADP_STDOUT = 48'b000000000000000000000000000000010000000000000000 ; // = 6'b010000 +localparam ADP_STDOUT1 = 48'b000000000000000000000000000000100000000000000000 ; // = 6'b010001 +localparam ADP_STDOUT2 = 48'b000000000000000000000000000001000000000000000000 ; // = 6'b010010 +localparam ADP_STDOUT3 = 48'b000000000000000000000000000010000000000000000000 ; // = 6'b010011 +localparam ADP_RXCMD = 48'b000000000000000000000000000100000000000000000000 ; // = 6'b010100 +localparam ADP_RXPARAM = 48'b000000000000000000000000001000000000000000000000 ; // = 6'b010101 +localparam ADP_ACTION = 48'b000000000000000000000000010000000000000000000000 ; // = 6'b010110 +localparam ADP_SYSCTL = 48'b000000000000000000000000100000000000000000000000 ; // = 6'b010111 +localparam ADP_READ = 48'b000000000000000000000001000000000000000000000000 ; // = 6'b011000 +localparam ADP_SYSCHK = 48'b000000000000000000000010000000000000000000000000 ; // = 6'b011001 +localparam ADP_STDIN = 48'b000000000000000000000100000000000000000000000000 ; // = 6'b011010 +localparam ADP_WRITE = 48'b000000000000000000001000000000000000000000000000 ; // = 6'b011011 +localparam ADP_EXIT = 48'b000000000000000000010000000000000000000000000000 ; // = 6'b011100 +localparam STD_IOCHK = 48'b000000000000000000100000000000000000000000000000 ; // = 6'b011101 +localparam STD_RXD1 = 48'b000000000000000001000000000000000000000000000000 ; // = 6'b011110 +localparam STD_RXD2 = 48'b000000000000000010000000000000000000000000000000 ; // = 6'b011111 +localparam STD_TXD1 = 48'b000000000000000100000000000000000000000000000000 ; // = 6'b100000 +localparam STD_TXD2 = 48'b000000000000001000000000000000000000000000000000 ; // = 6'b100001 +localparam ADP_UCTRL = 48'b000000000000010000000000000000000000000000000000 ; // = 6'b100010 +localparam ADP_UREADB0 = 48'b000000000000100000000000000000000000000000000000 ; // = 6'b100011 +localparam ADP_UREADB1 = 48'b000000000001000000000000000000000000000000000000 ; // = 6'b100100 +localparam ADP_UREADB2 = 48'b000000000010000000000000000000000000000000000000 ; // = 6'b100101 +localparam ADP_UREADB3 = 48'b000000000100000000000000000000000000000000000000 ; // = 6'b100110 +localparam ADP_UWRITE = 48'b000000001000000000000000000000000000000000000000 ; // = 6'b100111 +localparam ADP_POLL = 48'b000000010000000000000000000000000000000000000000 ; // = 6'b101000 +localparam ADP_POLL1 = 48'b000000100000000000000000000000000000000000000000 ; // = 6'b101001 +localparam ADP_POLL2 = 48'b000001000000000000000000000000000000000000000000 ; // = 6'b101010 +localparam ADP_FCTRL = 48'b000010000000000000000000000000000000000000000000 ; // = 6'b101011 +localparam ADP_FWRITE = 48'b000100000000000000000000000000000000000000000000 ; // = 6'b101100 +localparam ADP_ECHOCMD = 48'b001000000000000000000000000000000000000000000000 ; // = 6'b101101 +localparam ADP_ECHOBUS = 48'b010000000000000000000000000000000000000000000000 ; // = 6'b101110 +localparam ADP_UNKNOWN = 48'b100000000000000000000000000000000000000000000000 ; // = 6'b101111 +reg [47:0] adp_state ; +`endif + +reg [31:0] adp_bus_data; +reg banner ; +reg com_tx_req ; +reg [7:0] com_tx_byte ; +reg com_rx_ack ; +reg std_tx_req ; +reg [ 7:0] std_tx_byte; +reg std_rx_ack ; +reg adp_bus_req ; +reg adp_bus_write ; +reg adp_bus_err ; +reg [7:0] adp_cmd ; +reg [32:0] adp_param ; +reg [31:0] adp_addr ; +reg adp_addr_inc; +reg [31:0] adp_sys ; + +assign GPO8_o = adp_sys[7:0]; + +// ADP RX stream +wire com_rx_req = COMRX_TVALID_i; +wire [ 7:0] com_rx_byte = COMRX_TDATA_i; +assign COMRX_TREADY_o = com_rx_ack; +// ADP TX stream +wire com_tx_ack = COMTX_TREADY_i; +assign COMTX_TDATA_o = com_tx_byte; +assign COMTX_TVALID_o = com_tx_req; +// STD RX stream (from STDOUT) +wire std_rx_req = STDRX_TVALID_i; +wire [ 7:0] std_rx_byte = STDRX_TDATA_i; +assign STDRX_TREADY_o = std_rx_ack; +// STD TX stream (to STDIN) +wire std_tx_ack = STDTX_TREADY_i; +assign STDTX_TDATA_o = std_tx_byte; +assign STDTX_TVALID_o = std_tx_req; + +//AMBA AHB master as "stream" interface +reg ahb_dphase; +wire ahb_aphase = adp_bus_req & !ahb_dphase; +wire adp_bus_ack = ahb_dphase & HREADY_i; +// control pipe +always @(posedge HCLK or negedge HRESETn) + if(!HRESETn) + ahb_dphase <= 0; + else if (HREADY_i) + ahb_dphase <= (ahb_aphase); + +assign HADDR32_o = adp_addr; +assign HBURST3_o = 3'b001; // "INCR" burst signalled whenever transfer; +assign HMASTLOCK_o = 1'b0; +assign HPROT4_o[3:0] = {1'b0, 1'b0, 1'b1, 1'b1}; +assign HSIZE3_o[2:0] = {1'b0, 2'b10}; +assign HTRANS2_o = {ahb_aphase,1'b0}; // non-seq +assign HWDATA32_o = adp_bus_data; +assign HWRITE_o = adp_bus_write; + + +`ifndef ADPBASIC +reg [31:0] adp_val; +reg [31:0] adp_mask; +reg [31:0] adp_poll; +reg [31:0] adp_count; +reg adp_count_dec ; +wire adp_delay_done; +wire poll2_loop_next; +`endif + +// ADP_control flags in the 'C' control field +wire adp_disable; +wire adp_stdin_wait; + +// commnon interface handshake terms +wire com_rx_done = COMRX_TVALID_i & COMRX_TREADY_o; +wire com_tx_done = COMTX_TVALID_o & COMTX_TREADY_i; +wire std_rx_done = STDRX_TVALID_i & STDRX_TREADY_o; +wire std_tx_done = STDTX_TVALID_o & STDTX_TREADY_i; +wire adp_bus_done = (adp_bus_req & adp_bus_ack); + +// common task to set up for next state +task ADP_LINEACK_next; // prepare newline TX (and cancel any startup banner) +// begin com_tx_req <= 1; com_tx_byte <= 8'h0A; banner <= 0; adp_state <= ADP_LINEACK; end + begin com_tx_req <= 1; com_tx_byte <= 8'h0A; adp_state <= ADP_LINEACK; end +endtask +task ADP_PROMPT_next; // prepare prompt TX + begin com_tx_req <= 1; com_tx_byte <= PROMPT_CHAR; adp_state <= ADP_PROMPT; end +endtask +task ADP_BUSWRITEINC_next; // prepare bus write and addr++ on completion + begin adp_bus_req <=1; adp_bus_write <=1; adp_addr_inc <=1; end +endtask +task ADP_BUSREADINC_next; // prepare bus read and addr++ on completion + begin adp_bus_req <=1; adp_bus_write <=0; adp_addr_inc <=1; end +endtask + +task ADP_hexdigit_next; // output nibble +input [3:0] nibble; + begin com_tx_req <= 1; com_tx_byte <= FNmap_hex_digit(nibble[3:0]); end +endtask +task ADP_txchar_next; // output char +input [7:0] byte; + begin com_tx_req<= 1; com_tx_byte <= byte; end +endtask + +task com_rx_nxt; com_rx_ack <=1; endtask + +function FNcount_down_zero_next; // param about to be zero +input [31:0] counter; + FNcount_down_zero_next = !(|counter[31:1]); +endfunction + +always @(posedge HCLK or negedge HRESETn) + if(!HRESETn) begin + adp_state <= ADP_WRITEHEX ; + adp_bus_data <= BANNERHEX; + banner <= 1; // start-up HEX message + com_tx_req <= 0; // default no TX req + com_rx_ack <= 0; // default no RX ack + std_tx_req <= 0; // default no TX req + std_rx_ack <= 0; // default no RX ack + adp_bus_req <= 0; // default no bus transaction + adp_bus_err <= 0; // default no bus error + adp_cmd <= 0; + adp_param <= 0; + adp_addr <= 0; + adp_addr_inc <= 0; + adp_bus_write<= 0; +`ifndef ADPBASIC + adp_count <= 0; + adp_count_dec<= 0; + adp_val <= 0; + adp_mask <= 0; + adp_sys <= 0; +`endif + end else begin // default states + adp_state <= adp_state; // default to hold current state + com_tx_req <= 0; // default no TX req + com_rx_ack <= 0; // default no RX ack + std_tx_req <= 0; // default no TX req + std_rx_ack <= 0; // default no RX ack + adp_bus_req <= 0; // default no bus transaction + adp_addr <= (adp_addr_inc & adp_bus_done) ? adp_addr + 4 : adp_addr; // address++ + adp_addr_inc <= 0; +`ifndef ADPBASIC + adp_count <= (adp_count_dec & adp_bus_done & |adp_count) ? adp_count - 1 : adp_count; // param-- + adp_count_dec<= 0; +`endif + case (adp_state) +// >>>>>>>>>>>>>>>> STDIO BYPASS >>>>>>>>>>>>>>>>>>>>>> + STD_IOCHK: // check for commsrx or STDOUT and not busy service, else loop back + if (com_rx_req) begin com_rx_ack <= 1; adp_state <= STD_RXD1; end // input char pending for STDIN +// else if (com_tx_ack & std_rx_req) begin std_rx_ack <= 1; adp_state <= STD_TXD1; end // STDOUT char pending and not busy + else if (std_rx_req) begin std_rx_ack <= 1; adp_state <= STD_TXD1; end // STDOUT char pending + STD_TXD1: // get STD out char + if (std_rx_done) + begin com_tx_byte <= std_rx_byte; com_tx_req <= 1; adp_state <= STD_TXD2; end + else std_rx_ack <= 1; // extend + STD_TXD2: // output char to ADP channel + if (com_tx_done) begin adp_state <= STD_IOCHK; end + else com_tx_req <= 1; // extend + STD_RXD1: // read rx char and check for ADP entry else STDIN ** + if (com_rx_done) begin + if (FNvalid_adp_entry(com_rx_byte)) + begin ADP_txchar_next(8'h0A); adp_state <= ADP_LINEACK; end // ADP prompt + else if (std_tx_ack) + begin std_tx_byte <= com_rx_byte; std_tx_req <= 1; adp_state <= STD_RXD2; end + else adp_state <= STD_IOCHK; // otherwise discard STDIN char and process OP data if blocked + end else com_rx_ack <= 1; // extend + STD_RXD2: // get STD in char + if (std_tx_done) begin adp_state <= STD_IOCHK; end + else std_tx_req <= 1; // extend + +// >>>>>>>>>>>>>>>> ADP Monitor >>>>>>>>>>>>>>>>>>>>>> + ADP_PROMPT: // transition after reset deassertion + if (com_tx_done) begin adp_state <= ADP_IOCHK; end + else com_tx_req <= 1; // extend + + ADP_IOCHK: // check for commsrx or STDOUT and not busy service, else loop back + if (std_rx_req) begin com_tx_byte <= "<"; com_tx_req <= 1; adp_state <= ADP_STDOUT; end + else if (com_rx_req) begin com_rx_ack <= 1; adp_state <= ADP_RXCMD; end + +// >>>>>>>>>>>>>>>> ADP <STDOUT> >>>>>>>>>>>>>>>>>>>>>> + ADP_STDOUT: // output "<" + if (com_tx_done) begin std_rx_ack <= 1; adp_state <= ADP_STDOUT1; end + else com_tx_req <= 1; // extend stream request if not ready + ADP_STDOUT1: // get STD out char + if (std_rx_done) begin com_tx_byte <= std_rx_byte; com_tx_req <= 1; adp_state <= ADP_STDOUT2; end + else std_rx_ack <= 1; // else extend + ADP_STDOUT2: // output char + if (com_tx_done) begin com_tx_byte <= ">"; com_tx_req <= 1; adp_state <= ADP_STDOUT3; end + else com_tx_req <= 1; // else extend + ADP_STDOUT3: // output ">" + if (com_tx_done) begin if (com_rx_req) begin com_rx_ack <= 1; adp_state <= ADP_RXCMD; end else adp_state <= ADP_IOCHK; end + else com_tx_req <= 1; // else extend + +// >>>>>>>>>>>>>>>> ADP COMMAND PARSING >>>>>>>>>>>>>>>>>>>>>> + ADP_RXCMD: // read and save ADP command + if (com_rx_done) begin + if (FNexit(com_rx_byte)) adp_state <= STD_IOCHK; // immediate exit + else if (FNvalid_space(com_rx_byte)) com_rx_ack <= 1; // retry for a command + else if (FNvalid_EOL(com_rx_byte)) begin adp_cmd <= "?"; adp_state <= ADP_ACTION; end // no command, skip param + else begin adp_cmd <= com_rx_byte; adp_param <= 33'h1_00000000; com_rx_ack <= 1; adp_state <= ADP_RXPARAM; end // get optional parameter + end + else com_rx_ack <= 1; // extend stream request if not ready + ADP_RXPARAM: // read and build hex parameter + if (com_rx_done) begin // RX byte + if (FNexit(com_rx_byte)) adp_state <= STD_IOCHK; // exit + else if (FNvalid_EOL(com_rx_byte)) +`ifndef ADPBASIC + begin adp_count <= adp_param[31:0]; adp_state <= ADP_ACTION; end // parameter complete on EOL +`else + begin adp_state <= ADP_ACTION; end // parameter complete on EOL +`endif + else + begin adp_param <= {1'b0,FNBuild_param32_hexdigit(adp_param[31:0], com_rx_byte)}; com_rx_ack <= 1; end // build parameter + end + else com_rx_ack <= 1; + + ADP_ACTION: // parse command and action with parameter + if (FNexit(com_rx_byte)) + adp_state <= STD_IOCHK; + else if (FNvalid_cmd(adp_cmd) == CMD_A) + begin if (adp_param[32] == 1'b1) adp_param <= {1'b0, adp_addr}; else adp_addr <= adp_param[31:0]; + adp_state <= ADP_ECHOCMD; end + else if (FNvalid_cmd(adp_cmd) == CMD_C) begin + if (adp_param[32]) // report GPO + begin adp_state <= ADP_SYSCTL; end + else if (adp_param[31:8] == 1) // clear selected bits in GPO + begin adp_sys[7:0] <= adp_sys[7:0] & ~adp_param[7:0]; adp_state <= ADP_SYSCTL; end + else if (adp_param[31:8] == 2) // set selected bits in GPO + begin adp_sys[7:0] <= adp_sys[7:0] | adp_param[7:0]; adp_state <= ADP_SYSCTL; end + else if (adp_param[31:8] == 3) // overwrite bits in GPO + begin adp_sys[7:0] <= adp_param[7:0]; adp_state <= ADP_SYSCTL; end + else // 4 etc, report GPO + begin adp_state <= ADP_SYSCTL; end + end + else if (FNvalid_cmd(adp_cmd) == CMD_R) + begin ADP_BUSREADINC_next(); adp_state <= ADP_READ; +`ifndef ADPBASIC + adp_count_dec <= 1'b1; // optional loop param +`endif + end // no param required + else if (FNvalid_cmd(adp_cmd) == CMD_S) + begin adp_state <= ADP_SYSCHK; end + else if (FNvalid_cmd(adp_cmd) == CMD_W) + begin adp_bus_data <= adp_param[31:0]; ADP_BUSWRITEINC_next(); adp_state <= ADP_WRITE; end + else if (FNvalid_cmd(adp_cmd) == CMD_X) + begin com_tx_byte <= 8'h0a; com_tx_req <= 1; adp_state <= ADP_EXIT; end +`ifndef ADPBASIC + else if (FNvalid_cmd(adp_cmd) == CMD_U) + if (FNcount_down_zero_next(adp_param[31:0])) adp_state <= ADP_ECHOCMD; else adp_state <= ADP_UCTRL; // non-zero count + else if (FNvalid_cmd(adp_cmd) == CMD_M) + begin if (adp_param[32] == 1'b1) adp_param <= {1'b0,adp_mask}; else adp_mask <= adp_param[31:0]; + adp_state <= ADP_ECHOCMD; end + else if (FNvalid_cmd(adp_cmd) == CMD_P) + if (FNcount_down_zero_next(adp_param[31:0])) adp_state <= ADP_ECHOCMD; else adp_state <= ADP_POLL; // non-zero count + else if (FNvalid_cmd(adp_cmd) == CMD_V) + begin if (adp_param[32] == 1'b1) adp_param <= {1'b0,adp_val}; else adp_val <= adp_param[31:0]; + adp_state <= ADP_ECHOCMD; end + else if (FNvalid_cmd(adp_cmd) == CMD_F) + if (FNcount_down_zero_next(adp_param[31:0])) adp_state <= ADP_ECHOCMD; else adp_state <= ADP_FCTRL; // non-zero count +`endif + else + begin ADP_txchar_next("?"); adp_state <= ADP_UNKNOWN; end // unrecognised/invald + +// >>>>>>>>>>>>>>>> ADP BUS WRITE and READ >>>>>>>>>>>>>>>>>>>>>> + + ADP_WRITE: // perform bus write at current address pointer (and auto increment) + if (adp_bus_done) begin adp_state <= ADP_ECHOCMD; adp_bus_err <= HRESP_i; end + else begin ADP_BUSWRITEINC_next(); end // extend request + + ADP_READ: // perform bus read at current adp address (and auto increment) - and report in hex + if (adp_bus_done) begin adp_bus_data <= HRDATA32_i; adp_bus_err <= HRESP_i; ADP_txchar_next("R"); adp_state <= ADP_ECHOBUS; end + else begin + ADP_BUSREADINC_next(); +`ifndef ADPBASIC + adp_count_dec<= 1'b1; +`endif + end // extend request + +`ifndef ADPBASIC + +// >>>>>>>>>>>>>>>> ADP BINARY UPLOAD >>>>>>>>>>>>>>>>>>>>>> + ADP_UCTRL: // set control value + begin com_rx_ack <= 1; adp_state <= ADP_UREADB0; end // read next 4 bytes + ADP_UREADB0: // read raw binary byte + if (com_rx_done) begin com_rx_ack <= 1; adp_bus_data[31:24] <= com_rx_byte; adp_state <= ADP_UREADB1; end + else com_rx_ack <= 1; // extend stream request if not ready + ADP_UREADB1: // read raw binary byte + if (com_rx_done) begin com_rx_ack <= 1; adp_bus_data[23:16] <= com_rx_byte; adp_state <= ADP_UREADB2; end + else com_rx_ack <= 1; // extend stream request if not ready + ADP_UREADB2: // read raw binary byte 0 + if (com_rx_done) begin com_rx_ack <= 1; adp_bus_data[15: 8] <= com_rx_byte; adp_state <= ADP_UREADB3; end + else com_rx_ack <= 1; // extend stream request if not ready + ADP_UREADB3: // read raw binary byte 0 + if (com_rx_done) + begin adp_bus_data[ 7: 0] <= com_rx_byte; ADP_BUSWRITEINC_next(); adp_count_dec <= 1; adp_state <= ADP_UWRITE; end + else com_rx_ack <= 1; // extend stream request if not ready + ADP_UWRITE: // Write word to Addr++ + if (adp_bus_done) begin // auto address++, count-- + if (FNcount_down_zero_next(adp_count)) adp_state <= ADP_ECHOCMD; else begin adp_state <= ADP_UREADB0; adp_bus_err <= adp_bus_err | HRESP_i; end + end else begin ADP_BUSWRITEINC_next(); adp_count_dec <= 1; end // extend request + +// >>>>>>>>>>>>>>>> ADP BUS READ LOOP >>>>>>>>>>>>>>>>>>>>>> + ADP_POLL: // set poll value + begin adp_bus_req <= 1; adp_bus_write <= 0; adp_state <= ADP_POLL1; end + ADP_POLL1: // wait for read data, no addr++ + if (adp_bus_done) begin adp_bus_data <= HRDATA32_i; adp_count_dec <=1; adp_state <= ADP_POLL2; adp_bus_err <= adp_bus_err | HRESP_i; end + else begin adp_bus_req <= 1; adp_count_dec <=1; end + ADP_POLL2: + if (FNcount_down_zero_next(adp_count)) begin adp_state <= ADP_ECHOCMD; adp_bus_err <= 1'b1; end // timeout + else if (((adp_bus_data & adp_mask) ^ adp_val) == 0) begin adp_state <= ADP_ECHOCMD; adp_param <= {1'b0, (adp_param[31:0] - adp_count)}; end // exact match + else adp_state <= ADP_POLL; + +// >>>>>>>>>>>>>>>> ADP (ZERO) FILL MEMORY >>>>>>>>>>>>>>>>>>>>>> + ADP_FCTRL: // set control value + begin adp_bus_data <= adp_val; ADP_BUSWRITEINC_next(); adp_count_dec <= 1; adp_state <= ADP_FWRITE; end + ADP_FWRITE: // Write word to Addr++ + if (adp_bus_done) begin // auto address++, count-- + if (FNcount_down_zero_next(adp_count)) adp_state <= ADP_ECHOCMD; else begin adp_state <= ADP_FCTRL; adp_bus_err <= adp_bus_err | HRESP_i; end + end else begin ADP_BUSWRITEINC_next(); adp_count_dec <= 1; end // extend request +`endif + + // >>>>>>>>>>>>>>>> ADP MISC >>>>>>>>>>>>>>>>>>>>>> + + ADP_UNKNOWN: // output "?" + if (com_tx_done) begin ADP_LINEACK_next(); end + else com_tx_req <= 1; // extend stream request if not ready + + ADP_EXIT: // exit ADP mode + if (com_tx_done) adp_state <= STD_IOCHK; + else com_tx_req <= 1; // extend stream request if not ready + + ADP_SYSCHK: // check STDIN fifo + begin // no upper flags so STDIN char + if (std_tx_ack) begin std_tx_req <=1; std_tx_byte <= adp_param[7:0]; adp_state <= ADP_STDIN; end + else begin adp_bus_err <= 1'b1; adp_state <= ADP_ECHOCMD; end // signal error then echo comand + end + ADP_STDIN: // push char into STDIN + if (std_tx_done) begin adp_bus_data <= {24'b0,adp_param[7:0]}; ADP_txchar_next("S"); adp_state <= ADP_ECHOBUS; end + else std_tx_req <= 1; // extend + + ADP_SYSCTL: // read current status - and report in hex + begin adp_bus_data <= {GPI8_i[7:0],adp_sys[7:0],adp_param[15:0]}; ADP_txchar_next("C"); adp_state <= ADP_ECHOBUS; end + + ADP_ECHOCMD: // output command and (param) data + begin ADP_txchar_next(adp_cmd & 8'h5f); adp_bus_data <= adp_param[31:0]; adp_state <= ADP_ECHOBUS; end // output command char + ADP_ECHOBUS: // output command space and (bus) data + if (com_tx_done) begin adp_state <= ADP_WRITEHEXS; ADP_txchar_next(adp_bus_err ? "!" : " "); end // output space char, or "!" on bus error + else com_tx_req <= 1; // extend + + ADP_WRITEHEX: // output hex word with prefix + begin adp_state <= ADP_WRITEHEXS; ADP_txchar_next(adp_bus_err ? "!" : " "); end // output space char, or "!" on bus error + + ADP_WRITEHEXS: + if (com_tx_done) begin adp_state <= ADP_WRITEHEX9; ADP_txchar_next("0"); end // output "0" hex prefix + else com_tx_req <= 1; // extend + ADP_WRITEHEX9: + if (com_tx_done) begin adp_state <= ADP_WRITEHEX8; ADP_txchar_next("x"); end // output "x" hex prefix + else com_tx_req <= 1; // extend + ADP_WRITEHEX8: + if (com_tx_done) begin adp_state <= ADP_WRITEHEX7; ADP_hexdigit_next(adp_bus_data[31:28]); end // hex nibble 7 + else com_tx_req <= 1; // extend + ADP_WRITEHEX7: // output hex nibble 7 + if (com_tx_done) begin adp_state <= ADP_WRITEHEX6; ADP_hexdigit_next(adp_bus_data[27:24]); end // hex nibble 6 + else com_tx_req <= 1; // extend + ADP_WRITEHEX6: // output hex nibble 6 + if (com_tx_done) begin adp_state <= ADP_WRITEHEX5; ADP_hexdigit_next(adp_bus_data[23:20]); end // hex nibble 5 + else com_tx_req <= 1; // extend + ADP_WRITEHEX5: // output hex nibble 5 + if (com_tx_done) begin adp_state <= ADP_WRITEHEX4; ADP_hexdigit_next(adp_bus_data[19:16]); end // hex nibble 4 + else com_tx_req <= 1; // extend + ADP_WRITEHEX4: // output hex nibble 4 + if (com_tx_done) begin adp_state <= ADP_WRITEHEX3; ADP_hexdigit_next(adp_bus_data[15:12]); end // hex nibble 3 + else com_tx_req <= 1; // extend + ADP_WRITEHEX3: // output hex nibble 3 + if (com_tx_done) begin adp_state <= ADP_WRITEHEX2; ADP_hexdigit_next(adp_bus_data[11: 8]); end // hex nibble 2 + else com_tx_req <= 1; // extend + ADP_WRITEHEX2: // output hex nibble 2 + if (com_tx_done) begin adp_state <= ADP_WRITEHEX1; ADP_hexdigit_next(adp_bus_data[ 7: 4]); end // hex nibble 1 + else com_tx_req <= 1; // extend + ADP_WRITEHEX1: // output hex nibble 1 + if (com_tx_done) begin adp_state <= ADP_WRITEHEX0; ADP_hexdigit_next(adp_bus_data[ 3: 0]); end // hex nibble 0 + else com_tx_req <= 1; // extend + ADP_WRITEHEX0: // output hex nibble 0 (if not startup banner then scan to end of line before lineack + if (com_tx_done) begin + adp_bus_err <= 1'b0; // clear sticky bus error flag + if (banner) begin ADP_LINEACK_next(); end + else begin ADP_txchar_next(8'h0A); com_tx_req <= 1; adp_state <= ADP_LINEACK; end // newline and prompt + end else com_tx_req <= 1; // extend + + ADP_LINEACK: // write EOLN + if (com_tx_done) begin + begin ADP_txchar_next(8'h0D); adp_state <= ADP_LINEACK2; end + end else com_tx_req <= 1; // extend + ADP_LINEACK2: // CR + if (com_tx_done) begin + if (banner) begin banner <= 0; adp_state <= STD_IOCHK; end +`ifndef ADPBASIC + else if ((FNvalid_cmd(adp_cmd) == CMD_R) & |adp_count) //// non-zero count + begin ADP_BUSREADINC_next(); adp_count_dec <= 1'b1; adp_state <= ADP_READ; end // +`endif + else begin ADP_txchar_next(PROMPT_CHAR); adp_state <= ADP_PROMPT; end + end else com_tx_req <= 1; // extend + default: + begin ADP_txchar_next("#"); adp_state <= ADP_UNKNOWN; end // default error + endcase + end + +endmodule + +////AHBLITE_ADPMASTER instancing +//ADPmaster +// #(.PROMPT_CHAR ("]")) +// ADPmaster( +// .HCLK (ahb_hclk ), +// .HRESETn (ahb_hrestn ), +// .HADDR32_o (ahb_haddr ), +// .HBURST3_o (ahb_hburst ), +// .HMASTLOCK_o (ahb_hmastlock ), +// .HPROT4_o (ahb_hprot ), +// .HSIZE3_o (ahb_hsize ), +// .HTRANS2_o (ahb_htrans ), +// .HWDATA32_o (ahb_hwdata ), +// .HWRITE_o (ahb_hwrite ), +// .HRDATA32_i (ahb_hrdata ), +// .HREADY_i (ahb_hready ), +// .HRESP_i (ahb_hresp ), + +// .COMRX_TREADY_o(com_rx_tready), +// .COMRX_TDATA_i(com_rx_tdata), +// .COMRX_TVALID_i(com_rx_tvalid), +// .STDRX_TREADY_o(std_rx_tready), +// .STDRX_TDATA_i(std_rx_tdata), +// .STDRX_TVALID_i(std_rx_tvalid), +// .COMTX_TVALID_o(com_tx_tvalid), +// .COMTX_TDATA_o(com_tx_tdata), +// .COMTX_TREADY_i(com_tx_tready), +// .STDTX_TVALID_o(std_tx_tvalid), +// .STDTX_TDATA_o(std_tx_tdata), +// .STDTX_TREADY_i(std_tx_tready) + +// ); diff --git a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0/component.xml b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0/component.xml index 5696e41..072555f 100755 --- a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0/component.xml +++ b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0/component.xml @@ -341,28 +341,45 @@ <spirit:displayName>RX FIFO</spirit:displayName> <spirit:description>Data RX FIFO</spirit:description> <spirit:addressOffset>0x00</spirit:addressOffset> - <spirit:size spirit:format="long">1</spirit:size> + <spirit:size spirit:format="long" spirit:bitStringLength="8">32</spirit:size> + <spirit:volatile>true</spirit:volatile> + <spirit:access>read-only</spirit:access> + <spirit:reset> + <spirit:value spirit:format="long">0</spirit:value> + </spirit:reset> </spirit:register> <spirit:register> <spirit:name>TX_FIFO</spirit:name> <spirit:displayName>TX_FIFO</spirit:displayName> <spirit:description>Data TX FIFO</spirit:description> <spirit:addressOffset>0x04</spirit:addressOffset> - <spirit:size spirit:format="long">1</spirit:size> + <spirit:size spirit:format="long" spirit:bitStringLength="8">32</spirit:size> + <spirit:volatile>true</spirit:volatile> + <spirit:access>read-write</spirit:access> </spirit:register> <spirit:register> <spirit:name>STAT_REG</spirit:name> <spirit:displayName>STAT_REG</spirit:displayName> <spirit:description>Status register</spirit:description> <spirit:addressOffset>0x08</spirit:addressOffset> - <spirit:size spirit:format="long">1</spirit:size> + <spirit:size spirit:format="long" spirit:bitStringLength="8">32</spirit:size> + <spirit:volatile>true</spirit:volatile> + <spirit:access>read-only</spirit:access> + <spirit:reset> + <spirit:value spirit:format="long">0</spirit:value> + </spirit:reset> </spirit:register> <spirit:register> <spirit:name>CTRL_REG</spirit:name> <spirit:displayName>CTRL_REG</spirit:displayName> <spirit:description>Control register</spirit:description> <spirit:addressOffset>0x0c</spirit:addressOffset> - <spirit:size spirit:format="long">1</spirit:size> + <spirit:size spirit:format="long" spirit:bitStringLength="8">32</spirit:size> + <spirit:volatile>true</spirit:volatile> + <spirit:access>read-write</spirit:access> + <spirit:reset> + <spirit:value spirit:format="long">0</spirit:value> + </spirit:reset> </spirit:register> </spirit:addressBlock> </spirit:memoryMap> @@ -1023,11 +1040,11 @@ <xilinx:displayName>axi_stream_io_v1.0</xilinx:displayName> <xilinx:vendorDisplayName>SoC Labs</xilinx:vendorDisplayName> <xilinx:vendorURL>http://www.soclabs.org</xilinx:vendorURL> - <xilinx:coreRevision>18</xilinx:coreRevision> + <xilinx:coreRevision>19</xilinx:coreRevision> <xilinx:upgrades> <xilinx:canUpgradeFrom>xilinx.com:user:axi_stream_io:1.0</xilinx:canUpgradeFrom> </xilinx:upgrades> - <xilinx:coreCreationDateTime>2023-02-19T21:07:14Z</xilinx:coreCreationDateTime> + <xilinx:coreCreationDateTime>2023-03-20T20:25:28Z</xilinx:coreCreationDateTime> <xilinx:tags> <xilinx:tag xilinx:name="ui.data.coregen.dd@16fed581_ARCHIVE_LOCATION">c:/Users/dflynn/pynq/ip_repo/axi_stream_io_1.0</xilinx:tag> <xilinx:tag xilinx:name="ui.data.coregen.dd@2ec9608d_ARCHIVE_LOCATION">c:/Users/dflynn/pynq/ip_repo/axi_stream_io_1.0</xilinx:tag> @@ -1467,12 +1484,35 @@ <xilinx:tag xilinx:name="ui.data.coregen.df@6d178b5c_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> <xilinx:tag xilinx:name="ui.data.coregen.df@33a003ad_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> <xilinx:tag xilinx:name="ui.data.coregen.df@6e2ec915_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@6f7af038_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@10651fc4_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@21018812_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@3608e300_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@122973b0_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@69f031ac_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@6cac1894_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@47aa9444_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@e948638_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@240a46bd_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@1ec145a1_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@4699d16c_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@5a5c28d_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@2076db69_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@6fb8f114_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@164ee9fb_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@50207a00_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@5557cbaa_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@7e647370_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@4790eff9_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@33f18dbe_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@7c2a61f0_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> + <xilinx:tag xilinx:name="ui.data.coregen.df@5928464b_ARCHIVE_LOCATION">/home/dwf1m12/soclabs_git_new/nanosoc/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0</xilinx:tag> </xilinx:tags> </xilinx:coreExtensions> <xilinx:packagingInfo> <xilinx:xilinxVersion>2021.1</xilinx:xilinxVersion> <xilinx:checksum xilinx:scope="busInterfaces" xilinx:value="5562313f"/> - <xilinx:checksum xilinx:scope="memoryMaps" xilinx:value="d6592117"/> + <xilinx:checksum xilinx:scope="memoryMaps" xilinx:value="6ce5b224"/> <xilinx:checksum xilinx:scope="fileGroups" xilinx:value="f0ec23b4"/> <xilinx:checksum xilinx:scope="ports" xilinx:value="7c2aad6e"/> <xilinx:checksum xilinx:scope="hdlParameters" xilinx:value="cd9ec9b5"/> diff --git a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0/soclabs.org_user_axi_stream_io_1.0.zip b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/ip_repo/axi_stream_io_1.0/soclabs.org_user_axi_stream_io_1.0.zip index 6427293a7e3a842cbc0c6c8b2efec11dd4817b08..514814910f7ea87bc53616f4e6c0c41f3af6976c 100644 GIT binary patch delta 8167 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 C$Sl<W delta 7879 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 diff --git a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/scripts/build_mcu_fpga_ip.tcl b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/scripts/build_mcu_fpga_ip.tcl index 59baedb..64e58fc 100644 --- a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/scripts/build_mcu_fpga_ip.tcl +++ b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/scripts/build_mcu_fpga_ip.tcl @@ -79,6 +79,7 @@ read_verilog $soc_vlog/cmsdk_mcu_pin_mux.v read_verilog $soc_vlog/cmsdk_mcu_stclkctrl.v read_verilog $soc_vlog/cmsdk_mcu_sysctrl.v ##read_verilog $soc_vlog/cmsdk_uart_capture.v +read_verilog $soc_vlog/soclabs_ahb_aes128_ctrl.v read_verilog $soc_vlog/nanosoc_cpu.v read_verilog $soc_vlog/nanosoc_sys_ahb_decode.v read_verilog $soc_vlog/nanosoc_sysio.v diff --git a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/target_fpga_zcu104/design_1_wrapper.v b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/target_fpga_zcu104/design_1_wrapper.v index ce586c7..84df780 100644 --- a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/target_fpga_zcu104/design_1_wrapper.v +++ b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/target_fpga_zcu104/design_1_wrapper.v @@ -17,18 +17,17 @@ module design_1_wrapper PMOD0_4, PMOD0_5, PMOD0_6, - PMOD0_7 - ); -// PMOD1_0, -// PMOD1_1, -// PMOD1_2, -// PMOD1_3, -// PMOD1_4, -// PMOD1_5, -// PMOD1_6, -// PMOD1_7, -// dip_switch_4bits_tri_i, -// led_4bits_tri_o); + PMOD0_7, + PMOD1_0, + PMOD1_1, + PMOD1_2, + PMOD1_3, + PMOD1_4, + PMOD1_5, + PMOD1_6, + PMOD1_7, + DIPSW4, + LED4); inout wire PMOD0_0; inout wire PMOD0_1; @@ -38,17 +37,17 @@ module design_1_wrapper inout wire PMOD0_5; inout wire PMOD0_6; inout wire PMOD0_7; -// inout wire PMOD1_0; -// inout wire PMOD1_1; -// inout wire PMOD1_2; -// inout wire PMOD1_3; -// inout wire PMOD1_4; -// inout wire PMOD1_5; -// inout wire PMOD1_6; -// inout wire PMOD1_7; + inout wire PMOD1_0; + inout wire PMOD1_1; + inout wire PMOD1_2; + inout wire PMOD1_3; + inout wire PMOD1_4; + inout wire PMOD1_5; + inout wire PMOD1_6; + inout wire PMOD1_7; -// input wire [3:0]dip_switch_4bits_tri_i; -// output wire [3:0]led_4bits_tri_o; + input wire [3:0]DIPSW4; + output wire [3:0]LED4; wire [7:0]PMOD0_tri_i; wire [7:0]PMOD0_tri_o; @@ -72,27 +71,34 @@ module design_1_wrapper assign PMOD0_6 = PMOD0_tri_z[6] ? 1'bz : PMOD0_tri_o[6]; assign PMOD0_7 = PMOD0_tri_z[7] ? 1'bz : PMOD0_tri_o[7]; -// wire [7:0]PMOD1_tri_i; -// wire [7:0]PMOD1_tri_o; -// wire [7:0]PMOD1_tri_z; - -// assign PMOD1_tri_i[0] = PMOD1_0; -// assign PMOD1_tri_i[1] = PMOD1_1; -// assign PMOD1_tri_i[2] = PMOD1_2; -// assign PMOD1_tri_i[3] = PMOD1_3; -// assign PMOD1_tri_i[4] = PMOD1_4; -// assign PMOD1_tri_i[5] = PMOD1_5; -// assign PMOD1_tri_i[6] = PMOD1_6; -// assign PMOD1_tri_i[7] = PMOD1_7; - -// assign PMOD1_0 = PMOD1_tri_z[0] ? 1'bz : PMOD1_tri_o[0]; -// assign PMOD1_1 = PMOD1_tri_z[1] ? 1'bz : PMOD1_tri_o[1]; -// assign PMOD1_2 = PMOD1_tri_z[2] ? 1'bz : PMOD1_tri_o[2]; -// assign PMOD1_3 = PMOD1_tri_z[3] ? 1'bz : PMOD1_tri_o[3]; -// assign PMOD1_4 = PMOD1_tri_z[4] ? 1'bz : PMOD1_tri_o[4]; -// assign PMOD1_5 = PMOD1_tri_z[5] ? 1'bz : PMOD1_tri_o[5]; -// assign PMOD1_6 = PMOD1_tri_z[6] ? 1'bz : PMOD1_tri_o[6]; -// assign PMOD1_7 = PMOD1_tri_z[7] ? 1'bz : PMOD1_tri_o[7]; + wire [7:0]PMOD1_tri_i; + wire [7:0]PMOD1_tri_o; + wire [7:0]PMOD1_tri_z; + + assign PMOD1_tri_i[0] = PMOD1_0; + assign PMOD1_tri_i[1] = PMOD1_1; + assign PMOD1_tri_i[2] = PMOD1_2; + assign PMOD1_tri_i[3] = PMOD1_3; + assign PMOD1_tri_i[4] = PMOD1_4; + assign PMOD1_tri_i[5] = PMOD1_5; + assign PMOD1_tri_i[6] = PMOD1_6; + assign PMOD1_tri_i[7] = PMOD1_7; + + assign PMOD1_0 = PMOD1_tri_z[0] ? 1'bz : PMOD1_tri_o[0]; + assign PMOD1_1 = PMOD1_tri_z[1] ? 1'bz : PMOD1_tri_o[1]; + assign PMOD1_2 = PMOD1_tri_z[2] ? 1'bz : PMOD1_tri_o[2]; + assign PMOD1_3 = PMOD1_tri_z[3] ? 1'bz : PMOD1_tri_o[3]; + assign PMOD1_4 = PMOD1_tri_z[4] ? 1'bz : PMOD1_tri_o[4]; + assign PMOD1_5 = PMOD1_tri_z[5] ? 1'bz : PMOD1_tri_o[5]; + assign PMOD1_6 = PMOD1_tri_z[6] ? 1'bz : PMOD1_tri_o[6]; + assign PMOD1_7 = PMOD1_tri_z[7] ? 1'bz : PMOD1_tri_o[7]; + +// loop connect to preserve IOs +assign PMOD1_tri_o = {DIPSW4,DIPSW4}; +assign PMOD1_tri_z = {DIPSW4,DIPSW4}; + +// loop connect to presrve IOs +assign LED4 = DIPSW4; design_1 design_1_i (.pmoda_tri_i(PMOD0_tri_i), diff --git a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/target_fpga_zcu104/fpga_pinmap.xdc b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/target_fpga_zcu104/fpga_pinmap.xdc index 4a635dd..bb79e54 100644 --- a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/target_fpga_zcu104/fpga_pinmap.xdc +++ b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/target_fpga_zcu104/fpga_pinmap.xdc @@ -932,31 +932,31 @@ set_property PULLUP true [get_ports PMOD0_7] set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets PMOD0_7_IBUF_inst/O] -#set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_0] -#set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_1] -#set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_2] -#set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_3] -#set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_4] -#set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_5] -#set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_6] -#set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_7] -#set_property PACKAGE_PIN J9 [get_ports PMOD1_0] -#set_property PACKAGE_PIN K9 [get_ports PMOD1_1] -#set_property PACKAGE_PIN K8 [get_ports PMOD1_2] -#set_property PACKAGE_PIN L8 [get_ports PMOD1_3] -#set_property PACKAGE_PIN L10 [get_ports PMOD1_4] -#set_property PACKAGE_PIN M10 [get_ports PMOD1_5] -#set_property PACKAGE_PIN M8 [get_ports PMOD1_6] -#set_property PACKAGE_PIN M9 [get_ports PMOD1_7] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_0] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_1] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_2] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_3] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_4] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_5] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_6] +set_property IOSTANDARD LVCMOS33 [get_ports PMOD1_7] +set_property PACKAGE_PIN J9 [get_ports PMOD1_0] +set_property PACKAGE_PIN K9 [get_ports PMOD1_1] +set_property PACKAGE_PIN K8 [get_ports PMOD1_2] +set_property PACKAGE_PIN L8 [get_ports PMOD1_3] +set_property PACKAGE_PIN L10 [get_ports PMOD1_4] +set_property PACKAGE_PIN M10 [get_ports PMOD1_5] +set_property PACKAGE_PIN M8 [get_ports PMOD1_6] +set_property PACKAGE_PIN M9 [get_ports PMOD1_7] -#set_property PULLUP true [get_ports PMOD1_7] -#set_property PULLUP true [get_ports PMOD1_6] -#set_property PULLUP true [get_ports PMOD1_5] -#set_property PULLUP true [get_ports PMOD1_4] -#set_property PULLUP true [get_ports PMOD1_3] -#set_property PULLUP true [get_ports PMOD1_2] -#set_property PULLUP true [get_ports PMOD1_1] -#set_property PULLUP true [get_ports PMOD1_0] +set_property PULLUP true [get_ports PMOD1_7] +set_property PULLUP true [get_ports PMOD1_6] +set_property PULLUP true [get_ports PMOD1_5] +set_property PULLUP true [get_ports PMOD1_4] +set_property PULLUP true [get_ports PMOD1_3] +set_property PULLUP true [get_ports PMOD1_2] +set_property PULLUP true [get_ports PMOD1_1] +set_property PULLUP true [get_ports PMOD1_0] #PMODA pin0 to FTCLK @@ -983,13 +983,31 @@ set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets PMOD0_7_IBUF_inst/O] # LED0 to P0[0] -#set_property PACKAGE_PIN D5 [get_ports {P0[0]}] +set_property IOSTANDARD LVCMOS33 [get_ports {LED4[0]}] +set_property PACKAGE_PIN D5 [get_ports {LED4[0]}] # LED1 to P0[1] -#set_property PACKAGE_PIN D6 [get_ports {P0[1]}] +set_property IOSTANDARD LVCMOS33 [get_ports {LED4[1]}] +set_property PACKAGE_PIN D6 [get_ports {LED4[1]}] # LED2 to P0[2] -#set_property PACKAGE_PIN A5 [get_ports {P0[2]}] +set_property IOSTANDARD LVCMOS33 [get_ports {LED4[2]}] +set_property PACKAGE_PIN A5 [get_ports {LED4[2]}] # LED3 to P0[3] -#set_property PACKAGE_PIN B5 [get_ports {P0[3]}] +set_property IOSTANDARD LVCMOS33 [get_ports {LED4[3]}] +set_property PACKAGE_PIN B5 [get_ports {LED4[3]}] + + +# SW0 to P0[0] +set_property IOSTANDARD LVCMOS33 [get_ports {DIPSW4[0]}] +set_property PACKAGE_PIN E4 [get_ports {DIPSW4[0]}] +# SW1 to P0[1] +set_property IOSTANDARD LVCMOS33 [get_ports {DIPSW4[1]}] +set_property PACKAGE_PIN D4 [get_ports {DIPSW4[1]}] +# SW2 to P0[2] +set_property IOSTANDARD LVCMOS33 [get_ports {DIPSW4[2]}] +set_property PACKAGE_PIN F5 [get_ports {DIPSW4[2]}] +# SW3 to P0[3] +set_property IOSTANDARD LVCMOS33 [get_ports {DIPSW4[3]}] +set_property PACKAGE_PIN F4 [get_ports {DIPSW4[3]}] # SW0 to NRST (Down for active low) #set_property PACKAGE_PIN B4 [get_ports NRST] diff --git a/Cortex-M0/nanosoc/systems/mcu/rtl_sim/adp.cmd b/Cortex-M0/nanosoc/systems/mcu/rtl_sim/adp.cmd index f0a2c33..5fbccc1 100644 --- a/Cortex-M0/nanosoc/systems/mcu/rtl_sim/adp.cmd +++ b/Cortex-M0/nanosoc/systems/mcu/rtl_sim/adp.cmd @@ -7,13 +7,18 @@ A S 7e A a 1000000 -r 10 +r 8 a 20000000 r r a 30000000 r r +a 30000000 +w 12345678 +w 87654321 +a 30000000 +r 2 a 40006000 r r @@ -23,7 +28,7 @@ A v 0xe5e5e5e5 a 80000000 -f 4000 +f 200 A a 90000000 U 4 @@ -31,9 +36,36 @@ U 4 A A 0x90000000 R 5 -A b0000000 -w 1 -r +A 0x60000000 +r 0x14 +A 0x60000010 +w f8 +A 0x60000034 +w 07 +A 0x60000044 +w 0f +A 0x60000010 +r 0x10 +A 0x60007FF0 +F 4 +A 0x60007FF0 +R 4 +A 0x60000010 +r 0x10 +A 0x6000BFF0 +F 4 +A 0x6000BFF0 +R 4 +A 0x60000010 +r 0x10 +A 0x6000FFF0 +R 4 +A 0x60000010 +r 0x10 +A 0x60000018 +w 0x40 +A 0x6000FFF0 +R 4 A A 0x10000000 R diff --git a/Cortex-M0/nanosoc/systems/mcu/rtl_sim/makefile b/Cortex-M0/nanosoc/systems/mcu/rtl_sim/makefile index 9254704..69b6280 100644 --- a/Cortex-M0/nanosoc/systems/mcu/rtl_sim/makefile +++ b/Cortex-M0/nanosoc/systems/mcu/rtl_sim/makefile @@ -91,7 +91,7 @@ SIMULATOR = mti # MTI option #DF#MTI_OPTIONS = -novopt -MTI_OPTIONS = +MTI_OPTIONS = -suppress 2892 MTI_VC_OPTIONS = -f $(TBENCH_VC) # VCS option diff --git a/Cortex-M0/nanosoc/systems/mcu/verilog/nanosoc_chip.v b/Cortex-M0/nanosoc/systems/mcu/verilog/nanosoc_chip.v index 7209c10..2474888 100644 --- a/Cortex-M0/nanosoc/systems/mcu/verilog/nanosoc_chip.v +++ b/Cortex-M0/nanosoc/systems/mcu/verilog/nanosoc_chip.v @@ -821,44 +821,50 @@ localparam CORTEX_M0 = 1; // ************************************************ // ************************************************ // -// ADD YOUR EXPERIMENTAL AHB-MAPPED I/O HERE +// ADD YOUR EXPERIMENTAL AHB-MAPPED WRAPPER HERE // // // ************************************************ - -// -// dummy interface of the form: -// experimental_ip u_exp ( -// .HCLK (HCLK), -// .HRESETn (HRESETn), -// .HSEL (HSEL_exp), -// .HADDR (HADDR_exp), -// .HTRANS (HTRANS_exp), -// .HWRITE (HWRITE_exp), -// .HSIZE (HSIZE_exp), -// .HBURST (HBURST_exp), -// .HPROT (HPROT_exp), -// .HWDATA (HWDATA_exp), -// .HMASTLOCK (HMASTLOCK_exp), -// .HREADY (HREADYMUX_exp), -// .HRDATA (HRDATA_exp), -// .HREADYOUT (HREADYOUT_exp), -// .HRESP (HRESP_exp) -// ); - - // Default slave - cmsdk_ahb_default_slave u_ahb_exp ( - .HCLK (HCLK), - .HRESETn (HRESETn), - .HSEL (HSEL_exp), - .HTRANS (HTRANS_exp), - .HREADY (HREADYMUX_exp), - .HREADYOUT (HREADYOUT_exp), - .HRESP (HRESP_exp) + soclabs_ahb_aes128_ctrl u_exp_aes128 ( + .ahb_hclk (HCLK), + .ahb_hresetn (HRESETn), + .ahb_hsel (HSEL_exp), + .ahb_haddr16 (HADDR_exp[15:0]), + .ahb_htrans (HTRANS_exp), + .ahb_hwrite (HWRITE_exp), + .ahb_hsize (HSIZE_exp), +// .ahb_hburst (HBURST_exp), + .ahb_hprot (HPROT_exp), + .ahb_hwdata (HWDATA_exp), +// .ahb_hmastlock (HMASTLOCK_exp), + .ahb_hready (HREADYMUX_exp), + .ahb_hrdata (HRDATA_exp), + .ahb_hreadyout (HREADYOUT_exp), + .ahb_hresp (HRESP_exp), + .drq_ipdma128 ( ), + .dlast_ipdma128 (1'b0), + .drq_opdma128 ( ), + .dlast_opdma128 (1'b0), + .irq_key128 ( ), + .irq_ip128 ( ), + .irq_op128 ( ), + .irq_error ( ), + .irq_merged ( ) ); + +// // Default slave +// cmsdk_ahb_default_slave u_ahb_exp ( +// .HCLK (HCLK), +// .HRESETn (HRESETn), +// .HSEL (HSEL_exp), +// .HTRANS (HTRANS_exp), +// .HREADY (HREADYMUX_exp), +// .HREADYOUT (HREADYOUT_exp), +// .HRESP (HRESP_exp) +// ); +// assign HRDATA_exp = 32'heaedeaed; // Tie off Expansion Address Expansion Data - assign HRDATA_exp = 32'heaedeaed; // Tie off Expansion Address Expansion Data assign HRUSER_exp = 2'b00; // ************************************************ diff --git a/Cortex-M0/nanosoc/systems/mcu/verilog/soclabs_ahb_aes128_ctrl.v b/Cortex-M0/nanosoc/systems/mcu/verilog/soclabs_ahb_aes128_ctrl.v new file mode 100644 index 0000000..27796a3 --- /dev/null +++ b/Cortex-M0/nanosoc/systems/mcu/verilog/soclabs_ahb_aes128_ctrl.v @@ -0,0 +1,3015 @@ + //----------------------------------------------------------------------------- +// top-level soclabs example AHB interface +// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license. +// +// Contributors +// +// David Flynn (d.w.flynn@soton.ac.uk) +// +// Copyright (C) 2023, SoC Labs (www.soclabs.org) +//----------------------------------------------------------------------------- + +module soclabs_ahb_aes128_ctrl( +// ------------------------------------------------------- +// MCU interface +// ------------------------------------------------------- + input wire ahb_hclk, // Clock + input wire ahb_hresetn, // Reset + input wire ahb_hsel, // Device select + input wire [15:0] ahb_haddr16, // Address for byte select + input wire [1:0] ahb_htrans, // Transfer control + input wire [2:0] ahb_hsize, // Transfer size + input wire [3:0] ahb_hprot, // Protection control + input wire ahb_hwrite, // Write control + input wire ahb_hready, // Transfer phase done + input wire [31:0] ahb_hwdata, // Write data + output wire ahb_hreadyout, // Device ready + output wire [31:0] ahb_hrdata, // Read data output + output wire ahb_hresp, // Device response +// stream data + output wire drq_ipdma128, // (to) DMAC input burst request + input wire dlast_ipdma128,// (from) DMAC input burst end (last transfer) + output wire drq_opdma128, // (to) DMAC output dma burst request + input wire dlast_opdma128,// (from) DMAC output burst end (last transfer) + output wire irq_key128, + output wire irq_ip128, + output wire irq_op128, + output wire irq_error, + output wire irq_merged // combined interrrupt request (to CPU) + ); + + //---------------------------------------------------------------- + // Internal parameter definitions. + //---------------------------------------------------------------- + +///typedef struct { +/// __I uint32_t CORE_NAME0; /* 0x0000 */ +/// __I uint32_t CORE_NAME1; /* 0x0004 */ +/// __I uint32_t CORE_VERSION; /* 0x0008 */ +/// uint32_t RESRV0C; /* 0x000C */ +/// __IO uint32_t CONTROL; /* 0x0010 */ +/// __O uint32_t CONTROL_SET; /* 0x0014 */ +/// __O uint32_t CONTROL_CLR; /* 0x0018 */ +/// __I uint32_t STATUS; /* 0x001c */ +/// __I uint32_t QUALIFIER; /* 0x0020 */ +/// uint32_t RESRV24[3]; /* 0x0024 - 2F*/ +/// __IO uint32_t DRQ_MSK; /* 0x0030 */ +/// __O uint32_t DRQ_MSK_SET; /* 0x0034 */ +/// __O uint32_t DRQ_MSK_CLR; /* 0x0038 */ +/// __I uint32_t DRQ_STATUS; /* 0x003C */ +/// __IO uint32_t IRQ_MSK; /* 0x0040 */ +/// __O uint32_t IRQ_MSK_SET; /* 0x0044 */ +/// __O uint32_t IRQ_MSK_CLR; /* 0x0048 */ +/// __I uint32_t IRQ_STATUS; /* 0x004C */ +/// uint32_t RESRV50[1024-80] /* 0x0050-0x3FFC (1024-(20*4)) */ +/// __IO unit32_t KYBUF128[1020]; /* 0x4000-7FEF */ (1024-4) +/// __IO unit32_t KYBUF128END; /* 0x7FF0-7FFF */ +/// __IO unit32_t IPBUF128[1020]; /* 0x8000-BFEF */ (1024-4) +/// __IO unit32_t IPBUF128END; /* 0xBFF0-BFFF */ +/// __IO unit32_t OPBUF128[1020]; /* 0xC000-FFEF */ (1024-4) +/// __IO unit32_t OPBUF128END; /* 0xFFF0-FFFF */ +///} AES128_TypeDef; + + +// CORE ID + localparam ADDR_CORE_NAME0 = 16'h0000; + localparam ADDR_CORE_NAME1 = 16'h0004; + localparam ADDR_CORE_VERSION= 16'h0008; + localparam CORE_NAME0 = 32'h61657331; // "aes1" + localparam CORE_NAME1 = 32'h32382020; // "28 " + localparam CORE_VERSION = 32'h302e3630; // "0.01" + +// CTRL control register with bit-set/bit-clear options + localparam ADDR_CTRL = 16'h0010; + localparam ADDR_CTRL_SET = 16'h0014; + localparam ADDR_CTRL_CLR = 16'h0018; + localparam CTRL_REG_WIDTH = 8; + localparam CTRL_BIT_MAX = (CTRL_REG_WIDTH-1); + localparam CTRL_KEY_REQ_BIT = 0; + localparam CTRL_IP_REQ_BIT = 1; + localparam CTRL_OP_REQ_BIT = 2; + localparam CTRL_ERR_REQ_BIT = 3; + localparam CTRL_KEYOK_BIT = 4; + localparam CTRL_VALID_BIT = 5; + localparam CTRL_BYPASS_BIT = 6; + localparam CTRL_ENCODE_BIT = 7; +// STAT status regisyer + localparam ADDR_STAT = 16'h001c; + localparam STAT_REG_WIDTH = 8; + localparam STAT_BIT_MAX = (STAT_REG_WIDTH-1); + localparam STAT_KEYREQ_BIT = 0; + localparam STAT_INPREQ_BIT = 1; + localparam STAT_OUTREQ_BIT = 2; + localparam STAT_ERROR_BIT = 3; + localparam STAT_KEYOK_BIT = 4; + localparam STAT_VALID_BIT = 5; + +// QUAL qualifier field + localparam ADDR_QUAL = 16'h0020; + localparam QUAL_REG_WIDTH = 32; + localparam QUAL_BIT_MAX = (QUAL_REG_WIDTH-1); + +// DREQ DMAC request control with bit-set/bit-clear options + localparam ADDR_DREQ = 16'h0030; + localparam ADDR_DREQ_SET = 16'h0034; + localparam ADDR_DREQ_CLR = 16'h0038; + localparam ADDR_DREQ_ACT = 16'h003c; + localparam DREQ_REG_WIDTH = 3; + localparam DREQ_BIT_MAX = (DREQ_REG_WIDTH-1); + localparam REQ_KEYBUF_BIT = 0; + localparam REQ_IP_BUF_BIT = 1; + localparam REQ_OP_BUF_BIT = 2; + +// IREQ CPU interrupt request control with bit-set/bit-clear options + localparam ADDR_IREQ = 16'h0040; + localparam ADDR_IREQ_SET = 16'h0044; + localparam ADDR_IREQ_CLR = 16'h0048; + localparam ADDR_IREQ_ACT = 16'h004c; + localparam IREQ_REG_WIDTH = 4; + localparam IREQ_BIT_MAX = (IREQ_REG_WIDTH-1); + localparam REQ_ERROR_BIT = 3; + + localparam ADDR_KEY_BASE = 16'h4000; + localparam ADDR_KEY0 = 16'h4000; + localparam ADDR_KEY3 = 16'h400c; + localparam ADDR_KEY7 = 16'h401c; + + localparam ADDR_IBUF_BASE = 16'h8000; + localparam ADDR_IBUF_0 = 16'h8000; + localparam ADDR_IBUF_3 = 16'h800c; + + localparam ADDR_OBUF_BASE = 16'hc000; + localparam ADDR_OBUF_3 = 16'hc00c; + + + // -------------------------------------------------------------------------- + // Internal regs/wires + // -------------------------------------------------------------------------- + + reg [15:0] addr16_r; + reg sel_r; + reg wcyc_r; + reg rcyc_r; + reg [3:0] byte4_r; + + wire key128_load_ack; + wire ip128_load_ack; + wire op128_load_ack; + + // -------------------------------------------------------------------------- + // AHB slave byte buffer interface, support for unaligned data transfers + // -------------------------------------------------------------------------- + + wire [1:0] byt_adr = ahb_haddr16[1:0]; + // generate next byte enable decodes for Word/Half/Byte CPU/DMA accesses + wire [3:0] byte_nxt; + assign byte_nxt[0] = (ahb_hsize[1])|((ahb_hsize[0])&(!byt_adr[1]))|(byt_adr[1:0]==2'b00); + assign byte_nxt[1] = (ahb_hsize[1])|((ahb_hsize[0])&(!byt_adr[1]))|(byt_adr[1:0]==2'b01); + assign byte_nxt[2] = (ahb_hsize[1])|((ahb_hsize[0])&( byt_adr[1]))|(byt_adr[1:0]==2'b10); + assign byte_nxt[3] = (ahb_hsize[1])|((ahb_hsize[0])&( byt_adr[1]))|(byt_adr[1:0]==2'b11); + + // de-pipelined registered access signals + always @(posedge ahb_hclk or negedge ahb_hresetn) + if (!ahb_hresetn) + begin + addr16_r <= 16'h0000; + sel_r <= 1'b0; + wcyc_r <= 1'b0; + rcyc_r <= 1'b0; + byte4_r <= 4'b0000; + end else if (ahb_hready) + begin + addr16_r <= (ahb_hsel & ahb_htrans[1]) ? ahb_haddr16 : addr16_r; + sel_r <= (ahb_hsel & ahb_htrans[1]); + wcyc_r <= (ahb_hsel & ahb_htrans[1] & ahb_hwrite); + rcyc_r <= (ahb_hsel & ahb_htrans[1] & !ahb_hwrite); + byte4_r <= (ahb_hsel & ahb_htrans[1]) ? byte_nxt[3:0] : 4'b0000; + end + + +// pipelined "early" last access decodes, for PL230 dma_ack timing to deassert dma requests +// wire ahb128_last = ahb_hsel & ahb_htrans[1] & ahb_hready & ahb_haddr16[3] & ahb_haddr16[2] & byte_nxt[3]; +// wire ahb128_wlast = ahb_last & ahb_hwrite & |ahb_haddr[15:14]; // address phase of last write transfer +// wire ahb128_rlast = ahb_last & !ahb_hwrite & |ahb_haddr[15:14]; // address phase of last read transfer + + wire wlast128 = |ahb_haddr16[15:14] & addr16_r[3] & addr16_r[2] & byte4_r[3] & wcyc_r; // write last pulse + wire rlast128 = &ahb_haddr16[15:14] & addr16_r[3] & addr16_r[2] & byte4_r[3] & rcyc_r; // read last pulse + + //---------------------------------------------------------------- + // API register state and wiring + // + //---------------------------------------------------------------- + + reg [CTRL_BIT_MAX:0] control; + reg [QUAL_BIT_MAX:0] param; + reg [DREQ_BIT_MAX:0] drq_enable; + reg [IREQ_BIT_MAX:0] irq_enable; + + wire [STAT_BIT_MAX:0] status; + wire [DREQ_BIT_MAX:0] drq_active; + wire [IREQ_BIT_MAX:0] irq_active; + + wire [31:0] rd_keybuf; + wire [31:0] rd_ipbuf; + wire [31:0] rd_opbuf; + + //---------------------------------------------------------------- + // API write decoder + // + //---------------------------------------------------------------- + + wire sel_mode = sel_r & (addr16_r[15: 8] == 0); + wire sel_keybuf = sel_r & (addr16_r[15:14] == 1); + wire sel_ipbuf = sel_r & (addr16_r[15:14] == 2); + wire sel_opbuf = sel_r & (addr16_r[15:14] == 3); +// add address map "last" transfer signalling when last (byte) of alias map is written + wire alast_key128 = sel_keybuf & wcyc_r & (&addr16_r[13:2]) & byte4_r[3]; + wire alast_ip128 = sel_ipbuf & wcyc_r & (&addr16_r[13:2]) & byte4_r[3]; + wire alast_op128 = sel_opbuf & rcyc_r & (&addr16_r[13:2]) & byte4_r[3]; + + always @(posedge ahb_hclk or negedge ahb_hresetn) + if (!ahb_hresetn) begin + control <= {CTRL_REG_WIDTH{1'b0}}; + param <= {QUAL_REG_WIDTH{1'b0}}; + drq_enable <= {DREQ_REG_WIDTH{1'b0}}; + irq_enable <= {IREQ_REG_WIDTH{1'b0}}; + end + else if (sel_mode & wcyc_r & byte4_r[0]) + case (addr16_r) + ADDR_CTRL : control <= ahb_hwdata[CTRL_BIT_MAX:0]; // overwrite ctl reg + ADDR_CTRL_SET: control <= ahb_hwdata[CTRL_BIT_MAX:0] | control; // bit set ctl mask pattern + ADDR_CTRL_CLR: control <= ~ahb_hwdata[CTRL_BIT_MAX:0] & control; // bit clear ctl mask pattern + ADDR_QUAL : param <= ahb_hwdata[QUAL_BIT_MAX:0]; // write qual pattern + ADDR_DREQ : drq_enable <= ahb_hwdata[DREQ_BIT_MAX:0]; // overwrite dreq reg + ADDR_DREQ_SET: drq_enable <= ahb_hwdata[DREQ_BIT_MAX:0] | drq_enable; // bit set dreq mask pattern + ADDR_DREQ_CLR: drq_enable <= ~ahb_hwdata[DREQ_BIT_MAX:0] & drq_enable; // bit clear dreq mask pattern + ADDR_IREQ : irq_enable <= ahb_hwdata[IREQ_BIT_MAX:0]; // overwrite ireq reg + ADDR_IREQ_SET: irq_enable <= ahb_hwdata[IREQ_BIT_MAX:0] | irq_enable; // bit set ireq mask pattern + ADDR_IREQ_CLR: irq_enable <= ~ahb_hwdata[IREQ_BIT_MAX:0] & irq_enable; // bit clear ireq mask pattern + default: ; + endcase + else if (sel_keybuf & wcyc_r & (dlast_ipdma128 | alast_key128)) // key terminate + drq_enable[0] <= 1'b0; + else if (sel_ipbuf & wcyc_r & (dlast_ipdma128 | alast_ip128)) // ip-buffer terminate + drq_enable[1] <= 1'b0; + else if (sel_opbuf & rcyc_r & (dlast_opdma128 | alast_op128)) // op-buffer complete + drq_enable[2] <= 1'b0; + + //---------------------------------------------------------------- + // API read decoder + // + //---------------------------------------------------------------- + +reg [31:0] rdata32; // mux read data + + always @* + begin : read_decoder + rdata32 = 32'hbad0bad; + if (sel_r & rcyc_r) + case (addr16_r) + ADDR_CORE_NAME0 : rdata32 = CORE_NAME0; + ADDR_CORE_NAME1 : rdata32 = CORE_NAME1; + ADDR_CORE_VERSION : rdata32 = CORE_VERSION; + ADDR_CTRL : rdata32 = {{(32-CTRL_REG_WIDTH){1'b0}}, control}; + ADDR_STAT : rdata32 = {{(32-STAT_REG_WIDTH){1'b0}}, status}; + ADDR_QUAL : rdata32 = {{(32-QUAL_REG_WIDTH){1'b0}}, param}; + ADDR_DREQ : rdata32 = {{(32-DREQ_REG_WIDTH){1'b0}}, drq_enable}; + ADDR_DREQ_ACT : rdata32 = {{(32-DREQ_REG_WIDTH){1'b0}}, drq_active}; + ADDR_IREQ : rdata32 = {{(32-IREQ_REG_WIDTH){1'b0}}, irq_enable}; + ADDR_IREQ_ACT : rdata32 = {{(32-DREQ_REG_WIDTH){1'b0}}, irq_active}; + default: + if (sel_keybuf) rdata32 = rd_keybuf; + else if (sel_ipbuf) rdata32 = rd_ipbuf; + else if (sel_opbuf) rdata32 = rd_opbuf; + endcase + end // read_decoder + + assign ahb_hrdata = rdata32; + + assign ahb_hreadyout = 1'b1; // zero wait state interface + assign ahb_hresp = 1'b0; + + // -------------------------------------------------------------------------- + // Key Input Buffer - keybuf + // -------------------------------------------------------------------------- + + wire [127:0] key128_be; + + soclabs_iobuf_reg128 + #(.WRITE_ONLY (1), + .WRITE_ZPAD (0)) + u_reg128_key + ( + .clk (ahb_hclk ), // Clock + .rst_b (ahb_hresetn ), // Reset + .sel_r (sel_keybuf ), // Bank decode select + .wcyc_r (wcyc_r ), // Write cycle (wdata32 valid) + .rcyc_r (rcyc_r ), // Read cycle (return rdata32) + .word2_r (addr16_r[3:2] ), // Address for word select + .byte4_r (byte4_r[3:0] ), // Byte select decoded (up to 4 enabled) + .wdata32 (ahb_hwdata[31:0]), // Write data (byte lane qualified) + .rdata32 (rd_keybuf ), // Read data output + .dma128_ack (key128_load_ack ), // DMA burst acknowledge + .out128_le ( ), // Big-Endian 128-bit value + .out128_be (key128_be ) // Big-Endian 128-bit value + ); + + // -------------------------------------------------------------------------- + // Data Input Buffer - ipbuf + // -------------------------------------------------------------------------- + + wire [127:0] ip128_le; + wire [127:0] ip128_be; + + soclabs_iobuf_reg128 + #(.WRITE_ONLY (0), + .WRITE_ZPAD (1)) + u_reg128_ip + ( + .clk (ahb_hclk ), // Clock + .rst_b (ahb_hresetn ), // Reset + .sel_r (sel_ipbuf ), // Bank decode select + .wcyc_r (wcyc_r ), // Write cycle (wdata32 valid) + .rcyc_r (rcyc_r ), // Read cycle (return rdata32) + .word2_r (addr16_r[3:2] ), // Address for word select + .byte4_r (byte4_r[3:0] ), // Byte select decoded (up to 4 enabled) + .wdata32 (ahb_hwdata[31:0]), // Write data (byte lane qualified) + .rdata32 (rd_ipbuf ), // Read data output + .dma128_ack (ip128_load_ack ), // DMA burst acknowledge + .out128_le (ip128_le ), // Big-Endian 128-bit value + .out128_be (ip128_be ) // Big-Endian 128-bit value + ); + + // -------------------------------------------------------------------------- + // Data Output Buffer - opbufsel_keybuf + // -------------------------------------------------------------------------- + + wire [127:0] op128_be; + wire [127:0] op128_muxed = (control[CTRL_BYPASS_BIT]) ? ip128_be : op128_be; + + wire [31:0] op_slice32 [0:3]; + assign op_slice32[3] = {op128_muxed[ 7: 0],op128_muxed[ 15: 8],op128_muxed[ 23: 16],op128_muxed[ 31: 24]}; + assign op_slice32[2] = {op128_muxed[ 39: 32],op128_muxed[ 47: 40],op128_muxed[ 55: 48],op128_muxed[ 63: 56]}; + assign op_slice32[1] = {op128_muxed[ 71: 64],op128_muxed[ 79: 72],op128_muxed[ 87: 80],op128_muxed[ 95: 88]}; + assign op_slice32[0] = {op128_muxed[103: 96],op128_muxed[111:104],op128_muxed[119:112],op128_muxed[127:120]}; + + // 32-bit addressed read data + assign rd_opbuf = op_slice32[addr16_r[3:2]]; + + assign op128_load_ack = (sel_opbuf & rcyc_r & addr16_r[3] & addr16_r[2] & byte4_r[3]); + + // -------------------------------------------------------------------------- + // example aes128 engine timing + // -------------------------------------------------------------------------- + // -------------------------------------------------------------------------- + // AES-specific control interface + // -------------------------------------------------------------------------- + +wire aes128_encode = control[CTRL_ENCODE_BIT]; +wire aes256_keysize = 1'b0; + +wire aes_keyloaded_pulse = key128_load_ack; // pulse on last byte load of key128 +wire aes_dataloaded_pulse= ip128_load_ack; // pulse on last byte load of text128 +wire aes_ready; +wire aes_valid; + +// state machine control +reg aes_ready_del; +reg aes_init; +reg aes_next; +reg aes_key_busy; +reg aes_key_rdy; +reg aes_res_busy; +reg aes_res_rdy; + + always @(posedge ahb_hclk or negedge ahb_hresetn) + if (!ahb_hresetn) begin + aes_ready_del <= 1'b0; + aes_init <= 1'b0; + aes_next <= 1'b0; + aes_key_busy <= 1'b0; + aes_key_rdy <= 1'b0; + aes_res_busy <= 1'b0; + aes_res_rdy <= 1'b0; + end else begin + aes_ready_del <= aes_ready; // delay for rising edge detect + aes_init <= aes_keyloaded_pulse; + aes_next <= aes_dataloaded_pulse; + aes_key_busy <= (aes_init) | (aes_key_busy & !(aes_ready & !aes_ready_del)); // hold until key expansion done + aes_key_rdy <= (aes_key_busy & aes_ready & !aes_ready_del) // expanded key ready + | (aes_key_rdy & !(sel_keybuf & wcyc_r)); // hold until any key update + aes_res_busy <= (aes_next) | (aes_res_busy & !(aes_ready & !aes_ready_del)); // hold until block processing done + aes_res_rdy <= (aes_res_busy & aes_ready & !aes_ready_del) // block ready + | (aes_res_rdy & !op128_load_ack); // hold until output transferred + end + + assign drq_active[REQ_KEYBUF_BIT] = control[CTRL_KEY_REQ_BIT] | (!aes_key_busy & !aes_key_rdy & !wlast128); + assign drq_active[REQ_IP_BUF_BIT] = control[CTRL_IP_REQ_BIT] | (!aes_res_busy & !aes_res_rdy & aes_key_rdy & !wlast128); + assign drq_active[REQ_OP_BUF_BIT] = control[CTRL_OP_REQ_BIT] | (!aes_res_busy & aes_res_rdy & !rlast128); + +// input DMA channel shared by Key and Data-In + assign drq_ipdma128 = (drq_enable[REQ_KEYBUF_BIT] & drq_active[REQ_KEYBUF_BIT]) // if key DMA enabled + | (drq_enable[REQ_IP_BUF_BIT] & drq_active[REQ_IP_BUF_BIT]) // if ip128 DMA requested + ; + +// output DMA channel for Data-Out + assign drq_opdma128 = (drq_enable[REQ_OP_BUF_BIT] & drq_active[REQ_OP_BUF_BIT]); // if op128 DMA requested + +// and Interrupt requests are masked out if corresponding DMA requests are enabled + assign irq_active[REQ_KEYBUF_BIT] = drq_active[REQ_KEYBUF_BIT] & !drq_enable[REQ_KEYBUF_BIT]; + assign irq_active[REQ_IP_BUF_BIT] = drq_active[REQ_IP_BUF_BIT] & !drq_enable[REQ_IP_BUF_BIT]; + assign irq_active[REQ_OP_BUF_BIT] = drq_active[REQ_OP_BUF_BIT] & !drq_enable[REQ_OP_BUF_BIT]; + assign irq_active[REQ_ERROR_BIT ] = control[CTRL_ERR_REQ_BIT] | (!aes_res_busy & !aes_key_rdy); // error raised in SW + + assign irq_key128 = irq_active[REQ_KEYBUF_BIT] & !drq_active[REQ_KEYBUF_BIT]; + assign irq_ip128 = irq_active[REQ_IP_BUF_BIT] & !drq_active[REQ_IP_BUF_BIT]; + assign irq_op128 = irq_active[REQ_OP_BUF_BIT] & !drq_active[REQ_OP_BUF_BIT]; + assign irq_error = irq_active[REQ_ERROR_BIT ]; +// merge and mask if not DRQ + assign irq_merged = irq_key128 | irq_ip128 | irq_op128 | irq_error; + + +// wire up status port + assign status[2:0] = control [2:0]; + assign status[STAT_ERROR_BIT] = (!aes_res_busy & !aes_key_rdy); + assign status[STAT_KEYOK_BIT] = aes_key_rdy; + assign status[STAT_VALID_BIT] = aes_res_rdy; + assign status[7:6] = control [7:6]; + + //---------------------------------------------------------------- + // core instantiation. + //---------------------------------------------------------------- + aes_core core( + .clk(ahb_hclk), + .reset_n(ahb_hresetn), + + .encdec(aes128_encode), + .init(aes_init), + .next(aes_next), + .ready(aes_ready), + + .key({key128_be,key128_be}), + .keylen(aes256_keysize), + + .block(ip128_be), + .result(op128_be), + .result_valid(aes_valid) + ); + +endmodule + +module soclabs_iobuf_reg128 + #( + parameter WRITE_ONLY = 0, + parameter WRITE_ZPAD = 0 + ) ( +// ------------------------------------------------------- +// de-pipelined register interface +// ------------------------------------------------------- +// ahb + input wire clk, // Clock + input wire rst_b, // Reset + input wire sel_r, // Bank decode select + input wire wcyc_r, // Write cycle (wdata32 valid) + input wire rcyc_r, // Read cycle (return rdata32) + input wire [1:0] word2_r, // Address for word select + input wire [3:0] byte4_r, // Byte select decoded (up to 4 enabled) + input wire [31:0] wdata32, // Write data (byte lae qualified) + output wire [31:0] rdata32, // Read data output + output wire dma128_ack, // DMA burst acknowledge + output wire [127:0] out128_le, // Litte-Endian 128-bit value + output wire [127:0] out128_be // Big-Endian 128-bit value +) ; + + reg [7:0] byte0 [0:3]; + reg [7:0] byte1 [0:3]; + reg [7:0] byte2 [0:3]; + reg [7:0] byte3 [0:3]; + reg ack128; + + wire zpad_cfg = (WRITE_ZPAD==0) ? 1'b0 : 1'b1; + +// byte-0 array; flush on write to word-0, byte-0 +// else addressed word byte-0 write + always @(posedge clk or negedge rst_b) + if (!rst_b) + begin byte0[0] <= 8'h00; byte0[1] <= 8'h00; byte0[2] <= 8'h00; byte0[3] <= 8'h00; end + else if (zpad_cfg & sel_r & wcyc_r & byte4_r[0] & !word2_r[1] & !word2_r[0]) // Z-PAD rest + begin byte0[0] <= wdata32[ 7: 0]; byte0[1] <= 8'h00; byte0[2] <= 8'h00; byte0[3] <= 8'h00; end + else if (sel_r & wcyc_r & byte4_r[0]) + byte0[word2_r[1:0]] <= wdata32[ 7: 0]; + +// byte-1 array; flush on write to word-0, byte-0 if byte-1 not also written +// flush rest on write to word-0, byte-0 and byte-1 also written +// else address word byte-1 write + always @(posedge clk or negedge rst_b) + if (!rst_b) + begin byte1[0] <= 8'h00; byte1[1] <= 8'h00; byte1[2] <= 8'h00; byte1[3] <= 8'h00; end + else if (zpad_cfg & sel_r & wcyc_r & !byte4_r[1] & !word2_r[1] & !word2_r[0] & byte4_r[0]) // Z-PAD + begin byte1[0] <= 8'h00; byte1[1] <= 8'h00; byte1[2] <= 8'h00; byte1[3] <= 8'h00; end + else if (zpad_cfg & sel_r & wcyc_r & byte4_r[1] & !word2_r[1] & !word2_r[0] & byte4_r[0]) // Z-PAD rest + begin byte1[0] <= wdata32[15: 8]; byte1[1] <= 8'h00; byte1[2] <= 8'h00; byte1[3] <= 8'h00; end + else if (sel_r & wcyc_r & byte4_r[1]) + byte1[word2_r[1:0]] <= wdata32[15: 8]; + +// byte-2 array; flush on write to word-0, byte-0 if byte-2 not also written +// flush rest on write to word-0, byte-0 and byte-2 also written +// else address word byte-2 write + always @(posedge clk or negedge rst_b) + if (!rst_b) + begin byte2[0] <= 8'h00; byte2[1] <= 8'h00; byte2[2] <= 8'h00; byte2[3] <= 8'h00; end + else if (zpad_cfg & sel_r & wcyc_r & !byte4_r[2] & !word2_r[1] & !word2_r[0] & byte4_r[0]) // Z-PAD + begin byte2[0] <= 8'h00; byte2[1] <= 8'h00; byte2[2] <= 8'h00; byte2[3] <= 8'h00; end + else if (zpad_cfg & sel_r & wcyc_r & byte4_r[2] & !word2_r[1] & !word2_r[0] & byte4_r[0]) // Z-PAD rest + begin byte2[0] <= wdata32[23:16]; byte2[1] <= 8'h00; byte2[2] <= 8'h00; byte2[3] <= 8'h00; end + else if (sel_r & wcyc_r & byte4_r[2]) + byte2[word2_r[1:0]] <= wdata32[23:16]; + +// byte-3 array; flush on write to word-0, byte-0 if byte-3 not also written +// flush rest on write to word-0, byte-0 and byte-3 also written +// else address word byte-3 write + always @(posedge clk or negedge rst_b) + if (!rst_b) + begin byte3[0] <= 8'h00; byte3[1] <= 8'h00; byte3[2] <= 8'h00; byte3[3] <= 8'h00; end + else if (zpad_cfg & sel_r & wcyc_r & !byte4_r[3] & !word2_r[1] & !word2_r[0] & byte4_r[0]) // Z-PAD + begin byte3[0] <= 8'h00; byte3[1] <= 8'h00; byte3[2] <= 8'h00; byte3[3] <= 8'h00; end + else if (zpad_cfg & sel_r & wcyc_r & byte4_r[3] & !word2_r[1] & !word2_r[0] & byte4_r[0]) // Z-PAD rest + begin byte3[0] <= wdata32[31:24]; byte3[1] <= 8'h00; byte3[2] <= 8'h00; byte3[3] <= 8'h00; end + else if (sel_r & wcyc_r & byte4_r[3]) + byte3[word2_r[1:0]] <= wdata32[31:24]; + + // ack on write to final byte [15] + always @(posedge clk or negedge rst_b) + if (!rst_b) + ack128 <= 1'b0; + else + ack128 <= sel_r & wcyc_r & word2_r[1] & word2_r[0] & byte4_r[3]; + + assign dma128_ack = ack128; + +// byte reverse per word for Big Endian AES engine + assign out128_be = {byte0[0], byte1[0], byte2[0], byte3[0], + byte0[1], byte1[1], byte2[1], byte3[1], + byte0[2], byte1[2], byte2[2], byte3[2], + byte0[3], byte1[3], byte2[3], byte3[3]}; + +// byte reverse per word for Big Endian AES engine + assign out128_le = {byte3[3], byte2[3], byte1[3], byte0[3], + byte3[2], byte2[2], byte1[2], byte0[2], + byte3[1], byte2[1], byte1[1], byte0[1], + byte3[0], byte2[0], byte1[0], byte0[0]}; + +// little-endian read data (if not Write-Only) + assign rdata32 = (sel_r & rcyc_r & (WRITE_ONLY == 0)) + ? {byte3[word2_r[1:0]], byte2[word2_r[1:0]], + byte1[word2_r[1:0]], byte0[word2_r[1:0]]} + : 32'h00000000; + +endmodule + +//====================================================================== +// +// aes_core.v +// ---------- +// The AES core. This core supports key size of 128, and 256 bits. +// Most of the functionality is within the submodules. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2013, 2014, Secworks Sweden AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +`default_nettype none + +module aes_core( + input wire clk, + input wire reset_n, + + input wire encdec, + input wire init, + input wire next, + output wire ready, + + input wire [255 : 0] key, + input wire keylen, + + input wire [127 : 0] block, + output wire [127 : 0] result, + output wire result_valid + ); + + + + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + localparam CTRL_IDLE = 2'h0; + localparam CTRL_INIT = 2'h1; + localparam CTRL_NEXT = 2'h2; + + + //---------------------------------------------------------------- + // Registers including update variables and write enable. + //---------------------------------------------------------------- + reg [1 : 0] aes_core_ctrl_reg; + reg [1 : 0] aes_core_ctrl_new; + reg aes_core_ctrl_we; + + reg result_valid_reg; + reg result_valid_new; + reg result_valid_we; + + reg ready_reg; + reg ready_new; + reg ready_we; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg init_state; + + wire [127 : 0] round_key; + wire key_ready; + + reg enc_next; + wire [3 : 0] enc_round_nr; + wire [127 : 0] enc_new_block; + wire enc_ready; + wire [31 : 0] enc_sboxw; + + reg dec_next; + wire [3 : 0] dec_round_nr; + wire [127 : 0] dec_new_block; + wire dec_ready; + + reg [127 : 0] muxed_new_block; + reg [3 : 0] muxed_round_nr; + reg muxed_ready; + + wire [31 : 0] keymem_sboxw; + +/* verilator lint_off UNOPTFLAT */ + reg [31 : 0] muxed_sboxw; + wire [31 : 0] new_sboxw; +/* verilator lint_on UNOPTFLAT */ + + + //---------------------------------------------------------------- + // Instantiations. + //---------------------------------------------------------------- + aes_encipher_block enc_block( + .clk(clk), + .reset_n(reset_n), + + .next(enc_next), + + .keylen(keylen), + .round(enc_round_nr), + .round_key(round_key), + + .sboxw(enc_sboxw), + .new_sboxw(new_sboxw), + + .block(block), + .new_block(enc_new_block), + .ready(enc_ready) + ); + + + aes_decipher_block dec_block( + .clk(clk), + .reset_n(reset_n), + + .next(dec_next), + + .keylen(keylen), + .round(dec_round_nr), + .round_key(round_key), + + .block(block), + .new_block(dec_new_block), + .ready(dec_ready) + ); + + + aes_key_mem keymem( + .clk(clk), + .reset_n(reset_n), + + .key(key), + .keylen(keylen), + .init(init), + + .round(muxed_round_nr), + .round_key(round_key), + .ready(key_ready), + + .sboxw(keymem_sboxw), + .new_sboxw(new_sboxw) + ); + + + aes_sbox sbox_inst(.sboxw(muxed_sboxw), .new_sboxw(new_sboxw)); + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign ready = ready_reg; + assign result = muxed_new_block; + assign result_valid = result_valid_reg; + + + //---------------------------------------------------------------- + // reg_update + // + // Update functionality for all registers in the core. + // All registers are positive edge triggered with asynchronous + // active low reset. All registers have write enable. + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin: reg_update + if (!reset_n) + begin + result_valid_reg <= 1'b0; + ready_reg <= 1'b1; + aes_core_ctrl_reg <= CTRL_IDLE; + end + else + begin + if (result_valid_we) + result_valid_reg <= result_valid_new; + + if (ready_we) + ready_reg <= ready_new; + + if (aes_core_ctrl_we) + aes_core_ctrl_reg <= aes_core_ctrl_new; + end + end // reg_update + + + //---------------------------------------------------------------- + // sbox_mux + // + // Controls which of the encipher datapath or the key memory + // that gets access to the sbox. + //---------------------------------------------------------------- + always @* + begin : sbox_mux + if (init_state) + begin + muxed_sboxw = keymem_sboxw; + end + else + begin + muxed_sboxw = enc_sboxw; + end + end // sbox_mux + + + //---------------------------------------------------------------- + // encdex_mux + // + // Controls which of the datapaths that get the next signal, have + // access to the memory as well as the block processing result. + //---------------------------------------------------------------- + always @* + begin : encdec_mux + enc_next = 1'b0; + dec_next = 1'b0; + + if (encdec) + begin + // Encipher operations + enc_next = next; + muxed_round_nr = enc_round_nr; + muxed_new_block = enc_new_block; + muxed_ready = enc_ready; + end + else + begin + // Decipher operations + dec_next = next; + muxed_round_nr = dec_round_nr; + muxed_new_block = dec_new_block; + muxed_ready = dec_ready; + end + end // encdec_mux + + + //---------------------------------------------------------------- + // aes_core_ctrl + // + // Control FSM for aes core. Basically tracks if we are in + // key init, encipher or decipher modes and connects the + // different submodules to shared resources and interface ports. + //---------------------------------------------------------------- + always @* + begin : aes_core_ctrl + init_state = 1'b0; + ready_new = 1'b0; + ready_we = 1'b0; + result_valid_new = 1'b0; + result_valid_we = 1'b0; + aes_core_ctrl_new = CTRL_IDLE; + aes_core_ctrl_we = 1'b0; + + case (aes_core_ctrl_reg) + CTRL_IDLE: + begin + if (init) + begin + init_state = 1'b1; + ready_new = 1'b0; + ready_we = 1'b1; + result_valid_new = 1'b0; + result_valid_we = 1'b1; + aes_core_ctrl_new = CTRL_INIT; + aes_core_ctrl_we = 1'b1; + end + else if (next) + begin + init_state = 1'b0; + ready_new = 1'b0; + ready_we = 1'b1; + result_valid_new = 1'b0; + result_valid_we = 1'b1; + aes_core_ctrl_new = CTRL_NEXT; + aes_core_ctrl_we = 1'b1; + end + end + + CTRL_INIT: + begin + init_state = 1'b1; + + if (key_ready) + begin + ready_new = 1'b1; + ready_we = 1'b1; + aes_core_ctrl_new = CTRL_IDLE; + aes_core_ctrl_we = 1'b1; + end + end + + CTRL_NEXT: + begin + init_state = 1'b0; + + if (muxed_ready) + begin + ready_new = 1'b1; + ready_we = 1'b1; + result_valid_new = 1'b1; + result_valid_we = 1'b1; + aes_core_ctrl_new = CTRL_IDLE; + aes_core_ctrl_we = 1'b1; + end + end + + default: + begin + + end + endcase // case (aes_core_ctrl_reg) + + end // aes_core_ctrl +endmodule // aes_core + +//====================================================================== +// EOF aes_core.v +//====================================================================== + +//====================================================================== +// +// aes_encipher_block.v +// -------------------- +// The AES encipher round. A pure combinational module that implements +// the initial round, main round and final round logic for +// enciper operations. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2013, 2014, Secworks Sweden AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +`default_nettype none + +module aes_encipher_block( + input wire clk, + input wire reset_n, + + input wire next, + + input wire keylen, + output wire [3 : 0] round, + input wire [127 : 0] round_key, + + output wire [31 : 0] sboxw, + input wire [31 : 0] new_sboxw, + + input wire [127 : 0] block, + output wire [127 : 0] new_block, + output wire ready + ); + + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + localparam AES_128_BIT_KEY = 1'h0; + localparam AES_256_BIT_KEY = 1'h1; + + localparam AES128_ROUNDS = 4'ha; + localparam AES256_ROUNDS = 4'he; + + localparam NO_UPDATE = 3'h0; + localparam INIT_UPDATE = 3'h1; + localparam SBOX_UPDATE = 3'h2; + localparam MAIN_UPDATE = 3'h3; + localparam FINAL_UPDATE = 3'h4; + + localparam CTRL_IDLE = 2'h0; + localparam CTRL_INIT = 2'h1; + localparam CTRL_SBOX = 2'h2; + localparam CTRL_MAIN = 2'h3; + + + //---------------------------------------------------------------- + // Round functions with sub functions. + //---------------------------------------------------------------- + function [7 : 0] gm2(input [7 : 0] op); + begin + gm2 = {op[6 : 0], 1'b0} ^ (8'h1b & {8{op[7]}}); + end + endfunction // gm2 + + function [7 : 0] gm3(input [7 : 0] op); + begin + gm3 = gm2(op) ^ op; + end + endfunction // gm3 + + function [31 : 0] mixw(input [31 : 0] w); + reg [7 : 0] b0, b1, b2, b3; + reg [7 : 0] mb0, mb1, mb2, mb3; + begin + b0 = w[31 : 24]; + b1 = w[23 : 16]; + b2 = w[15 : 08]; + b3 = w[07 : 00]; + + mb0 = gm2(b0) ^ gm3(b1) ^ b2 ^ b3; + mb1 = b0 ^ gm2(b1) ^ gm3(b2) ^ b3; + mb2 = b0 ^ b1 ^ gm2(b2) ^ gm3(b3); + mb3 = gm3(b0) ^ b1 ^ b2 ^ gm2(b3); + + mixw = {mb0, mb1, mb2, mb3}; + end + endfunction // mixw + + function [127 : 0] mixcolumns(input [127 : 0] data); + reg [31 : 0] w0, w1, w2, w3; + reg [31 : 0] ws0, ws1, ws2, ws3; + begin + w0 = data[127 : 096]; + w1 = data[095 : 064]; + w2 = data[063 : 032]; + w3 = data[031 : 000]; + + ws0 = mixw(w0); + ws1 = mixw(w1); + ws2 = mixw(w2); + ws3 = mixw(w3); + + mixcolumns = {ws0, ws1, ws2, ws3}; + end + endfunction // mixcolumns + + function [127 : 0] shiftrows(input [127 : 0] data); + reg [31 : 0] w0, w1, w2, w3; + reg [31 : 0] ws0, ws1, ws2, ws3; + begin + w0 = data[127 : 096]; + w1 = data[095 : 064]; + w2 = data[063 : 032]; + w3 = data[031 : 000]; + + ws0 = {w0[31 : 24], w1[23 : 16], w2[15 : 08], w3[07 : 00]}; + ws1 = {w1[31 : 24], w2[23 : 16], w3[15 : 08], w0[07 : 00]}; + ws2 = {w2[31 : 24], w3[23 : 16], w0[15 : 08], w1[07 : 00]}; + ws3 = {w3[31 : 24], w0[23 : 16], w1[15 : 08], w2[07 : 00]}; + + shiftrows = {ws0, ws1, ws2, ws3}; + end + endfunction // shiftrows + + function [127 : 0] addroundkey(input [127 : 0] data, input [127 : 0] rkey); + begin + addroundkey = data ^ rkey; + end + endfunction // addroundkey + + + //---------------------------------------------------------------- + // Registers including update variables and write enable. + //---------------------------------------------------------------- + reg [1 : 0] sword_ctr_reg; + reg [1 : 0] sword_ctr_new; + reg sword_ctr_we; + reg sword_ctr_inc; + reg sword_ctr_rst; + + reg [3 : 0] round_ctr_reg; + reg [3 : 0] round_ctr_new; + reg round_ctr_we; + reg round_ctr_rst; + reg round_ctr_inc; + + reg [127 : 0] block_new; + reg [31 : 0] block_w0_reg; + reg [31 : 0] block_w1_reg; + reg [31 : 0] block_w2_reg; + reg [31 : 0] block_w3_reg; + reg block_w0_we; + reg block_w1_we; + reg block_w2_we; + reg block_w3_we; + + reg ready_reg; + reg ready_new; + reg ready_we; + + reg [1 : 0] enc_ctrl_reg; + reg [1 : 0] enc_ctrl_new; + reg enc_ctrl_we; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg [2 : 0] update_type; + reg [31 : 0] muxed_sboxw; + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign round = round_ctr_reg; + assign sboxw = muxed_sboxw; + assign new_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg}; + assign ready = ready_reg; + + + //---------------------------------------------------------------- + // reg_update + // + // Update functionality for all registers in the core. + // All registers are positive edge triggered with asynchronous + // active low reset. All registers have write enable. + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin: reg_update + if (!reset_n) + begin + block_w0_reg <= 32'h0; + block_w1_reg <= 32'h0; + block_w2_reg <= 32'h0; + block_w3_reg <= 32'h0; + sword_ctr_reg <= 2'h0; + round_ctr_reg <= 4'h0; + ready_reg <= 1'b1; + enc_ctrl_reg <= CTRL_IDLE; + end + else + begin + if (block_w0_we) + block_w0_reg <= block_new[127 : 096]; + + if (block_w1_we) + block_w1_reg <= block_new[095 : 064]; + + if (block_w2_we) + block_w2_reg <= block_new[063 : 032]; + + if (block_w3_we) + block_w3_reg <= block_new[031 : 000]; + + if (sword_ctr_we) + sword_ctr_reg <= sword_ctr_new; + + if (round_ctr_we) + round_ctr_reg <= round_ctr_new; + + if (ready_we) + ready_reg <= ready_new; + + if (enc_ctrl_we) + enc_ctrl_reg <= enc_ctrl_new; + end + end // reg_update + + + //---------------------------------------------------------------- + // round_logic + // + // The logic needed to implement init, main and final rounds. + //---------------------------------------------------------------- + always @* + begin : round_logic + reg [127 : 0] old_block, shiftrows_block, mixcolumns_block; + reg [127 : 0] addkey_init_block, addkey_main_block, addkey_final_block; + + block_new = 128'h0; + muxed_sboxw = 32'h0; + block_w0_we = 1'b0; + block_w1_we = 1'b0; + block_w2_we = 1'b0; + block_w3_we = 1'b0; + + old_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg}; + shiftrows_block = shiftrows(old_block); + mixcolumns_block = mixcolumns(shiftrows_block); + addkey_init_block = addroundkey(block, round_key); + addkey_main_block = addroundkey(mixcolumns_block, round_key); + addkey_final_block = addroundkey(shiftrows_block, round_key); + + case (update_type) + INIT_UPDATE: + begin + block_new = addkey_init_block; + block_w0_we = 1'b1; + block_w1_we = 1'b1; + block_w2_we = 1'b1; + block_w3_we = 1'b1; + end + + SBOX_UPDATE: + begin + block_new = {new_sboxw, new_sboxw, new_sboxw, new_sboxw}; + + case (sword_ctr_reg) + 2'h0: + begin + muxed_sboxw = block_w0_reg; + block_w0_we = 1'b1; + end + + 2'h1: + begin + muxed_sboxw = block_w1_reg; + block_w1_we = 1'b1; + end + + 2'h2: + begin + muxed_sboxw = block_w2_reg; + block_w2_we = 1'b1; + end + + 2'h3: + begin + muxed_sboxw = block_w3_reg; + block_w3_we = 1'b1; + end + endcase // case (sbox_mux_ctrl_reg) + end + + MAIN_UPDATE: + begin + block_new = addkey_main_block; + block_w0_we = 1'b1; + block_w1_we = 1'b1; + block_w2_we = 1'b1; + block_w3_we = 1'b1; + end + + FINAL_UPDATE: + begin + block_new = addkey_final_block; + block_w0_we = 1'b1; + block_w1_we = 1'b1; + block_w2_we = 1'b1; + block_w3_we = 1'b1; + end + + default: + begin + end + endcase // case (update_type) + end // round_logic + + + //---------------------------------------------------------------- + // sword_ctr + // + // The subbytes word counter with reset and increase logic. + //---------------------------------------------------------------- + always @* + begin : sword_ctr + sword_ctr_new = 2'h0; + sword_ctr_we = 1'b0; + + if (sword_ctr_rst) + begin + sword_ctr_new = 2'h0; + sword_ctr_we = 1'b1; + end + else if (sword_ctr_inc) + begin + sword_ctr_new = sword_ctr_reg + 1'b1; + sword_ctr_we = 1'b1; + end + end // sword_ctr + + + //---------------------------------------------------------------- + // round_ctr + // + // The round counter with reset and increase logic. + //---------------------------------------------------------------- + always @* + begin : round_ctr + round_ctr_new = 4'h0; + round_ctr_we = 1'b0; + + if (round_ctr_rst) + begin + round_ctr_new = 4'h0; + round_ctr_we = 1'b1; + end + else if (round_ctr_inc) + begin + round_ctr_new = round_ctr_reg + 1'b1; + round_ctr_we = 1'b1; + end + end // round_ctr + + + //---------------------------------------------------------------- + // encipher_ctrl + // + // The FSM that controls the encipher operations. + //---------------------------------------------------------------- + always @* + begin: encipher_ctrl + reg [3 : 0] num_rounds; + + // Default assignments. + sword_ctr_inc = 1'b0; + sword_ctr_rst = 1'b0; + round_ctr_inc = 1'b0; + round_ctr_rst = 1'b0; + ready_new = 1'b0; + ready_we = 1'b0; + update_type = NO_UPDATE; + enc_ctrl_new = CTRL_IDLE; + enc_ctrl_we = 1'b0; + + if (keylen == AES_256_BIT_KEY) + begin + num_rounds = AES256_ROUNDS; + end + else + begin + num_rounds = AES128_ROUNDS; + end + + case(enc_ctrl_reg) + CTRL_IDLE: + begin + if (next) + begin + round_ctr_rst = 1'b1; + ready_new = 1'b0; + ready_we = 1'b1; + enc_ctrl_new = CTRL_INIT; + enc_ctrl_we = 1'b1; + end + end + + CTRL_INIT: + begin + round_ctr_inc = 1'b1; + sword_ctr_rst = 1'b1; + update_type = INIT_UPDATE; + enc_ctrl_new = CTRL_SBOX; + enc_ctrl_we = 1'b1; + end + + CTRL_SBOX: + begin + sword_ctr_inc = 1'b1; + update_type = SBOX_UPDATE; + if (sword_ctr_reg == 2'h3) + begin + enc_ctrl_new = CTRL_MAIN; + enc_ctrl_we = 1'b1; + end + end + + CTRL_MAIN: + begin + sword_ctr_rst = 1'b1; + round_ctr_inc = 1'b1; + if (round_ctr_reg < num_rounds) + begin + update_type = MAIN_UPDATE; + enc_ctrl_new = CTRL_SBOX; + enc_ctrl_we = 1'b1; + end + else + begin + update_type = FINAL_UPDATE; + ready_new = 1'b1; + ready_we = 1'b1; + enc_ctrl_new = CTRL_IDLE; + enc_ctrl_we = 1'b1; + end + end + + default: + begin + // Empty. Just here to make the synthesis tool happy. + end + endcase // case (enc_ctrl_reg) + end // encipher_ctrl + +endmodule // aes_encipher_block + +//====================================================================== +// EOF aes_encipher_block.v +//====================================================================== + +//====================================================================== +// +// aes_decipher_block.v +// -------------------- +// The AES decipher round. A pure combinational module that implements +// the initial round, main round and final round logic for +// decciper operations. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2013, 2014, Secworks Sweden AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +`default_nettype none + +module aes_decipher_block( + input wire clk, + input wire reset_n, + + input wire next, + + input wire keylen, + output wire [3 : 0] round, + input wire [127 : 0] round_key, + + input wire [127 : 0] block, + output wire [127 : 0] new_block, + output wire ready + ); + + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + localparam AES_128_BIT_KEY = 1'h0; + localparam AES_256_BIT_KEY = 1'h1; + + localparam AES128_ROUNDS = 4'ha; + localparam AES256_ROUNDS = 4'he; + + localparam NO_UPDATE = 3'h0; + localparam INIT_UPDATE = 3'h1; + localparam SBOX_UPDATE = 3'h2; + localparam MAIN_UPDATE = 3'h3; + localparam FINAL_UPDATE = 3'h4; + + localparam CTRL_IDLE = 2'h0; + localparam CTRL_INIT = 2'h1; + localparam CTRL_SBOX = 2'h2; + localparam CTRL_MAIN = 2'h3; + + + //---------------------------------------------------------------- + // Gaolis multiplication functions for Inverse MixColumn. + //---------------------------------------------------------------- + function [7 : 0] gm2(input [7 : 0] op); + begin + gm2 = {op[6 : 0], 1'b0} ^ (8'h1b & {8{op[7]}}); + end + endfunction // gm2 + + function [7 : 0] gm3(input [7 : 0] op); + begin + gm3 = gm2(op) ^ op; + end + endfunction // gm3 + + function [7 : 0] gm4(input [7 : 0] op); + begin + gm4 = gm2(gm2(op)); + end + endfunction // gm4 + + function [7 : 0] gm8(input [7 : 0] op); + begin + gm8 = gm2(gm4(op)); + end + endfunction // gm8 + + function [7 : 0] gm09(input [7 : 0] op); + begin + gm09 = gm8(op) ^ op; + end + endfunction // gm09 + + function [7 : 0] gm11(input [7 : 0] op); + begin + gm11 = gm8(op) ^ gm2(op) ^ op; + end + endfunction // gm11 + + function [7 : 0] gm13(input [7 : 0] op); + begin + gm13 = gm8(op) ^ gm4(op) ^ op; + end + endfunction // gm13 + + function [7 : 0] gm14(input [7 : 0] op); + begin + gm14 = gm8(op) ^ gm4(op) ^ gm2(op); + end + endfunction // gm14 + + function [31 : 0] inv_mixw(input [31 : 0] w); + reg [7 : 0] b0, b1, b2, b3; + reg [7 : 0] mb0, mb1, mb2, mb3; + begin + b0 = w[31 : 24]; + b1 = w[23 : 16]; + b2 = w[15 : 08]; + b3 = w[07 : 00]; + + mb0 = gm14(b0) ^ gm11(b1) ^ gm13(b2) ^ gm09(b3); + mb1 = gm09(b0) ^ gm14(b1) ^ gm11(b2) ^ gm13(b3); + mb2 = gm13(b0) ^ gm09(b1) ^ gm14(b2) ^ gm11(b3); + mb3 = gm11(b0) ^ gm13(b1) ^ gm09(b2) ^ gm14(b3); + + inv_mixw = {mb0, mb1, mb2, mb3}; + end + endfunction // mixw + + function [127 : 0] inv_mixcolumns(input [127 : 0] data); + reg [31 : 0] w0, w1, w2, w3; + reg [31 : 0] ws0, ws1, ws2, ws3; + begin + w0 = data[127 : 096]; + w1 = data[095 : 064]; + w2 = data[063 : 032]; + w3 = data[031 : 000]; + + ws0 = inv_mixw(w0); + ws1 = inv_mixw(w1); + ws2 = inv_mixw(w2); + ws3 = inv_mixw(w3); + + inv_mixcolumns = {ws0, ws1, ws2, ws3}; + end + endfunction // inv_mixcolumns + + function [127 : 0] inv_shiftrows(input [127 : 0] data); + reg [31 : 0] w0, w1, w2, w3; + reg [31 : 0] ws0, ws1, ws2, ws3; + begin + w0 = data[127 : 096]; + w1 = data[095 : 064]; + w2 = data[063 : 032]; + w3 = data[031 : 000]; + + ws0 = {w0[31 : 24], w3[23 : 16], w2[15 : 08], w1[07 : 00]}; + ws1 = {w1[31 : 24], w0[23 : 16], w3[15 : 08], w2[07 : 00]}; + ws2 = {w2[31 : 24], w1[23 : 16], w0[15 : 08], w3[07 : 00]}; + ws3 = {w3[31 : 24], w2[23 : 16], w1[15 : 08], w0[07 : 00]}; + + inv_shiftrows = {ws0, ws1, ws2, ws3}; + end + endfunction // inv_shiftrows + + function [127 : 0] addroundkey(input [127 : 0] data, input [127 : 0] rkey); + begin + addroundkey = data ^ rkey; + end + endfunction // addroundkey + + + //---------------------------------------------------------------- + // Registers including update variables and write enable. + //---------------------------------------------------------------- + reg [1 : 0] sword_ctr_reg; + reg [1 : 0] sword_ctr_new; + reg sword_ctr_we; + reg sword_ctr_inc; + reg sword_ctr_rst; + + reg [3 : 0] round_ctr_reg; + reg [3 : 0] round_ctr_new; + reg round_ctr_we; + reg round_ctr_set; + reg round_ctr_dec; + + reg [127 : 0] block_new; + reg [31 : 0] block_w0_reg; + reg [31 : 0] block_w1_reg; + reg [31 : 0] block_w2_reg; + reg [31 : 0] block_w3_reg; + reg block_w0_we; + reg block_w1_we; + reg block_w2_we; + reg block_w3_we; + + reg ready_reg; + reg ready_new; + reg ready_we; + + reg [1 : 0] dec_ctrl_reg; + reg [1 : 0] dec_ctrl_new; + reg dec_ctrl_we; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg [31 : 0] tmp_sboxw; + wire [31 : 0] new_sboxw; + reg [2 : 0] update_type; + + + //---------------------------------------------------------------- + // Instantiations. + //---------------------------------------------------------------- + aes_inv_sbox inv_sbox_inst(.sboxw(tmp_sboxw), .new_sboxw(new_sboxw)); + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign round = round_ctr_reg; + assign new_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg}; + assign ready = ready_reg; + + + //---------------------------------------------------------------- + // reg_update + // + // Update functionality for all registers in the core. + // All registers are positive edge triggered with synchronous + // active low reset. All registers have write enable. + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin: reg_update + if (!reset_n) + begin + block_w0_reg <= 32'h0; + block_w1_reg <= 32'h0; + block_w2_reg <= 32'h0; + block_w3_reg <= 32'h0; + sword_ctr_reg <= 2'h0; + round_ctr_reg <= 4'h0; + ready_reg <= 1'b1; + dec_ctrl_reg <= CTRL_IDLE; + end + else + begin + if (block_w0_we) + block_w0_reg <= block_new[127 : 096]; + + if (block_w1_we) + block_w1_reg <= block_new[095 : 064]; + + if (block_w2_we) + block_w2_reg <= block_new[063 : 032]; + + if (block_w3_we) + block_w3_reg <= block_new[031 : 000]; + + if (sword_ctr_we) + sword_ctr_reg <= sword_ctr_new; + + if (round_ctr_we) + round_ctr_reg <= round_ctr_new; + + if (ready_we) + ready_reg <= ready_new; + + if (dec_ctrl_we) + dec_ctrl_reg <= dec_ctrl_new; + end + end // reg_update + + + //---------------------------------------------------------------- + // round_logic + // + // The logic needed to implement init, main and final rounds. + //---------------------------------------------------------------- + always @* + begin : round_logic + reg [127 : 0] old_block, inv_shiftrows_block, inv_mixcolumns_block; + reg [127 : 0] addkey_block; + + inv_shiftrows_block = 128'h0; + inv_mixcolumns_block = 128'h0; + addkey_block = 128'h0; + block_new = 128'h0; + tmp_sboxw = 32'h0; + block_w0_we = 1'b0; + block_w1_we = 1'b0; + block_w2_we = 1'b0; + block_w3_we = 1'b0; + + old_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg}; + + // Update based on update type. + case (update_type) + // InitRound + INIT_UPDATE: + begin + old_block = block; + addkey_block = addroundkey(old_block, round_key); + inv_shiftrows_block = inv_shiftrows(addkey_block); + block_new = inv_shiftrows_block; + block_w0_we = 1'b1; + block_w1_we = 1'b1; + block_w2_we = 1'b1; + block_w3_we = 1'b1; + end + + SBOX_UPDATE: + begin + block_new = {new_sboxw, new_sboxw, new_sboxw, new_sboxw}; + + case (sword_ctr_reg) + 2'h0: + begin + tmp_sboxw = block_w0_reg; + block_w0_we = 1'b1; + end + + 2'h1: + begin + tmp_sboxw = block_w1_reg; + block_w1_we = 1'b1; + end + + 2'h2: + begin + tmp_sboxw = block_w2_reg; + block_w2_we = 1'b1; + end + + 2'h3: + begin + tmp_sboxw = block_w3_reg; + block_w3_we = 1'b1; + end + endcase // case (sbox_mux_ctrl_reg) + end + + MAIN_UPDATE: + begin + addkey_block = addroundkey(old_block, round_key); + inv_mixcolumns_block = inv_mixcolumns(addkey_block); + inv_shiftrows_block = inv_shiftrows(inv_mixcolumns_block); + block_new = inv_shiftrows_block; + block_w0_we = 1'b1; + block_w1_we = 1'b1; + block_w2_we = 1'b1; + block_w3_we = 1'b1; + end + + FINAL_UPDATE: + begin + block_new = addroundkey(old_block, round_key); + block_w0_we = 1'b1; + block_w1_we = 1'b1; + block_w2_we = 1'b1; + block_w3_we = 1'b1; + end + + default: + begin + end + endcase // case (update_type) + end // round_logic + + + //---------------------------------------------------------------- + // sword_ctr + // + // The subbytes word counter with reset and increase logic. + //---------------------------------------------------------------- + always @* + begin : sword_ctr + sword_ctr_new = 2'h0; + sword_ctr_we = 1'b0; + + if (sword_ctr_rst) + begin + sword_ctr_new = 2'h0; + sword_ctr_we = 1'b1; + end + else if (sword_ctr_inc) + begin + sword_ctr_new = sword_ctr_reg + 1'b1; + sword_ctr_we = 1'b1; + end + end // sword_ctr + + + //---------------------------------------------------------------- + // round_ctr + // + // The round counter with reset and increase logic. + //---------------------------------------------------------------- + always @* + begin : round_ctr + round_ctr_new = 4'h0; + round_ctr_we = 1'b0; + + if (round_ctr_set) + begin + if (keylen == AES_256_BIT_KEY) + begin + round_ctr_new = AES256_ROUNDS; + end + else + begin + round_ctr_new = AES128_ROUNDS; + end + round_ctr_we = 1'b1; + end + else if (round_ctr_dec) + begin + round_ctr_new = round_ctr_reg - 1'b1; + round_ctr_we = 1'b1; + end + end // round_ctr + + + //---------------------------------------------------------------- + // decipher_ctrl + // + // The FSM that controls the decipher operations. + //---------------------------------------------------------------- + always @* + begin: decipher_ctrl + sword_ctr_inc = 1'b0; + sword_ctr_rst = 1'b0; + round_ctr_dec = 1'b0; + round_ctr_set = 1'b0; + ready_new = 1'b0; + ready_we = 1'b0; + update_type = NO_UPDATE; + dec_ctrl_new = CTRL_IDLE; + dec_ctrl_we = 1'b0; + + case(dec_ctrl_reg) + CTRL_IDLE: + begin + if (next) + begin + round_ctr_set = 1'b1; + ready_new = 1'b0; + ready_we = 1'b1; + dec_ctrl_new = CTRL_INIT; + dec_ctrl_we = 1'b1; + end + end + + CTRL_INIT: + begin + sword_ctr_rst = 1'b1; + update_type = INIT_UPDATE; + dec_ctrl_new = CTRL_SBOX; + dec_ctrl_we = 1'b1; + end + + CTRL_SBOX: + begin + sword_ctr_inc = 1'b1; + update_type = SBOX_UPDATE; + if (sword_ctr_reg == 2'h3) + begin + round_ctr_dec = 1'b1; + dec_ctrl_new = CTRL_MAIN; + dec_ctrl_we = 1'b1; + end + end + + CTRL_MAIN: + begin + sword_ctr_rst = 1'b1; + if (round_ctr_reg > 0) + begin + update_type = MAIN_UPDATE; + dec_ctrl_new = CTRL_SBOX; + dec_ctrl_we = 1'b1; + end + else + begin + update_type = FINAL_UPDATE; + ready_new = 1'b1; + ready_we = 1'b1; + dec_ctrl_new = CTRL_IDLE; + dec_ctrl_we = 1'b1; + end + end + + default: + begin + // Empty. Just here to make the synthesis tool happy. + end + endcase // case (dec_ctrl_reg) + end // decipher_ctrl + +endmodule // aes_decipher_block + +//====================================================================== +// EOF aes_decipher_block.v +//====================================================================== + +//====================================================================== +// +// aes_key_mem.v +// ------------- +// The AES key memory including round key generator. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2013 Secworks Sweden AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +`default_nettype none + +module aes_key_mem( + input wire clk, + input wire reset_n, + + input wire [255 : 0] key, + input wire keylen, + input wire init, + + input wire [3 : 0] round, + output wire [127 : 0] round_key, + output wire ready, + + + output wire [31 : 0] sboxw, + input wire [31 : 0] new_sboxw + ); + + + //---------------------------------------------------------------- + // Parameters. + //---------------------------------------------------------------- + localparam AES_128_BIT_KEY = 1'h0; + localparam AES_256_BIT_KEY = 1'h1; + + localparam AES_128_NUM_ROUNDS = 10; + localparam AES_256_NUM_ROUNDS = 14; + + localparam CTRL_IDLE = 3'h0; + localparam CTRL_INIT = 3'h1; + localparam CTRL_GENERATE = 3'h2; + localparam CTRL_DONE = 3'h3; + + + //---------------------------------------------------------------- + // Registers. + //---------------------------------------------------------------- + reg [127 : 0] key_mem [0 : 14]; + reg [127 : 0] key_mem_new; + reg key_mem_we; + + reg [127 : 0] prev_key0_reg; + reg [127 : 0] prev_key0_new; + reg prev_key0_we; + + reg [127 : 0] prev_key1_reg; + reg [127 : 0] prev_key1_new; + reg prev_key1_we; + + reg [3 : 0] round_ctr_reg; + reg [3 : 0] round_ctr_new; + reg round_ctr_rst; + reg round_ctr_inc; + reg round_ctr_we; + + reg [2 : 0] key_mem_ctrl_reg; + reg [2 : 0] key_mem_ctrl_new; + reg key_mem_ctrl_we; + + reg ready_reg; + reg ready_new; + reg ready_we; + + reg [7 : 0] rcon_reg; + reg [7 : 0] rcon_new; + reg rcon_we; + reg rcon_set; + reg rcon_next; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg [31 : 0] tmp_sboxw; + reg round_key_update; + reg [127 : 0] tmp_round_key; + + + //---------------------------------------------------------------- + // Concurrent assignments for ports. + //---------------------------------------------------------------- + assign round_key = tmp_round_key; + assign ready = ready_reg; + assign sboxw = tmp_sboxw; + + + //---------------------------------------------------------------- + // reg_update + // + // Update functionality for all registers in the core. + // All registers are positive edge triggered with asynchronous + // active low reset. All registers have write enable. + //---------------------------------------------------------------- + always @ (posedge clk or negedge reset_n) + begin: reg_update + integer i; + + if (!reset_n) + begin + for (i = 0 ; i <= AES_256_NUM_ROUNDS ; i = i + 1) + key_mem [i] <= 128'h0; + + ready_reg <= 1'b0; + rcon_reg <= 8'h0; + round_ctr_reg <= 4'h0; + prev_key0_reg <= 128'h0; + prev_key1_reg <= 128'h0; + key_mem_ctrl_reg <= CTRL_IDLE; + end + else + begin + if (ready_we) + ready_reg <= ready_new; + + if (rcon_we) + rcon_reg <= rcon_new; + + if (round_ctr_we) + round_ctr_reg <= round_ctr_new; + + if (key_mem_we) + key_mem[round_ctr_reg] <= key_mem_new; + + if (prev_key0_we) + prev_key0_reg <= prev_key0_new; + + if (prev_key1_we) + prev_key1_reg <= prev_key1_new; + + if (key_mem_ctrl_we) + key_mem_ctrl_reg <= key_mem_ctrl_new; + end + end // reg_update + + + //---------------------------------------------------------------- + // key_mem_read + // + // Combinational read port for the key memory. + //---------------------------------------------------------------- + always @* + begin : key_mem_read + tmp_round_key = key_mem[round]; + end // key_mem_read + + + //---------------------------------------------------------------- + // round_key_gen + // + // The round key generator logic for AES-128 and AES-256. + //---------------------------------------------------------------- + always @* + begin: round_key_gen + reg [31 : 0] w0, w1, w2, w3, w4, w5, w6, w7; + reg [31 : 0] k0, k1, k2, k3; + reg [31 : 0] rconw, rotstw, tw, trw; + + // Default assignments. + key_mem_new = 128'h0; + key_mem_we = 1'b0; + prev_key0_new = 128'h0; + prev_key0_we = 1'b0; + prev_key1_new = 128'h0; + prev_key1_we = 1'b0; + + k0 = 32'h0; + k1 = 32'h0; + k2 = 32'h0; + k3 = 32'h0; + + rcon_set = 1'b1; + rcon_next = 1'b0; + + // Extract words and calculate intermediate values. + // Perform rotation of sbox word etc. + w0 = prev_key0_reg[127 : 096]; + w1 = prev_key0_reg[095 : 064]; + w2 = prev_key0_reg[063 : 032]; + w3 = prev_key0_reg[031 : 000]; + + w4 = prev_key1_reg[127 : 096]; + w5 = prev_key1_reg[095 : 064]; + w6 = prev_key1_reg[063 : 032]; + w7 = prev_key1_reg[031 : 000]; + + rconw = {rcon_reg, 24'h0}; + tmp_sboxw = w7; + rotstw = {new_sboxw[23 : 00], new_sboxw[31 : 24]}; + trw = rotstw ^ rconw; + tw = new_sboxw; + + // Generate the specific round keys. + if (round_key_update) + begin + rcon_set = 1'b0; + key_mem_we = 1'b1; + case (keylen) + AES_128_BIT_KEY: + begin + if (round_ctr_reg == 0) + begin + key_mem_new = key[255 : 128]; + prev_key1_new = key[255 : 128]; + prev_key1_we = 1'b1; + rcon_next = 1'b1; + end + else + begin + k0 = w4 ^ trw; + k1 = w5 ^ w4 ^ trw; + k2 = w6 ^ w5 ^ w4 ^ trw; + k3 = w7 ^ w6 ^ w5 ^ w4 ^ trw; + + key_mem_new = {k0, k1, k2, k3}; + prev_key1_new = {k0, k1, k2, k3}; + prev_key1_we = 1'b1; + rcon_next = 1'b1; + end + end + + AES_256_BIT_KEY: + begin + if (round_ctr_reg == 0) + begin + key_mem_new = key[255 : 128]; + prev_key0_new = key[255 : 128]; + prev_key0_we = 1'b1; + end + else if (round_ctr_reg == 1) + begin + key_mem_new = key[127 : 0]; + prev_key1_new = key[127 : 0]; + prev_key1_we = 1'b1; + rcon_next = 1'b1; + end + else + begin + if (round_ctr_reg[0] == 0) + begin + k0 = w0 ^ trw; + k1 = w1 ^ w0 ^ trw; + k2 = w2 ^ w1 ^ w0 ^ trw; + k3 = w3 ^ w2 ^ w1 ^ w0 ^ trw; + end + else + begin + k0 = w0 ^ tw; + k1 = w1 ^ w0 ^ tw; + k2 = w2 ^ w1 ^ w0 ^ tw; + k3 = w3 ^ w2 ^ w1 ^ w0 ^ tw; + rcon_next = 1'b1; + end + + // Store the generated round keys. + key_mem_new = {k0, k1, k2, k3}; + prev_key1_new = {k0, k1, k2, k3}; + prev_key1_we = 1'b1; + prev_key0_new = prev_key1_reg; + prev_key0_we = 1'b1; + end + end + + default: + begin + end + endcase // case (keylen) + end + end // round_key_gen + + + //---------------------------------------------------------------- + // rcon_logic + // + // Caclulates the rcon value for the different key expansion + // iterations. + //---------------------------------------------------------------- + always @* + begin : rcon_logic + reg [7 : 0] tmp_rcon; + rcon_new = 8'h00; + rcon_we = 1'b0; + + tmp_rcon = {rcon_reg[6 : 0], 1'b0} ^ (8'h1b & {8{rcon_reg[7]}}); + + if (rcon_set) + begin + rcon_new = 8'h8d; + rcon_we = 1'b1; + end + + if (rcon_next) + begin + rcon_new = tmp_rcon[7 : 0]; + rcon_we = 1'b1; + end + end + + + //---------------------------------------------------------------- + // round_ctr + // + // The round counter logic with increase and reset. + //---------------------------------------------------------------- + always @* + begin : round_ctr + round_ctr_new = 4'h0; + round_ctr_we = 1'b0; + + if (round_ctr_rst) + begin + round_ctr_new = 4'h0; + round_ctr_we = 1'b1; + end + + else if (round_ctr_inc) + begin + round_ctr_new = round_ctr_reg + 1'b1; + round_ctr_we = 1'b1; + end + end + + + //---------------------------------------------------------------- + // key_mem_ctrl + // + // + // The FSM that controls the round key generation. + //---------------------------------------------------------------- + always @* + begin: key_mem_ctrl + reg [3 : 0] num_rounds; + + // Default assignments. + ready_new = 1'b0; + ready_we = 1'b0; + round_key_update = 1'b0; + round_ctr_rst = 1'b0; + round_ctr_inc = 1'b0; + key_mem_ctrl_new = CTRL_IDLE; + key_mem_ctrl_we = 1'b0; + + if (keylen == AES_128_BIT_KEY) + num_rounds = AES_128_NUM_ROUNDS; + else + num_rounds = AES_256_NUM_ROUNDS; + + case(key_mem_ctrl_reg) + CTRL_IDLE: + begin + if (init) + begin + ready_new = 1'b0; + ready_we = 1'b1; + key_mem_ctrl_new = CTRL_INIT; + key_mem_ctrl_we = 1'b1; + end + end + + CTRL_INIT: + begin + round_ctr_rst = 1'b1; + key_mem_ctrl_new = CTRL_GENERATE; + key_mem_ctrl_we = 1'b1; + end + + CTRL_GENERATE: + begin + round_ctr_inc = 1'b1; + round_key_update = 1'b1; + if (round_ctr_reg == num_rounds) + begin + key_mem_ctrl_new = CTRL_DONE; + key_mem_ctrl_we = 1'b1; + end + end + + CTRL_DONE: + begin + ready_new = 1'b1; + ready_we = 1'b1; + key_mem_ctrl_new = CTRL_IDLE; + key_mem_ctrl_we = 1'b1; + end + + default: + begin + end + endcase // case (key_mem_ctrl_reg) + + end // key_mem_ctrl +endmodule // aes_key_mem + +//====================================================================== +// EOF aes_key_mem.v +//====================================================================== + +//====================================================================== +// +// aes_sbox.v +// ---------- +// The AES S-box. Basically a 256 Byte ROM. This implementation +// contains four parallel S-boxes to handle a 32 bit word. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2014, Secworks Sweden AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +`default_nettype none + +module aes_sbox( + input wire [31 : 0] sboxw, + output wire [31 : 0] new_sboxw + ); + + + //---------------------------------------------------------------- + // The sbox array. + //---------------------------------------------------------------- + wire [7 : 0] sbox [0 : 255]; + + + //---------------------------------------------------------------- + // Four parallel muxes. + //---------------------------------------------------------------- + assign new_sboxw[31 : 24] = sbox[sboxw[31 : 24]]; + assign new_sboxw[23 : 16] = sbox[sboxw[23 : 16]]; + assign new_sboxw[15 : 08] = sbox[sboxw[15 : 08]]; + assign new_sboxw[07 : 00] = sbox[sboxw[07 : 00]]; + + + //---------------------------------------------------------------- + // Creating the sbox array contents. + //---------------------------------------------------------------- + assign sbox[8'h00] = 8'h63; + assign sbox[8'h01] = 8'h7c; + assign sbox[8'h02] = 8'h77; + assign sbox[8'h03] = 8'h7b; + assign sbox[8'h04] = 8'hf2; + assign sbox[8'h05] = 8'h6b; + assign sbox[8'h06] = 8'h6f; + assign sbox[8'h07] = 8'hc5; + assign sbox[8'h08] = 8'h30; + assign sbox[8'h09] = 8'h01; + assign sbox[8'h0a] = 8'h67; + assign sbox[8'h0b] = 8'h2b; + assign sbox[8'h0c] = 8'hfe; + assign sbox[8'h0d] = 8'hd7; + assign sbox[8'h0e] = 8'hab; + assign sbox[8'h0f] = 8'h76; + assign sbox[8'h10] = 8'hca; + assign sbox[8'h11] = 8'h82; + assign sbox[8'h12] = 8'hc9; + assign sbox[8'h13] = 8'h7d; + assign sbox[8'h14] = 8'hfa; + assign sbox[8'h15] = 8'h59; + assign sbox[8'h16] = 8'h47; + assign sbox[8'h17] = 8'hf0; + assign sbox[8'h18] = 8'had; + assign sbox[8'h19] = 8'hd4; + assign sbox[8'h1a] = 8'ha2; + assign sbox[8'h1b] = 8'haf; + assign sbox[8'h1c] = 8'h9c; + assign sbox[8'h1d] = 8'ha4; + assign sbox[8'h1e] = 8'h72; + assign sbox[8'h1f] = 8'hc0; + assign sbox[8'h20] = 8'hb7; + assign sbox[8'h21] = 8'hfd; + assign sbox[8'h22] = 8'h93; + assign sbox[8'h23] = 8'h26; + assign sbox[8'h24] = 8'h36; + assign sbox[8'h25] = 8'h3f; + assign sbox[8'h26] = 8'hf7; + assign sbox[8'h27] = 8'hcc; + assign sbox[8'h28] = 8'h34; + assign sbox[8'h29] = 8'ha5; + assign sbox[8'h2a] = 8'he5; + assign sbox[8'h2b] = 8'hf1; + assign sbox[8'h2c] = 8'h71; + assign sbox[8'h2d] = 8'hd8; + assign sbox[8'h2e] = 8'h31; + assign sbox[8'h2f] = 8'h15; + assign sbox[8'h30] = 8'h04; + assign sbox[8'h31] = 8'hc7; + assign sbox[8'h32] = 8'h23; + assign sbox[8'h33] = 8'hc3; + assign sbox[8'h34] = 8'h18; + assign sbox[8'h35] = 8'h96; + assign sbox[8'h36] = 8'h05; + assign sbox[8'h37] = 8'h9a; + assign sbox[8'h38] = 8'h07; + assign sbox[8'h39] = 8'h12; + assign sbox[8'h3a] = 8'h80; + assign sbox[8'h3b] = 8'he2; + assign sbox[8'h3c] = 8'heb; + assign sbox[8'h3d] = 8'h27; + assign sbox[8'h3e] = 8'hb2; + assign sbox[8'h3f] = 8'h75; + assign sbox[8'h40] = 8'h09; + assign sbox[8'h41] = 8'h83; + assign sbox[8'h42] = 8'h2c; + assign sbox[8'h43] = 8'h1a; + assign sbox[8'h44] = 8'h1b; + assign sbox[8'h45] = 8'h6e; + assign sbox[8'h46] = 8'h5a; + assign sbox[8'h47] = 8'ha0; + assign sbox[8'h48] = 8'h52; + assign sbox[8'h49] = 8'h3b; + assign sbox[8'h4a] = 8'hd6; + assign sbox[8'h4b] = 8'hb3; + assign sbox[8'h4c] = 8'h29; + assign sbox[8'h4d] = 8'he3; + assign sbox[8'h4e] = 8'h2f; + assign sbox[8'h4f] = 8'h84; + assign sbox[8'h50] = 8'h53; + assign sbox[8'h51] = 8'hd1; + assign sbox[8'h52] = 8'h00; + assign sbox[8'h53] = 8'hed; + assign sbox[8'h54] = 8'h20; + assign sbox[8'h55] = 8'hfc; + assign sbox[8'h56] = 8'hb1; + assign sbox[8'h57] = 8'h5b; + assign sbox[8'h58] = 8'h6a; + assign sbox[8'h59] = 8'hcb; + assign sbox[8'h5a] = 8'hbe; + assign sbox[8'h5b] = 8'h39; + assign sbox[8'h5c] = 8'h4a; + assign sbox[8'h5d] = 8'h4c; + assign sbox[8'h5e] = 8'h58; + assign sbox[8'h5f] = 8'hcf; + assign sbox[8'h60] = 8'hd0; + assign sbox[8'h61] = 8'hef; + assign sbox[8'h62] = 8'haa; + assign sbox[8'h63] = 8'hfb; + assign sbox[8'h64] = 8'h43; + assign sbox[8'h65] = 8'h4d; + assign sbox[8'h66] = 8'h33; + assign sbox[8'h67] = 8'h85; + assign sbox[8'h68] = 8'h45; + assign sbox[8'h69] = 8'hf9; + assign sbox[8'h6a] = 8'h02; + assign sbox[8'h6b] = 8'h7f; + assign sbox[8'h6c] = 8'h50; + assign sbox[8'h6d] = 8'h3c; + assign sbox[8'h6e] = 8'h9f; + assign sbox[8'h6f] = 8'ha8; + assign sbox[8'h70] = 8'h51; + assign sbox[8'h71] = 8'ha3; + assign sbox[8'h72] = 8'h40; + assign sbox[8'h73] = 8'h8f; + assign sbox[8'h74] = 8'h92; + assign sbox[8'h75] = 8'h9d; + assign sbox[8'h76] = 8'h38; + assign sbox[8'h77] = 8'hf5; + assign sbox[8'h78] = 8'hbc; + assign sbox[8'h79] = 8'hb6; + assign sbox[8'h7a] = 8'hda; + assign sbox[8'h7b] = 8'h21; + assign sbox[8'h7c] = 8'h10; + assign sbox[8'h7d] = 8'hff; + assign sbox[8'h7e] = 8'hf3; + assign sbox[8'h7f] = 8'hd2; + assign sbox[8'h80] = 8'hcd; + assign sbox[8'h81] = 8'h0c; + assign sbox[8'h82] = 8'h13; + assign sbox[8'h83] = 8'hec; + assign sbox[8'h84] = 8'h5f; + assign sbox[8'h85] = 8'h97; + assign sbox[8'h86] = 8'h44; + assign sbox[8'h87] = 8'h17; + assign sbox[8'h88] = 8'hc4; + assign sbox[8'h89] = 8'ha7; + assign sbox[8'h8a] = 8'h7e; + assign sbox[8'h8b] = 8'h3d; + assign sbox[8'h8c] = 8'h64; + assign sbox[8'h8d] = 8'h5d; + assign sbox[8'h8e] = 8'h19; + assign sbox[8'h8f] = 8'h73; + assign sbox[8'h90] = 8'h60; + assign sbox[8'h91] = 8'h81; + assign sbox[8'h92] = 8'h4f; + assign sbox[8'h93] = 8'hdc; + assign sbox[8'h94] = 8'h22; + assign sbox[8'h95] = 8'h2a; + assign sbox[8'h96] = 8'h90; + assign sbox[8'h97] = 8'h88; + assign sbox[8'h98] = 8'h46; + assign sbox[8'h99] = 8'hee; + assign sbox[8'h9a] = 8'hb8; + assign sbox[8'h9b] = 8'h14; + assign sbox[8'h9c] = 8'hde; + assign sbox[8'h9d] = 8'h5e; + assign sbox[8'h9e] = 8'h0b; + assign sbox[8'h9f] = 8'hdb; + assign sbox[8'ha0] = 8'he0; + assign sbox[8'ha1] = 8'h32; + assign sbox[8'ha2] = 8'h3a; + assign sbox[8'ha3] = 8'h0a; + assign sbox[8'ha4] = 8'h49; + assign sbox[8'ha5] = 8'h06; + assign sbox[8'ha6] = 8'h24; + assign sbox[8'ha7] = 8'h5c; + assign sbox[8'ha8] = 8'hc2; + assign sbox[8'ha9] = 8'hd3; + assign sbox[8'haa] = 8'hac; + assign sbox[8'hab] = 8'h62; + assign sbox[8'hac] = 8'h91; + assign sbox[8'had] = 8'h95; + assign sbox[8'hae] = 8'he4; + assign sbox[8'haf] = 8'h79; + assign sbox[8'hb0] = 8'he7; + assign sbox[8'hb1] = 8'hc8; + assign sbox[8'hb2] = 8'h37; + assign sbox[8'hb3] = 8'h6d; + assign sbox[8'hb4] = 8'h8d; + assign sbox[8'hb5] = 8'hd5; + assign sbox[8'hb6] = 8'h4e; + assign sbox[8'hb7] = 8'ha9; + assign sbox[8'hb8] = 8'h6c; + assign sbox[8'hb9] = 8'h56; + assign sbox[8'hba] = 8'hf4; + assign sbox[8'hbb] = 8'hea; + assign sbox[8'hbc] = 8'h65; + assign sbox[8'hbd] = 8'h7a; + assign sbox[8'hbe] = 8'hae; + assign sbox[8'hbf] = 8'h08; + assign sbox[8'hc0] = 8'hba; + assign sbox[8'hc1] = 8'h78; + assign sbox[8'hc2] = 8'h25; + assign sbox[8'hc3] = 8'h2e; + assign sbox[8'hc4] = 8'h1c; + assign sbox[8'hc5] = 8'ha6; + assign sbox[8'hc6] = 8'hb4; + assign sbox[8'hc7] = 8'hc6; + assign sbox[8'hc8] = 8'he8; + assign sbox[8'hc9] = 8'hdd; + assign sbox[8'hca] = 8'h74; + assign sbox[8'hcb] = 8'h1f; + assign sbox[8'hcc] = 8'h4b; + assign sbox[8'hcd] = 8'hbd; + assign sbox[8'hce] = 8'h8b; + assign sbox[8'hcf] = 8'h8a; + assign sbox[8'hd0] = 8'h70; + assign sbox[8'hd1] = 8'h3e; + assign sbox[8'hd2] = 8'hb5; + assign sbox[8'hd3] = 8'h66; + assign sbox[8'hd4] = 8'h48; + assign sbox[8'hd5] = 8'h03; + assign sbox[8'hd6] = 8'hf6; + assign sbox[8'hd7] = 8'h0e; + assign sbox[8'hd8] = 8'h61; + assign sbox[8'hd9] = 8'h35; + assign sbox[8'hda] = 8'h57; + assign sbox[8'hdb] = 8'hb9; + assign sbox[8'hdc] = 8'h86; + assign sbox[8'hdd] = 8'hc1; + assign sbox[8'hde] = 8'h1d; + assign sbox[8'hdf] = 8'h9e; + assign sbox[8'he0] = 8'he1; + assign sbox[8'he1] = 8'hf8; + assign sbox[8'he2] = 8'h98; + assign sbox[8'he3] = 8'h11; + assign sbox[8'he4] = 8'h69; + assign sbox[8'he5] = 8'hd9; + assign sbox[8'he6] = 8'h8e; + assign sbox[8'he7] = 8'h94; + assign sbox[8'he8] = 8'h9b; + assign sbox[8'he9] = 8'h1e; + assign sbox[8'hea] = 8'h87; + assign sbox[8'heb] = 8'he9; + assign sbox[8'hec] = 8'hce; + assign sbox[8'hed] = 8'h55; + assign sbox[8'hee] = 8'h28; + assign sbox[8'hef] = 8'hdf; + assign sbox[8'hf0] = 8'h8c; + assign sbox[8'hf1] = 8'ha1; + assign sbox[8'hf2] = 8'h89; + assign sbox[8'hf3] = 8'h0d; + assign sbox[8'hf4] = 8'hbf; + assign sbox[8'hf5] = 8'he6; + assign sbox[8'hf6] = 8'h42; + assign sbox[8'hf7] = 8'h68; + assign sbox[8'hf8] = 8'h41; + assign sbox[8'hf9] = 8'h99; + assign sbox[8'hfa] = 8'h2d; + assign sbox[8'hfb] = 8'h0f; + assign sbox[8'hfc] = 8'hb0; + assign sbox[8'hfd] = 8'h54; + assign sbox[8'hfe] = 8'hbb; + assign sbox[8'hff] = 8'h16; + +endmodule // aes_sbox + +//====================================================================== +// EOF aes_sbox.v +//====================================================================== + +//====================================================================== +// +// aes_inv_sbox.v +// -------------- +// The inverse AES S-box. Basically a 256 Byte ROM. +// +// +// Copyright (c) 2013 Secworks Sweden AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +`default_nettype none + +module aes_inv_sbox( + input wire [31 : 0] sboxw, + output wire [31 : 0] new_sboxw + ); + + + //---------------------------------------------------------------- + // The inverse sbox array. + //---------------------------------------------------------------- + wire [7 : 0] inv_sbox [0 : 255]; + + + //---------------------------------------------------------------- + // Four parallel muxes. + //---------------------------------------------------------------- + assign new_sboxw[31 : 24] = inv_sbox[sboxw[31 : 24]]; + assign new_sboxw[23 : 16] = inv_sbox[sboxw[23 : 16]]; + assign new_sboxw[15 : 08] = inv_sbox[sboxw[15 : 08]]; + assign new_sboxw[07 : 00] = inv_sbox[sboxw[07 : 00]]; + + + //---------------------------------------------------------------- + // Creating the contents of the array. + //---------------------------------------------------------------- + assign inv_sbox[8'h00] = 8'h52; + assign inv_sbox[8'h01] = 8'h09; + assign inv_sbox[8'h02] = 8'h6a; + assign inv_sbox[8'h03] = 8'hd5; + assign inv_sbox[8'h04] = 8'h30; + assign inv_sbox[8'h05] = 8'h36; + assign inv_sbox[8'h06] = 8'ha5; + assign inv_sbox[8'h07] = 8'h38; + assign inv_sbox[8'h08] = 8'hbf; + assign inv_sbox[8'h09] = 8'h40; + assign inv_sbox[8'h0a] = 8'ha3; + assign inv_sbox[8'h0b] = 8'h9e; + assign inv_sbox[8'h0c] = 8'h81; + assign inv_sbox[8'h0d] = 8'hf3; + assign inv_sbox[8'h0e] = 8'hd7; + assign inv_sbox[8'h0f] = 8'hfb; + assign inv_sbox[8'h10] = 8'h7c; + assign inv_sbox[8'h11] = 8'he3; + assign inv_sbox[8'h12] = 8'h39; + assign inv_sbox[8'h13] = 8'h82; + assign inv_sbox[8'h14] = 8'h9b; + assign inv_sbox[8'h15] = 8'h2f; + assign inv_sbox[8'h16] = 8'hff; + assign inv_sbox[8'h17] = 8'h87; + assign inv_sbox[8'h18] = 8'h34; + assign inv_sbox[8'h19] = 8'h8e; + assign inv_sbox[8'h1a] = 8'h43; + assign inv_sbox[8'h1b] = 8'h44; + assign inv_sbox[8'h1c] = 8'hc4; + assign inv_sbox[8'h1d] = 8'hde; + assign inv_sbox[8'h1e] = 8'he9; + assign inv_sbox[8'h1f] = 8'hcb; + assign inv_sbox[8'h20] = 8'h54; + assign inv_sbox[8'h21] = 8'h7b; + assign inv_sbox[8'h22] = 8'h94; + assign inv_sbox[8'h23] = 8'h32; + assign inv_sbox[8'h24] = 8'ha6; + assign inv_sbox[8'h25] = 8'hc2; + assign inv_sbox[8'h26] = 8'h23; + assign inv_sbox[8'h27] = 8'h3d; + assign inv_sbox[8'h28] = 8'hee; + assign inv_sbox[8'h29] = 8'h4c; + assign inv_sbox[8'h2a] = 8'h95; + assign inv_sbox[8'h2b] = 8'h0b; + assign inv_sbox[8'h2c] = 8'h42; + assign inv_sbox[8'h2d] = 8'hfa; + assign inv_sbox[8'h2e] = 8'hc3; + assign inv_sbox[8'h2f] = 8'h4e; + assign inv_sbox[8'h30] = 8'h08; + assign inv_sbox[8'h31] = 8'h2e; + assign inv_sbox[8'h32] = 8'ha1; + assign inv_sbox[8'h33] = 8'h66; + assign inv_sbox[8'h34] = 8'h28; + assign inv_sbox[8'h35] = 8'hd9; + assign inv_sbox[8'h36] = 8'h24; + assign inv_sbox[8'h37] = 8'hb2; + assign inv_sbox[8'h38] = 8'h76; + assign inv_sbox[8'h39] = 8'h5b; + assign inv_sbox[8'h3a] = 8'ha2; + assign inv_sbox[8'h3b] = 8'h49; + assign inv_sbox[8'h3c] = 8'h6d; + assign inv_sbox[8'h3d] = 8'h8b; + assign inv_sbox[8'h3e] = 8'hd1; + assign inv_sbox[8'h3f] = 8'h25; + assign inv_sbox[8'h40] = 8'h72; + assign inv_sbox[8'h41] = 8'hf8; + assign inv_sbox[8'h42] = 8'hf6; + assign inv_sbox[8'h43] = 8'h64; + assign inv_sbox[8'h44] = 8'h86; + assign inv_sbox[8'h45] = 8'h68; + assign inv_sbox[8'h46] = 8'h98; + assign inv_sbox[8'h47] = 8'h16; + assign inv_sbox[8'h48] = 8'hd4; + assign inv_sbox[8'h49] = 8'ha4; + assign inv_sbox[8'h4a] = 8'h5c; + assign inv_sbox[8'h4b] = 8'hcc; + assign inv_sbox[8'h4c] = 8'h5d; + assign inv_sbox[8'h4d] = 8'h65; + assign inv_sbox[8'h4e] = 8'hb6; + assign inv_sbox[8'h4f] = 8'h92; + assign inv_sbox[8'h50] = 8'h6c; + assign inv_sbox[8'h51] = 8'h70; + assign inv_sbox[8'h52] = 8'h48; + assign inv_sbox[8'h53] = 8'h50; + assign inv_sbox[8'h54] = 8'hfd; + assign inv_sbox[8'h55] = 8'hed; + assign inv_sbox[8'h56] = 8'hb9; + assign inv_sbox[8'h57] = 8'hda; + assign inv_sbox[8'h58] = 8'h5e; + assign inv_sbox[8'h59] = 8'h15; + assign inv_sbox[8'h5a] = 8'h46; + assign inv_sbox[8'h5b] = 8'h57; + assign inv_sbox[8'h5c] = 8'ha7; + assign inv_sbox[8'h5d] = 8'h8d; + assign inv_sbox[8'h5e] = 8'h9d; + assign inv_sbox[8'h5f] = 8'h84; + assign inv_sbox[8'h60] = 8'h90; + assign inv_sbox[8'h61] = 8'hd8; + assign inv_sbox[8'h62] = 8'hab; + assign inv_sbox[8'h63] = 8'h00; + assign inv_sbox[8'h64] = 8'h8c; + assign inv_sbox[8'h65] = 8'hbc; + assign inv_sbox[8'h66] = 8'hd3; + assign inv_sbox[8'h67] = 8'h0a; + assign inv_sbox[8'h68] = 8'hf7; + assign inv_sbox[8'h69] = 8'he4; + assign inv_sbox[8'h6a] = 8'h58; + assign inv_sbox[8'h6b] = 8'h05; + assign inv_sbox[8'h6c] = 8'hb8; + assign inv_sbox[8'h6d] = 8'hb3; + assign inv_sbox[8'h6e] = 8'h45; + assign inv_sbox[8'h6f] = 8'h06; + assign inv_sbox[8'h70] = 8'hd0; + assign inv_sbox[8'h71] = 8'h2c; + assign inv_sbox[8'h72] = 8'h1e; + assign inv_sbox[8'h73] = 8'h8f; + assign inv_sbox[8'h74] = 8'hca; + assign inv_sbox[8'h75] = 8'h3f; + assign inv_sbox[8'h76] = 8'h0f; + assign inv_sbox[8'h77] = 8'h02; + assign inv_sbox[8'h78] = 8'hc1; + assign inv_sbox[8'h79] = 8'haf; + assign inv_sbox[8'h7a] = 8'hbd; + assign inv_sbox[8'h7b] = 8'h03; + assign inv_sbox[8'h7c] = 8'h01; + assign inv_sbox[8'h7d] = 8'h13; + assign inv_sbox[8'h7e] = 8'h8a; + assign inv_sbox[8'h7f] = 8'h6b; + assign inv_sbox[8'h80] = 8'h3a; + assign inv_sbox[8'h81] = 8'h91; + assign inv_sbox[8'h82] = 8'h11; + assign inv_sbox[8'h83] = 8'h41; + assign inv_sbox[8'h84] = 8'h4f; + assign inv_sbox[8'h85] = 8'h67; + assign inv_sbox[8'h86] = 8'hdc; + assign inv_sbox[8'h87] = 8'hea; + assign inv_sbox[8'h88] = 8'h97; + assign inv_sbox[8'h89] = 8'hf2; + assign inv_sbox[8'h8a] = 8'hcf; + assign inv_sbox[8'h8b] = 8'hce; + assign inv_sbox[8'h8c] = 8'hf0; + assign inv_sbox[8'h8d] = 8'hb4; + assign inv_sbox[8'h8e] = 8'he6; + assign inv_sbox[8'h8f] = 8'h73; + assign inv_sbox[8'h90] = 8'h96; + assign inv_sbox[8'h91] = 8'hac; + assign inv_sbox[8'h92] = 8'h74; + assign inv_sbox[8'h93] = 8'h22; + assign inv_sbox[8'h94] = 8'he7; + assign inv_sbox[8'h95] = 8'had; + assign inv_sbox[8'h96] = 8'h35; + assign inv_sbox[8'h97] = 8'h85; + assign inv_sbox[8'h98] = 8'he2; + assign inv_sbox[8'h99] = 8'hf9; + assign inv_sbox[8'h9a] = 8'h37; + assign inv_sbox[8'h9b] = 8'he8; + assign inv_sbox[8'h9c] = 8'h1c; + assign inv_sbox[8'h9d] = 8'h75; + assign inv_sbox[8'h9e] = 8'hdf; + assign inv_sbox[8'h9f] = 8'h6e; + assign inv_sbox[8'ha0] = 8'h47; + assign inv_sbox[8'ha1] = 8'hf1; + assign inv_sbox[8'ha2] = 8'h1a; + assign inv_sbox[8'ha3] = 8'h71; + assign inv_sbox[8'ha4] = 8'h1d; + assign inv_sbox[8'ha5] = 8'h29; + assign inv_sbox[8'ha6] = 8'hc5; + assign inv_sbox[8'ha7] = 8'h89; + assign inv_sbox[8'ha8] = 8'h6f; + assign inv_sbox[8'ha9] = 8'hb7; + assign inv_sbox[8'haa] = 8'h62; + assign inv_sbox[8'hab] = 8'h0e; + assign inv_sbox[8'hac] = 8'haa; + assign inv_sbox[8'had] = 8'h18; + assign inv_sbox[8'hae] = 8'hbe; + assign inv_sbox[8'haf] = 8'h1b; + assign inv_sbox[8'hb0] = 8'hfc; + assign inv_sbox[8'hb1] = 8'h56; + assign inv_sbox[8'hb2] = 8'h3e; + assign inv_sbox[8'hb3] = 8'h4b; + assign inv_sbox[8'hb4] = 8'hc6; + assign inv_sbox[8'hb5] = 8'hd2; + assign inv_sbox[8'hb6] = 8'h79; + assign inv_sbox[8'hb7] = 8'h20; + assign inv_sbox[8'hb8] = 8'h9a; + assign inv_sbox[8'hb9] = 8'hdb; + assign inv_sbox[8'hba] = 8'hc0; + assign inv_sbox[8'hbb] = 8'hfe; + assign inv_sbox[8'hbc] = 8'h78; + assign inv_sbox[8'hbd] = 8'hcd; + assign inv_sbox[8'hbe] = 8'h5a; + assign inv_sbox[8'hbf] = 8'hf4; + assign inv_sbox[8'hc0] = 8'h1f; + assign inv_sbox[8'hc1] = 8'hdd; + assign inv_sbox[8'hc2] = 8'ha8; + assign inv_sbox[8'hc3] = 8'h33; + assign inv_sbox[8'hc4] = 8'h88; + assign inv_sbox[8'hc5] = 8'h07; + assign inv_sbox[8'hc6] = 8'hc7; + assign inv_sbox[8'hc7] = 8'h31; + assign inv_sbox[8'hc8] = 8'hb1; + assign inv_sbox[8'hc9] = 8'h12; + assign inv_sbox[8'hca] = 8'h10; + assign inv_sbox[8'hcb] = 8'h59; + assign inv_sbox[8'hcc] = 8'h27; + assign inv_sbox[8'hcd] = 8'h80; + assign inv_sbox[8'hce] = 8'hec; + assign inv_sbox[8'hcf] = 8'h5f; + assign inv_sbox[8'hd0] = 8'h60; + assign inv_sbox[8'hd1] = 8'h51; + assign inv_sbox[8'hd2] = 8'h7f; + assign inv_sbox[8'hd3] = 8'ha9; + assign inv_sbox[8'hd4] = 8'h19; + assign inv_sbox[8'hd5] = 8'hb5; + assign inv_sbox[8'hd6] = 8'h4a; + assign inv_sbox[8'hd7] = 8'h0d; + assign inv_sbox[8'hd8] = 8'h2d; + assign inv_sbox[8'hd9] = 8'he5; + assign inv_sbox[8'hda] = 8'h7a; + assign inv_sbox[8'hdb] = 8'h9f; + assign inv_sbox[8'hdc] = 8'h93; + assign inv_sbox[8'hdd] = 8'hc9; + assign inv_sbox[8'hde] = 8'h9c; + assign inv_sbox[8'hdf] = 8'hef; + assign inv_sbox[8'he0] = 8'ha0; + assign inv_sbox[8'he1] = 8'he0; + assign inv_sbox[8'he2] = 8'h3b; + assign inv_sbox[8'he3] = 8'h4d; + assign inv_sbox[8'he4] = 8'hae; + assign inv_sbox[8'he5] = 8'h2a; + assign inv_sbox[8'he6] = 8'hf5; + assign inv_sbox[8'he7] = 8'hb0; + assign inv_sbox[8'he8] = 8'hc8; + assign inv_sbox[8'he9] = 8'heb; + assign inv_sbox[8'hea] = 8'hbb; + assign inv_sbox[8'heb] = 8'h3c; + assign inv_sbox[8'hec] = 8'h83; + assign inv_sbox[8'hed] = 8'h53; + assign inv_sbox[8'hee] = 8'h99; + assign inv_sbox[8'hef] = 8'h61; + assign inv_sbox[8'hf0] = 8'h17; + assign inv_sbox[8'hf1] = 8'h2b; + assign inv_sbox[8'hf2] = 8'h04; + assign inv_sbox[8'hf3] = 8'h7e; + assign inv_sbox[8'hf4] = 8'hba; + assign inv_sbox[8'hf5] = 8'h77; + assign inv_sbox[8'hf6] = 8'hd6; + assign inv_sbox[8'hf7] = 8'h26; + assign inv_sbox[8'hf8] = 8'he1; + assign inv_sbox[8'hf9] = 8'h69; + assign inv_sbox[8'hfa] = 8'h14; + assign inv_sbox[8'hfb] = 8'h63; + assign inv_sbox[8'hfc] = 8'h55; + assign inv_sbox[8'hfd] = 8'h21; + assign inv_sbox[8'hfe] = 8'h0c; + assign inv_sbox[8'hff] = 8'h7d; + +endmodule // aes_inv_sbox + +//====================================================================== +// EOF aes_inv_sbox.v +//====================================================================== diff --git a/IPLIB/ADPcontrol_v1_0/ADPmanager.v b/IPLIB/ADPcontrol_v1_0/ADPmanager.v index 26705e8..f056b75 100755 --- a/IPLIB/ADPcontrol_v1_0/ADPmanager.v +++ b/IPLIB/ADPcontrol_v1_0/ADPmanager.v @@ -71,8 +71,8 @@ localparam CMD_A = 4'b0001; // set Address localparam CMD_C = 4'b0010; // Control localparam CMD_R = 4'b0011; // Read word, addr++ localparam CMD_S = 4'b0100; // Status/STDIN -localparam CMD_W = 4'b0100; // Write word, addr++ -localparam CMD_X = 4'b0101; // eXit +localparam CMD_W = 4'b0101; // Write word, addr++ +localparam CMD_X = 4'b0110; // eXit `ifndef ADPBASIC localparam CMD_F = 4'b1000; // Fill (wordocunt) from addr++ localparam CMD_M = 4'b1001; // set read Mask -- GitLab