From 7764d0ba1dcf064ae487ee985c43083a0909e7f4 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 5 Jan 2013 11:13:26 +0100 Subject: initial import --- tests/iwls2005/README | 7 + tests/iwls2005/aes_core/aes_cipher_top.v | 256 ++++++++++ tests/iwls2005/aes_core/aes_inv_cipher_top.v | 327 +++++++++++++ tests/iwls2005/aes_core/aes_inv_sbox.v | 328 +++++++++++++ tests/iwls2005/aes_core/aes_key_expand_128.v | 87 ++++ tests/iwls2005/aes_core/aes_rcon.v | 96 ++++ tests/iwls2005/aes_core/aes_sbox.v | 329 +++++++++++++ tests/iwls2005/aes_core/timescale.v | 1 + tests/iwls2005/fpu/except.v | 153 ++++++ tests/iwls2005/fpu/fpu.v | 560 ++++++++++++++++++++++ tests/iwls2005/fpu/post_norm.v | 676 +++++++++++++++++++++++++++ tests/iwls2005/fpu/pre_norm.v | 270 +++++++++++ tests/iwls2005/fpu/pre_norm_fmul.v | 150 ++++++ tests/iwls2005/fpu/primitives.v | 103 ++++ tests/iwls2005/i2c/i2c_master_bit_ctrl.v | 535 +++++++++++++++++++++ tests/iwls2005/i2c/i2c_master_byte_ctrl.v | 344 ++++++++++++++ tests/iwls2005/i2c/i2c_master_defines.v | 64 +++ tests/iwls2005/i2c/i2c_master_top.v | 301 ++++++++++++ tests/iwls2005/i2c/timescale.v | 2 + tests/iwls2005/run-fm.sh | 42 ++ tests/iwls2005/run-synth.sh | 45 ++ tests/iwls2005/run-synth.ys | 11 + tests/iwls2005/sasc/sasc_brg.v | 160 +++++++ tests/iwls2005/sasc/sasc_fifo4.v | 135 ++++++ tests/iwls2005/sasc/sasc_top.v | 301 ++++++++++++ tests/iwls2005/sasc/timescale.v | 1 + tests/iwls2005/simple_spi/fifo4.v | 134 ++++++ tests/iwls2005/simple_spi/simple_spi_top.v | 329 +++++++++++++ tests/iwls2005/spi/spi_clgen.v | 108 +++++ tests/iwls2005/spi/spi_defines.v | 159 +++++++ tests/iwls2005/spi/spi_shift.v | 238 ++++++++++ tests/iwls2005/spi/spi_top.v | 287 ++++++++++++ tests/iwls2005/spi/timescale.v | 2 + tests/iwls2005/ss_pcm/pcm_slv_top.v | 222 +++++++++ tests/iwls2005/ss_pcm/timescale.v | 1 + tests/iwls2005/systemcaes/aes.v | 358 ++++++++++++++ tests/iwls2005/systemcaes/byte_mixcolum.v | 92 ++++ tests/iwls2005/systemcaes/keysched.v | 248 ++++++++++ tests/iwls2005/systemcaes/mixcolum.v | 188 ++++++++ tests/iwls2005/systemcaes/sbox.v | 392 ++++++++++++++++ tests/iwls2005/systemcaes/subbytes.v | 259 ++++++++++ tests/iwls2005/systemcaes/timescale.v | 1 + tests/iwls2005/systemcaes/word_mixcolum.v | 124 +++++ tests/iwls2005/usb_phy/timescale.v | 1 + tests/iwls2005/usb_phy/usb_phy.v | 184 ++++++++ tests/iwls2005/usb_phy/usb_rx_phy.v | 452 ++++++++++++++++++ tests/iwls2005/usb_phy/usb_tx_phy.v | 465 ++++++++++++++++++ 47 files changed, 9528 insertions(+) create mode 100644 tests/iwls2005/README create mode 100644 tests/iwls2005/aes_core/aes_cipher_top.v create mode 100644 tests/iwls2005/aes_core/aes_inv_cipher_top.v create mode 100644 tests/iwls2005/aes_core/aes_inv_sbox.v create mode 100644 tests/iwls2005/aes_core/aes_key_expand_128.v create mode 100644 tests/iwls2005/aes_core/aes_rcon.v create mode 100644 tests/iwls2005/aes_core/aes_sbox.v create mode 100644 tests/iwls2005/aes_core/timescale.v create mode 100644 tests/iwls2005/fpu/except.v create mode 100644 tests/iwls2005/fpu/fpu.v create mode 100644 tests/iwls2005/fpu/post_norm.v create mode 100644 tests/iwls2005/fpu/pre_norm.v create mode 100644 tests/iwls2005/fpu/pre_norm_fmul.v create mode 100644 tests/iwls2005/fpu/primitives.v create mode 100644 tests/iwls2005/i2c/i2c_master_bit_ctrl.v create mode 100644 tests/iwls2005/i2c/i2c_master_byte_ctrl.v create mode 100644 tests/iwls2005/i2c/i2c_master_defines.v create mode 100644 tests/iwls2005/i2c/i2c_master_top.v create mode 100644 tests/iwls2005/i2c/timescale.v create mode 100755 tests/iwls2005/run-fm.sh create mode 100755 tests/iwls2005/run-synth.sh create mode 100644 tests/iwls2005/run-synth.ys create mode 100644 tests/iwls2005/sasc/sasc_brg.v create mode 100644 tests/iwls2005/sasc/sasc_fifo4.v create mode 100644 tests/iwls2005/sasc/sasc_top.v create mode 100644 tests/iwls2005/sasc/timescale.v create mode 100644 tests/iwls2005/simple_spi/fifo4.v create mode 100644 tests/iwls2005/simple_spi/simple_spi_top.v create mode 100644 tests/iwls2005/spi/spi_clgen.v create mode 100644 tests/iwls2005/spi/spi_defines.v create mode 100644 tests/iwls2005/spi/spi_shift.v create mode 100644 tests/iwls2005/spi/spi_top.v create mode 100644 tests/iwls2005/spi/timescale.v create mode 100644 tests/iwls2005/ss_pcm/pcm_slv_top.v create mode 100644 tests/iwls2005/ss_pcm/timescale.v create mode 100644 tests/iwls2005/systemcaes/aes.v create mode 100644 tests/iwls2005/systemcaes/byte_mixcolum.v create mode 100644 tests/iwls2005/systemcaes/keysched.v create mode 100644 tests/iwls2005/systemcaes/mixcolum.v create mode 100644 tests/iwls2005/systemcaes/sbox.v create mode 100644 tests/iwls2005/systemcaes/subbytes.v create mode 100644 tests/iwls2005/systemcaes/timescale.v create mode 100644 tests/iwls2005/systemcaes/word_mixcolum.v create mode 100644 tests/iwls2005/usb_phy/timescale.v create mode 100644 tests/iwls2005/usb_phy/usb_phy.v create mode 100644 tests/iwls2005/usb_phy/usb_rx_phy.v create mode 100644 tests/iwls2005/usb_phy/usb_tx_phy.v (limited to 'tests/iwls2005') diff --git a/tests/iwls2005/README b/tests/iwls2005/README new file mode 100644 index 00000000..f44a89d9 --- /dev/null +++ b/tests/iwls2005/README @@ -0,0 +1,7 @@ + +A collection of smaller rtl examples from the IWLS 2005 benchmark [1]. +We have no testbenches for these but we can check if we can +parse and synthesize them. + +[1] http://iwls.org/iwls2005/benchmarks.html + diff --git a/tests/iwls2005/aes_core/aes_cipher_top.v b/tests/iwls2005/aes_core/aes_cipher_top.v new file mode 100644 index 00000000..a0acaeb4 --- /dev/null +++ b/tests/iwls2005/aes_core/aes_cipher_top.v @@ -0,0 +1,256 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// AES Cipher Top Level //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/aes_core/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: aes_cipher_top.v,v 1.1.1.1 2002/11/09 11:22:48 rudi Exp $ +// +// $Date: 2002/11/09 11:22:48 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: aes_cipher_top.v,v $ +// Revision 1.1.1.1 2002/11/09 11:22:48 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "timescale.v" + +module aes_cipher_top(clk, rst, ld, done, key, text_in, text_out ); +input clk, rst; +input ld; +output done; +input [127:0] key; +input [127:0] text_in; +output [127:0] text_out; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +wire [31:0] w0, w1, w2, w3; +reg [127:0] text_in_r; +reg [127:0] text_out; +reg [7:0] sa00, sa01, sa02, sa03; +reg [7:0] sa10, sa11, sa12, sa13; +reg [7:0] sa20, sa21, sa22, sa23; +reg [7:0] sa30, sa31, sa32, sa33; +wire [7:0] sa00_next, sa01_next, sa02_next, sa03_next; +wire [7:0] sa10_next, sa11_next, sa12_next, sa13_next; +wire [7:0] sa20_next, sa21_next, sa22_next, sa23_next; +wire [7:0] sa30_next, sa31_next, sa32_next, sa33_next; +wire [7:0] sa00_sub, sa01_sub, sa02_sub, sa03_sub; +wire [7:0] sa10_sub, sa11_sub, sa12_sub, sa13_sub; +wire [7:0] sa20_sub, sa21_sub, sa22_sub, sa23_sub; +wire [7:0] sa30_sub, sa31_sub, sa32_sub, sa33_sub; +wire [7:0] sa00_sr, sa01_sr, sa02_sr, sa03_sr; +wire [7:0] sa10_sr, sa11_sr, sa12_sr, sa13_sr; +wire [7:0] sa20_sr, sa21_sr, sa22_sr, sa23_sr; +wire [7:0] sa30_sr, sa31_sr, sa32_sr, sa33_sr; +wire [7:0] sa00_mc, sa01_mc, sa02_mc, sa03_mc; +wire [7:0] sa10_mc, sa11_mc, sa12_mc, sa13_mc; +wire [7:0] sa20_mc, sa21_mc, sa22_mc, sa23_mc; +wire [7:0] sa30_mc, sa31_mc, sa32_mc, sa33_mc; +reg done, ld_r; +reg [3:0] dcnt; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk) + if(!rst) dcnt <= #1 4'h0; + else + if(ld) dcnt <= #1 4'hb; + else + if(|dcnt) dcnt <= #1 dcnt - 4'h1; + +always @(posedge clk) done <= #1 !(|dcnt[3:1]) & dcnt[0] & !ld; +always @(posedge clk) if(ld) text_in_r <= #1 text_in; +always @(posedge clk) ld_r <= #1 ld; + +//////////////////////////////////////////////////////////////////// +// +// Initial Permutation (AddRoundKey) +// + +always @(posedge clk) sa33 <= #1 ld_r ? text_in_r[007:000] ^ w3[07:00] : sa33_next; +always @(posedge clk) sa23 <= #1 ld_r ? text_in_r[015:008] ^ w3[15:08] : sa23_next; +always @(posedge clk) sa13 <= #1 ld_r ? text_in_r[023:016] ^ w3[23:16] : sa13_next; +always @(posedge clk) sa03 <= #1 ld_r ? text_in_r[031:024] ^ w3[31:24] : sa03_next; +always @(posedge clk) sa32 <= #1 ld_r ? text_in_r[039:032] ^ w2[07:00] : sa32_next; +always @(posedge clk) sa22 <= #1 ld_r ? text_in_r[047:040] ^ w2[15:08] : sa22_next; +always @(posedge clk) sa12 <= #1 ld_r ? text_in_r[055:048] ^ w2[23:16] : sa12_next; +always @(posedge clk) sa02 <= #1 ld_r ? text_in_r[063:056] ^ w2[31:24] : sa02_next; +always @(posedge clk) sa31 <= #1 ld_r ? text_in_r[071:064] ^ w1[07:00] : sa31_next; +always @(posedge clk) sa21 <= #1 ld_r ? text_in_r[079:072] ^ w1[15:08] : sa21_next; +always @(posedge clk) sa11 <= #1 ld_r ? text_in_r[087:080] ^ w1[23:16] : sa11_next; +always @(posedge clk) sa01 <= #1 ld_r ? text_in_r[095:088] ^ w1[31:24] : sa01_next; +always @(posedge clk) sa30 <= #1 ld_r ? text_in_r[103:096] ^ w0[07:00] : sa30_next; +always @(posedge clk) sa20 <= #1 ld_r ? text_in_r[111:104] ^ w0[15:08] : sa20_next; +always @(posedge clk) sa10 <= #1 ld_r ? text_in_r[119:112] ^ w0[23:16] : sa10_next; +always @(posedge clk) sa00 <= #1 ld_r ? text_in_r[127:120] ^ w0[31:24] : sa00_next; + +//////////////////////////////////////////////////////////////////// +// +// Round Permutations +// + +assign sa00_sr = sa00_sub; +assign sa01_sr = sa01_sub; +assign sa02_sr = sa02_sub; +assign sa03_sr = sa03_sub; +assign sa10_sr = sa11_sub; +assign sa11_sr = sa12_sub; +assign sa12_sr = sa13_sub; +assign sa13_sr = sa10_sub; +assign sa20_sr = sa22_sub; +assign sa21_sr = sa23_sub; +assign sa22_sr = sa20_sub; +assign sa23_sr = sa21_sub; +assign sa30_sr = sa33_sub; +assign sa31_sr = sa30_sub; +assign sa32_sr = sa31_sub; +assign sa33_sr = sa32_sub; +assign {sa00_mc, sa10_mc, sa20_mc, sa30_mc} = mix_col(sa00_sr,sa10_sr,sa20_sr,sa30_sr); +assign {sa01_mc, sa11_mc, sa21_mc, sa31_mc} = mix_col(sa01_sr,sa11_sr,sa21_sr,sa31_sr); +assign {sa02_mc, sa12_mc, sa22_mc, sa32_mc} = mix_col(sa02_sr,sa12_sr,sa22_sr,sa32_sr); +assign {sa03_mc, sa13_mc, sa23_mc, sa33_mc} = mix_col(sa03_sr,sa13_sr,sa23_sr,sa33_sr); +assign sa00_next = sa00_mc ^ w0[31:24]; +assign sa01_next = sa01_mc ^ w1[31:24]; +assign sa02_next = sa02_mc ^ w2[31:24]; +assign sa03_next = sa03_mc ^ w3[31:24]; +assign sa10_next = sa10_mc ^ w0[23:16]; +assign sa11_next = sa11_mc ^ w1[23:16]; +assign sa12_next = sa12_mc ^ w2[23:16]; +assign sa13_next = sa13_mc ^ w3[23:16]; +assign sa20_next = sa20_mc ^ w0[15:08]; +assign sa21_next = sa21_mc ^ w1[15:08]; +assign sa22_next = sa22_mc ^ w2[15:08]; +assign sa23_next = sa23_mc ^ w3[15:08]; +assign sa30_next = sa30_mc ^ w0[07:00]; +assign sa31_next = sa31_mc ^ w1[07:00]; +assign sa32_next = sa32_mc ^ w2[07:00]; +assign sa33_next = sa33_mc ^ w3[07:00]; + +//////////////////////////////////////////////////////////////////// +// +// Final text output +// + +always @(posedge clk) text_out[127:120] <= #1 sa00_sr ^ w0[31:24]; +always @(posedge clk) text_out[095:088] <= #1 sa01_sr ^ w1[31:24]; +always @(posedge clk) text_out[063:056] <= #1 sa02_sr ^ w2[31:24]; +always @(posedge clk) text_out[031:024] <= #1 sa03_sr ^ w3[31:24]; +always @(posedge clk) text_out[119:112] <= #1 sa10_sr ^ w0[23:16]; +always @(posedge clk) text_out[087:080] <= #1 sa11_sr ^ w1[23:16]; +always @(posedge clk) text_out[055:048] <= #1 sa12_sr ^ w2[23:16]; +always @(posedge clk) text_out[023:016] <= #1 sa13_sr ^ w3[23:16]; +always @(posedge clk) text_out[111:104] <= #1 sa20_sr ^ w0[15:08]; +always @(posedge clk) text_out[079:072] <= #1 sa21_sr ^ w1[15:08]; +always @(posedge clk) text_out[047:040] <= #1 sa22_sr ^ w2[15:08]; +always @(posedge clk) text_out[015:008] <= #1 sa23_sr ^ w3[15:08]; +always @(posedge clk) text_out[103:096] <= #1 sa30_sr ^ w0[07:00]; +always @(posedge clk) text_out[071:064] <= #1 sa31_sr ^ w1[07:00]; +always @(posedge clk) text_out[039:032] <= #1 sa32_sr ^ w2[07:00]; +always @(posedge clk) text_out[007:000] <= #1 sa33_sr ^ w3[07:00]; + +//////////////////////////////////////////////////////////////////// +// +// Generic Functions +// + +function [31:0] mix_col; +input [7:0] s0,s1,s2,s3; +reg [7:0] s0_o,s1_o,s2_o,s3_o; +begin +mix_col[31:24]=xtime(s0)^xtime(s1)^s1^s2^s3; +mix_col[23:16]=s0^xtime(s1)^xtime(s2)^s2^s3; +mix_col[15:08]=s0^s1^xtime(s2)^xtime(s3)^s3; +mix_col[07:00]=xtime(s0)^s0^s1^s2^xtime(s3); +end +endfunction + +function [7:0] xtime; +input [7:0] b; xtime={b[6:0],1'b0}^(8'h1b&{8{b[7]}}); +endfunction + +//////////////////////////////////////////////////////////////////// +// +// Modules +// + +aes_key_expand_128 u0( + .clk( clk ), + .kld( ld ), + .key( key ), + .wo_0( w0 ), + .wo_1( w1 ), + .wo_2( w2 ), + .wo_3( w3 )); + +aes_sbox us00( .a( sa00 ), .d( sa00_sub )); +aes_sbox us01( .a( sa01 ), .d( sa01_sub )); +aes_sbox us02( .a( sa02 ), .d( sa02_sub )); +aes_sbox us03( .a( sa03 ), .d( sa03_sub )); +aes_sbox us10( .a( sa10 ), .d( sa10_sub )); +aes_sbox us11( .a( sa11 ), .d( sa11_sub )); +aes_sbox us12( .a( sa12 ), .d( sa12_sub )); +aes_sbox us13( .a( sa13 ), .d( sa13_sub )); +aes_sbox us20( .a( sa20 ), .d( sa20_sub )); +aes_sbox us21( .a( sa21 ), .d( sa21_sub )); +aes_sbox us22( .a( sa22 ), .d( sa22_sub )); +aes_sbox us23( .a( sa23 ), .d( sa23_sub )); +aes_sbox us30( .a( sa30 ), .d( sa30_sub )); +aes_sbox us31( .a( sa31 ), .d( sa31_sub )); +aes_sbox us32( .a( sa32 ), .d( sa32_sub )); +aes_sbox us33( .a( sa33 ), .d( sa33_sub )); + +endmodule + + diff --git a/tests/iwls2005/aes_core/aes_inv_cipher_top.v b/tests/iwls2005/aes_core/aes_inv_cipher_top.v new file mode 100644 index 00000000..51b3525a --- /dev/null +++ b/tests/iwls2005/aes_core/aes_inv_cipher_top.v @@ -0,0 +1,327 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// AES Inverse Cipher Top Level //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/aes_core/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: aes_inv_cipher_top.v,v 1.1.1.1 2002/11/09 11:22:53 rudi Exp $ +// +// $Date: 2002/11/09 11:22:53 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: aes_inv_cipher_top.v,v $ +// Revision 1.1.1.1 2002/11/09 11:22:53 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "timescale.v" + +module aes_inv_cipher_top(clk, rst, kld, ld, done, key, text_in, text_out ); +input clk, rst; +input kld, ld; +output done; +input [127:0] key; +input [127:0] text_in; +output [127:0] text_out; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +wire [31:0] wk0, wk1, wk2, wk3; +reg [31:0] w0, w1, w2, w3; +reg [127:0] text_in_r; +reg [127:0] text_out; +reg [7:0] sa00, sa01, sa02, sa03; +reg [7:0] sa10, sa11, sa12, sa13; +reg [7:0] sa20, sa21, sa22, sa23; +reg [7:0] sa30, sa31, sa32, sa33; +wire [7:0] sa00_next, sa01_next, sa02_next, sa03_next; +wire [7:0] sa10_next, sa11_next, sa12_next, sa13_next; +wire [7:0] sa20_next, sa21_next, sa22_next, sa23_next; +wire [7:0] sa30_next, sa31_next, sa32_next, sa33_next; +wire [7:0] sa00_sub, sa01_sub, sa02_sub, sa03_sub; +wire [7:0] sa10_sub, sa11_sub, sa12_sub, sa13_sub; +wire [7:0] sa20_sub, sa21_sub, sa22_sub, sa23_sub; +wire [7:0] sa30_sub, sa31_sub, sa32_sub, sa33_sub; +wire [7:0] sa00_sr, sa01_sr, sa02_sr, sa03_sr; +wire [7:0] sa10_sr, sa11_sr, sa12_sr, sa13_sr; +wire [7:0] sa20_sr, sa21_sr, sa22_sr, sa23_sr; +wire [7:0] sa30_sr, sa31_sr, sa32_sr, sa33_sr; +wire [7:0] sa00_ark, sa01_ark, sa02_ark, sa03_ark; +wire [7:0] sa10_ark, sa11_ark, sa12_ark, sa13_ark; +wire [7:0] sa20_ark, sa21_ark, sa22_ark, sa23_ark; +wire [7:0] sa30_ark, sa31_ark, sa32_ark, sa33_ark; +reg ld_r, go, done; +reg [3:0] dcnt; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk) + if(!rst) dcnt <= #1 4'h0; + else + if(done) dcnt <= #1 4'h0; + else + if(ld) dcnt <= #1 4'h1; + else + if(go) dcnt <= #1 dcnt + 4'h1; + +always @(posedge clk) done <= #1 (dcnt==4'hb) & !ld; + +always @(posedge clk) + if(!rst) go <= #1 1'b0; + else + if(ld) go <= #1 1'b1; + else + if(done) go <= #1 1'b0; + +always @(posedge clk) if(ld) text_in_r <= #1 text_in; + +always @(posedge clk) ld_r <= #1 ld; + +//////////////////////////////////////////////////////////////////// +// +// Initial Permutation +// + +always @(posedge clk) sa33 <= #1 ld_r ? text_in_r[007:000] ^ w3[07:00] : sa33_next; +always @(posedge clk) sa23 <= #1 ld_r ? text_in_r[015:008] ^ w3[15:08] : sa23_next; +always @(posedge clk) sa13 <= #1 ld_r ? text_in_r[023:016] ^ w3[23:16] : sa13_next; +always @(posedge clk) sa03 <= #1 ld_r ? text_in_r[031:024] ^ w3[31:24] : sa03_next; +always @(posedge clk) sa32 <= #1 ld_r ? text_in_r[039:032] ^ w2[07:00] : sa32_next; +always @(posedge clk) sa22 <= #1 ld_r ? text_in_r[047:040] ^ w2[15:08] : sa22_next; +always @(posedge clk) sa12 <= #1 ld_r ? text_in_r[055:048] ^ w2[23:16] : sa12_next; +always @(posedge clk) sa02 <= #1 ld_r ? text_in_r[063:056] ^ w2[31:24] : sa02_next; +always @(posedge clk) sa31 <= #1 ld_r ? text_in_r[071:064] ^ w1[07:00] : sa31_next; +always @(posedge clk) sa21 <= #1 ld_r ? text_in_r[079:072] ^ w1[15:08] : sa21_next; +always @(posedge clk) sa11 <= #1 ld_r ? text_in_r[087:080] ^ w1[23:16] : sa11_next; +always @(posedge clk) sa01 <= #1 ld_r ? text_in_r[095:088] ^ w1[31:24] : sa01_next; +always @(posedge clk) sa30 <= #1 ld_r ? text_in_r[103:096] ^ w0[07:00] : sa30_next; +always @(posedge clk) sa20 <= #1 ld_r ? text_in_r[111:104] ^ w0[15:08] : sa20_next; +always @(posedge clk) sa10 <= #1 ld_r ? text_in_r[119:112] ^ w0[23:16] : sa10_next; +always @(posedge clk) sa00 <= #1 ld_r ? text_in_r[127:120] ^ w0[31:24] : sa00_next; + +//////////////////////////////////////////////////////////////////// +// +// Round Permutations +// + +assign sa00_sr = sa00; +assign sa01_sr = sa01; +assign sa02_sr = sa02; +assign sa03_sr = sa03; +assign sa10_sr = sa13; +assign sa11_sr = sa10; +assign sa12_sr = sa11; +assign sa13_sr = sa12; +assign sa20_sr = sa22; +assign sa21_sr = sa23; +assign sa22_sr = sa20; +assign sa23_sr = sa21; +assign sa30_sr = sa31; +assign sa31_sr = sa32; +assign sa32_sr = sa33; +assign sa33_sr = sa30; +assign sa00_ark = sa00_sub ^ w0[31:24]; +assign sa01_ark = sa01_sub ^ w1[31:24]; +assign sa02_ark = sa02_sub ^ w2[31:24]; +assign sa03_ark = sa03_sub ^ w3[31:24]; +assign sa10_ark = sa10_sub ^ w0[23:16]; +assign sa11_ark = sa11_sub ^ w1[23:16]; +assign sa12_ark = sa12_sub ^ w2[23:16]; +assign sa13_ark = sa13_sub ^ w3[23:16]; +assign sa20_ark = sa20_sub ^ w0[15:08]; +assign sa21_ark = sa21_sub ^ w1[15:08]; +assign sa22_ark = sa22_sub ^ w2[15:08]; +assign sa23_ark = sa23_sub ^ w3[15:08]; +assign sa30_ark = sa30_sub ^ w0[07:00]; +assign sa31_ark = sa31_sub ^ w1[07:00]; +assign sa32_ark = sa32_sub ^ w2[07:00]; +assign sa33_ark = sa33_sub ^ w3[07:00]; +assign {sa00_next, sa10_next, sa20_next, sa30_next} = inv_mix_col(sa00_ark,sa10_ark,sa20_ark,sa30_ark); +assign {sa01_next, sa11_next, sa21_next, sa31_next} = inv_mix_col(sa01_ark,sa11_ark,sa21_ark,sa31_ark); +assign {sa02_next, sa12_next, sa22_next, sa32_next} = inv_mix_col(sa02_ark,sa12_ark,sa22_ark,sa32_ark); +assign {sa03_next, sa13_next, sa23_next, sa33_next} = inv_mix_col(sa03_ark,sa13_ark,sa23_ark,sa33_ark); + +//////////////////////////////////////////////////////////////////// +// +// Final Text Output +// + +always @(posedge clk) text_out[127:120] <= #1 sa00_ark; +always @(posedge clk) text_out[095:088] <= #1 sa01_ark; +always @(posedge clk) text_out[063:056] <= #1 sa02_ark; +always @(posedge clk) text_out[031:024] <= #1 sa03_ark; +always @(posedge clk) text_out[119:112] <= #1 sa10_ark; +always @(posedge clk) text_out[087:080] <= #1 sa11_ark; +always @(posedge clk) text_out[055:048] <= #1 sa12_ark; +always @(posedge clk) text_out[023:016] <= #1 sa13_ark; +always @(posedge clk) text_out[111:104] <= #1 sa20_ark; +always @(posedge clk) text_out[079:072] <= #1 sa21_ark; +always @(posedge clk) text_out[047:040] <= #1 sa22_ark; +always @(posedge clk) text_out[015:008] <= #1 sa23_ark; +always @(posedge clk) text_out[103:096] <= #1 sa30_ark; +always @(posedge clk) text_out[071:064] <= #1 sa31_ark; +always @(posedge clk) text_out[039:032] <= #1 sa32_ark; +always @(posedge clk) text_out[007:000] <= #1 sa33_ark; + +//////////////////////////////////////////////////////////////////// +// +// Generic Functions +// + +function [31:0] inv_mix_col; +input [7:0] s0,s1,s2,s3; +begin +inv_mix_col[31:24]=pmul_e(s0)^pmul_b(s1)^pmul_d(s2)^pmul_9(s3); +inv_mix_col[23:16]=pmul_9(s0)^pmul_e(s1)^pmul_b(s2)^pmul_d(s3); +inv_mix_col[15:08]=pmul_d(s0)^pmul_9(s1)^pmul_e(s2)^pmul_b(s3); +inv_mix_col[07:00]=pmul_b(s0)^pmul_d(s1)^pmul_9(s2)^pmul_e(s3); +end +endfunction + +// Some synthesis tools don't like xtime being called recursevly ... +function [7:0] pmul_e; +input [7:0] b; +reg [7:0] two,four,eight; +begin +two=xtime(b);four=xtime(two);eight=xtime(four);pmul_e=eight^four^two; +end +endfunction + +function [7:0] pmul_9; +input [7:0] b; +reg [7:0] two,four,eight; +begin +two=xtime(b);four=xtime(two);eight=xtime(four);pmul_9=eight^b; +end +endfunction + +function [7:0] pmul_d; +input [7:0] b; +reg [7:0] two,four,eight; +begin +two=xtime(b);four=xtime(two);eight=xtime(four);pmul_d=eight^four^b; +end +endfunction + +function [7:0] pmul_b; +input [7:0] b; +reg [7:0] two,four,eight; +begin +two=xtime(b);four=xtime(two);eight=xtime(four);pmul_b=eight^two^b; +end +endfunction + +function [7:0] xtime; +input [7:0] b;xtime={b[6:0],1'b0}^(8'h1b&{8{b[7]}}); +endfunction + +//////////////////////////////////////////////////////////////////// +// +// Key Buffer +// + +reg [127:0] kb[10:0]; +reg [3:0] kcnt; +reg kdone; +reg kb_ld; + +always @(posedge clk) + if(!rst) kcnt <= #1 4'ha; + else + if(kld) kcnt <= #1 4'ha; + else + if(kb_ld) kcnt <= #1 kcnt - 4'h1; + +always @(posedge clk) + if(!rst) kb_ld <= #1 1'b0; + else + if(kld) kb_ld <= #1 1'b1; + else + if(kcnt==4'h0) kb_ld <= #1 1'b0; + +always @(posedge clk) kdone <= #1 (kcnt==4'h0) & !kld; +always @(posedge clk) if(kb_ld) kb[kcnt] <= #1 {wk3, wk2, wk1, wk0}; +always @(posedge clk) {w3, w2, w1, w0} <= #1 kb[dcnt]; + +//////////////////////////////////////////////////////////////////// +// +// Modules +// + +aes_key_expand_128 u0( + .clk( clk ), + .kld( kld ), + .key( key ), + .wo_0( wk0 ), + .wo_1( wk1 ), + .wo_2( wk2 ), + .wo_3( wk3 )); + +aes_inv_sbox us00( .a( sa00_sr ), .d( sa00_sub )); +aes_inv_sbox us01( .a( sa01_sr ), .d( sa01_sub )); +aes_inv_sbox us02( .a( sa02_sr ), .d( sa02_sub )); +aes_inv_sbox us03( .a( sa03_sr ), .d( sa03_sub )); +aes_inv_sbox us10( .a( sa10_sr ), .d( sa10_sub )); +aes_inv_sbox us11( .a( sa11_sr ), .d( sa11_sub )); +aes_inv_sbox us12( .a( sa12_sr ), .d( sa12_sub )); +aes_inv_sbox us13( .a( sa13_sr ), .d( sa13_sub )); +aes_inv_sbox us20( .a( sa20_sr ), .d( sa20_sub )); +aes_inv_sbox us21( .a( sa21_sr ), .d( sa21_sub )); +aes_inv_sbox us22( .a( sa22_sr ), .d( sa22_sub )); +aes_inv_sbox us23( .a( sa23_sr ), .d( sa23_sub )); +aes_inv_sbox us30( .a( sa30_sr ), .d( sa30_sub )); +aes_inv_sbox us31( .a( sa31_sr ), .d( sa31_sub )); +aes_inv_sbox us32( .a( sa32_sr ), .d( sa32_sub )); +aes_inv_sbox us33( .a( sa33_sr ), .d( sa33_sub )); + +endmodule + diff --git a/tests/iwls2005/aes_core/aes_inv_sbox.v b/tests/iwls2005/aes_core/aes_inv_sbox.v new file mode 100644 index 00000000..323181eb --- /dev/null +++ b/tests/iwls2005/aes_core/aes_inv_sbox.v @@ -0,0 +1,328 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// AES Inverse SBOX (ROM) //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/aes_core/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: aes_inv_sbox.v,v 1.1.1.1 2002/11/09 11:22:55 rudi Exp $ +// +// $Date: 2002/11/09 11:22:55 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: aes_inv_sbox.v,v $ +// Revision 1.1.1.1 2002/11/09 11:22:55 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "timescale.v" + +module aes_inv_sbox(a,d); +input [7:0] a; +output [7:0] d; +reg [7:0] d; + +always @(a) + case(a) // synopsys full_case parallel_case + 8'h00: d=8'h52; + 8'h01: d=8'h09; + 8'h02: d=8'h6a; + 8'h03: d=8'hd5; + 8'h04: d=8'h30; + 8'h05: d=8'h36; + 8'h06: d=8'ha5; + 8'h07: d=8'h38; + 8'h08: d=8'hbf; + 8'h09: d=8'h40; + 8'h0a: d=8'ha3; + 8'h0b: d=8'h9e; + 8'h0c: d=8'h81; + 8'h0d: d=8'hf3; + 8'h0e: d=8'hd7; + 8'h0f: d=8'hfb; + 8'h10: d=8'h7c; + 8'h11: d=8'he3; + 8'h12: d=8'h39; + 8'h13: d=8'h82; + 8'h14: d=8'h9b; + 8'h15: d=8'h2f; + 8'h16: d=8'hff; + 8'h17: d=8'h87; + 8'h18: d=8'h34; + 8'h19: d=8'h8e; + 8'h1a: d=8'h43; + 8'h1b: d=8'h44; + 8'h1c: d=8'hc4; + 8'h1d: d=8'hde; + 8'h1e: d=8'he9; + 8'h1f: d=8'hcb; + 8'h20: d=8'h54; + 8'h21: d=8'h7b; + 8'h22: d=8'h94; + 8'h23: d=8'h32; + 8'h24: d=8'ha6; + 8'h25: d=8'hc2; + 8'h26: d=8'h23; + 8'h27: d=8'h3d; + 8'h28: d=8'hee; + 8'h29: d=8'h4c; + 8'h2a: d=8'h95; + 8'h2b: d=8'h0b; + 8'h2c: d=8'h42; + 8'h2d: d=8'hfa; + 8'h2e: d=8'hc3; + 8'h2f: d=8'h4e; + 8'h30: d=8'h08; + 8'h31: d=8'h2e; + 8'h32: d=8'ha1; + 8'h33: d=8'h66; + 8'h34: d=8'h28; + 8'h35: d=8'hd9; + 8'h36: d=8'h24; + 8'h37: d=8'hb2; + 8'h38: d=8'h76; + 8'h39: d=8'h5b; + 8'h3a: d=8'ha2; + 8'h3b: d=8'h49; + 8'h3c: d=8'h6d; + 8'h3d: d=8'h8b; + 8'h3e: d=8'hd1; + 8'h3f: d=8'h25; + 8'h40: d=8'h72; + 8'h41: d=8'hf8; + 8'h42: d=8'hf6; + 8'h43: d=8'h64; + 8'h44: d=8'h86; + 8'h45: d=8'h68; + 8'h46: d=8'h98; + 8'h47: d=8'h16; + 8'h48: d=8'hd4; + 8'h49: d=8'ha4; + 8'h4a: d=8'h5c; + 8'h4b: d=8'hcc; + 8'h4c: d=8'h5d; + 8'h4d: d=8'h65; + 8'h4e: d=8'hb6; + 8'h4f: d=8'h92; + 8'h50: d=8'h6c; + 8'h51: d=8'h70; + 8'h52: d=8'h48; + 8'h53: d=8'h50; + 8'h54: d=8'hfd; + 8'h55: d=8'hed; + 8'h56: d=8'hb9; + 8'h57: d=8'hda; + 8'h58: d=8'h5e; + 8'h59: d=8'h15; + 8'h5a: d=8'h46; + 8'h5b: d=8'h57; + 8'h5c: d=8'ha7; + 8'h5d: d=8'h8d; + 8'h5e: d=8'h9d; + 8'h5f: d=8'h84; + 8'h60: d=8'h90; + 8'h61: d=8'hd8; + 8'h62: d=8'hab; + 8'h63: d=8'h00; + 8'h64: d=8'h8c; + 8'h65: d=8'hbc; + 8'h66: d=8'hd3; + 8'h67: d=8'h0a; + 8'h68: d=8'hf7; + 8'h69: d=8'he4; + 8'h6a: d=8'h58; + 8'h6b: d=8'h05; + 8'h6c: d=8'hb8; + 8'h6d: d=8'hb3; + 8'h6e: d=8'h45; + 8'h6f: d=8'h06; + 8'h70: d=8'hd0; + 8'h71: d=8'h2c; + 8'h72: d=8'h1e; + 8'h73: d=8'h8f; + 8'h74: d=8'hca; + 8'h75: d=8'h3f; + 8'h76: d=8'h0f; + 8'h77: d=8'h02; + 8'h78: d=8'hc1; + 8'h79: d=8'haf; + 8'h7a: d=8'hbd; + 8'h7b: d=8'h03; + 8'h7c: d=8'h01; + 8'h7d: d=8'h13; + 8'h7e: d=8'h8a; + 8'h7f: d=8'h6b; + 8'h80: d=8'h3a; + 8'h81: d=8'h91; + 8'h82: d=8'h11; + 8'h83: d=8'h41; + 8'h84: d=8'h4f; + 8'h85: d=8'h67; + 8'h86: d=8'hdc; + 8'h87: d=8'hea; + 8'h88: d=8'h97; + 8'h89: d=8'hf2; + 8'h8a: d=8'hcf; + 8'h8b: d=8'hce; + 8'h8c: d=8'hf0; + 8'h8d: d=8'hb4; + 8'h8e: d=8'he6; + 8'h8f: d=8'h73; + 8'h90: d=8'h96; + 8'h91: d=8'hac; + 8'h92: d=8'h74; + 8'h93: d=8'h22; + 8'h94: d=8'he7; + 8'h95: d=8'had; + 8'h96: d=8'h35; + 8'h97: d=8'h85; + 8'h98: d=8'he2; + 8'h99: d=8'hf9; + 8'h9a: d=8'h37; + 8'h9b: d=8'he8; + 8'h9c: d=8'h1c; + 8'h9d: d=8'h75; + 8'h9e: d=8'hdf; + 8'h9f: d=8'h6e; + 8'ha0: d=8'h47; + 8'ha1: d=8'hf1; + 8'ha2: d=8'h1a; + 8'ha3: d=8'h71; + 8'ha4: d=8'h1d; + 8'ha5: d=8'h29; + 8'ha6: d=8'hc5; + 8'ha7: d=8'h89; + 8'ha8: d=8'h6f; + 8'ha9: d=8'hb7; + 8'haa: d=8'h62; + 8'hab: d=8'h0e; + 8'hac: d=8'haa; + 8'had: d=8'h18; + 8'hae: d=8'hbe; + 8'haf: d=8'h1b; + 8'hb0: d=8'hfc; + 8'hb1: d=8'h56; + 8'hb2: d=8'h3e; + 8'hb3: d=8'h4b; + 8'hb4: d=8'hc6; + 8'hb5: d=8'hd2; + 8'hb6: d=8'h79; + 8'hb7: d=8'h20; + 8'hb8: d=8'h9a; + 8'hb9: d=8'hdb; + 8'hba: d=8'hc0; + 8'hbb: d=8'hfe; + 8'hbc: d=8'h78; + 8'hbd: d=8'hcd; + 8'hbe: d=8'h5a; + 8'hbf: d=8'hf4; + 8'hc0: d=8'h1f; + 8'hc1: d=8'hdd; + 8'hc2: d=8'ha8; + 8'hc3: d=8'h33; + 8'hc4: d=8'h88; + 8'hc5: d=8'h07; + 8'hc6: d=8'hc7; + 8'hc7: d=8'h31; + 8'hc8: d=8'hb1; + 8'hc9: d=8'h12; + 8'hca: d=8'h10; + 8'hcb: d=8'h59; + 8'hcc: d=8'h27; + 8'hcd: d=8'h80; + 8'hce: d=8'hec; + 8'hcf: d=8'h5f; + 8'hd0: d=8'h60; + 8'hd1: d=8'h51; + 8'hd2: d=8'h7f; + 8'hd3: d=8'ha9; + 8'hd4: d=8'h19; + 8'hd5: d=8'hb5; + 8'hd6: d=8'h4a; + 8'hd7: d=8'h0d; + 8'hd8: d=8'h2d; + 8'hd9: d=8'he5; + 8'hda: d=8'h7a; + 8'hdb: d=8'h9f; + 8'hdc: d=8'h93; + 8'hdd: d=8'hc9; + 8'hde: d=8'h9c; + 8'hdf: d=8'hef; + 8'he0: d=8'ha0; + 8'he1: d=8'he0; + 8'he2: d=8'h3b; + 8'he3: d=8'h4d; + 8'he4: d=8'hae; + 8'he5: d=8'h2a; + 8'he6: d=8'hf5; + 8'he7: d=8'hb0; + 8'he8: d=8'hc8; + 8'he9: d=8'heb; + 8'hea: d=8'hbb; + 8'heb: d=8'h3c; + 8'hec: d=8'h83; + 8'hed: d=8'h53; + 8'hee: d=8'h99; + 8'hef: d=8'h61; + 8'hf0: d=8'h17; + 8'hf1: d=8'h2b; + 8'hf2: d=8'h04; + 8'hf3: d=8'h7e; + 8'hf4: d=8'hba; + 8'hf5: d=8'h77; + 8'hf6: d=8'hd6; + 8'hf7: d=8'h26; + 8'hf8: d=8'he1; + 8'hf9: d=8'h69; + 8'hfa: d=8'h14; + 8'hfb: d=8'h63; + 8'hfc: d=8'h55; + 8'hfd: d=8'h21; + 8'hfe: d=8'h0c; + 8'hff: d=8'h7d; + endcase +endmodule + + diff --git a/tests/iwls2005/aes_core/aes_key_expand_128.v b/tests/iwls2005/aes_core/aes_key_expand_128.v new file mode 100644 index 00000000..ddc74b73 --- /dev/null +++ b/tests/iwls2005/aes_core/aes_key_expand_128.v @@ -0,0 +1,87 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// AES Key Expand Block (for 128 bit keys) //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/aes_core/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: aes_key_expand_128.v,v 1.1.1.1 2002/11/09 11:22:38 rudi Exp $ +// +// $Date: 2002/11/09 11:22:38 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: aes_key_expand_128.v,v $ +// Revision 1.1.1.1 2002/11/09 11:22:38 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "timescale.v" + +module aes_key_expand_128(clk, kld, key, wo_0, wo_1, wo_2, wo_3); +input clk; +input kld; +input [127:0] key; +output [31:0] wo_0, wo_1, wo_2, wo_3; +reg [31:0] w[3:0]; +wire [31:0] tmp_w; +wire [31:0] subword; +wire [31:0] rcon; + +assign wo_0 = w[0]; +assign wo_1 = w[1]; +assign wo_2 = w[2]; +assign wo_3 = w[3]; +always @(posedge clk) w[0] <= #1 kld ? key[127:096] : w[0]^subword^rcon; +always @(posedge clk) w[1] <= #1 kld ? key[095:064] : w[0]^w[1]^subword^rcon; +always @(posedge clk) w[2] <= #1 kld ? key[063:032] : w[0]^w[2]^w[1]^subword^rcon; +always @(posedge clk) w[3] <= #1 kld ? key[031:000] : w[0]^w[3]^w[2]^w[1]^subword^rcon; +assign tmp_w = w[3]; +aes_sbox u0( .a(tmp_w[23:16]), .d(subword[31:24])); +aes_sbox u1( .a(tmp_w[15:08]), .d(subword[23:16])); +aes_sbox u2( .a(tmp_w[07:00]), .d(subword[15:08])); +aes_sbox u3( .a(tmp_w[31:24]), .d(subword[07:00])); +aes_rcon r0( .clk(clk), .kld(kld), .out(rcon)); +endmodule + diff --git a/tests/iwls2005/aes_core/aes_rcon.v b/tests/iwls2005/aes_core/aes_rcon.v new file mode 100644 index 00000000..c2c0a124 --- /dev/null +++ b/tests/iwls2005/aes_core/aes_rcon.v @@ -0,0 +1,96 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// AES RCON Block //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/aes_core/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: aes_rcon.v,v 1.1.1.1 2002/11/09 11:22:38 rudi Exp $ +// +// $Date: 2002/11/09 11:22:38 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: aes_rcon.v,v $ +// Revision 1.1.1.1 2002/11/09 11:22:38 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "timescale.v" + +module aes_rcon(clk, kld, out); +input clk; +input kld; +output [31:0] out; +reg [31:0] out; +reg [3:0] rcnt; +wire [3:0] rcnt_next; + +always @(posedge clk) + if(kld) out <= #1 32'h01_00_00_00; + else out <= #1 frcon(rcnt_next); + +assign rcnt_next = rcnt + 4'h1; +always @(posedge clk) + if(kld) rcnt <= #1 4'h0; + else rcnt <= #1 rcnt_next; + +function [31:0] frcon; +input [3:0] i; +case(i) // synopsys parallel_case + 4'h0: frcon=32'h01_00_00_00; + 4'h1: frcon=32'h02_00_00_00; + 4'h2: frcon=32'h04_00_00_00; + 4'h3: frcon=32'h08_00_00_00; + 4'h4: frcon=32'h10_00_00_00; + 4'h5: frcon=32'h20_00_00_00; + 4'h6: frcon=32'h40_00_00_00; + 4'h7: frcon=32'h80_00_00_00; + 4'h8: frcon=32'h1b_00_00_00; + 4'h9: frcon=32'h36_00_00_00; + default: frcon=32'h00_00_00_00; +endcase +endfunction + +endmodule diff --git a/tests/iwls2005/aes_core/aes_sbox.v b/tests/iwls2005/aes_core/aes_sbox.v new file mode 100644 index 00000000..e01d75ef --- /dev/null +++ b/tests/iwls2005/aes_core/aes_sbox.v @@ -0,0 +1,329 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// AES SBOX (ROM) //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/aes_core/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: aes_sbox.v,v 1.1.1.1 2002/11/09 11:22:38 rudi Exp $ +// +// $Date: 2002/11/09 11:22:38 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: aes_sbox.v,v $ +// Revision 1.1.1.1 2002/11/09 11:22:38 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "timescale.v" + +module aes_sbox(a,d); +input [7:0] a; +output [7:0] d; +reg [7:0] d; + +always @(a) + case(a) // synopsys full_case parallel_case + 8'h00: d=8'h63; + 8'h01: d=8'h7c; + 8'h02: d=8'h77; + 8'h03: d=8'h7b; + 8'h04: d=8'hf2; + 8'h05: d=8'h6b; + 8'h06: d=8'h6f; + 8'h07: d=8'hc5; + 8'h08: d=8'h30; + 8'h09: d=8'h01; + 8'h0a: d=8'h67; + 8'h0b: d=8'h2b; + 8'h0c: d=8'hfe; + 8'h0d: d=8'hd7; + 8'h0e: d=8'hab; + 8'h0f: d=8'h76; + 8'h10: d=8'hca; + 8'h11: d=8'h82; + 8'h12: d=8'hc9; + 8'h13: d=8'h7d; + 8'h14: d=8'hfa; + 8'h15: d=8'h59; + 8'h16: d=8'h47; + 8'h17: d=8'hf0; + 8'h18: d=8'had; + 8'h19: d=8'hd4; + 8'h1a: d=8'ha2; + 8'h1b: d=8'haf; + 8'h1c: d=8'h9c; + 8'h1d: d=8'ha4; + 8'h1e: d=8'h72; + 8'h1f: d=8'hc0; + 8'h20: d=8'hb7; + 8'h21: d=8'hfd; + 8'h22: d=8'h93; + 8'h23: d=8'h26; + 8'h24: d=8'h36; + 8'h25: d=8'h3f; + 8'h26: d=8'hf7; + 8'h27: d=8'hcc; + 8'h28: d=8'h34; + 8'h29: d=8'ha5; + 8'h2a: d=8'he5; + 8'h2b: d=8'hf1; + 8'h2c: d=8'h71; + 8'h2d: d=8'hd8; + 8'h2e: d=8'h31; + 8'h2f: d=8'h15; + 8'h30: d=8'h04; + 8'h31: d=8'hc7; + 8'h32: d=8'h23; + 8'h33: d=8'hc3; + 8'h34: d=8'h18; + 8'h35: d=8'h96; + 8'h36: d=8'h05; + 8'h37: d=8'h9a; + 8'h38: d=8'h07; + 8'h39: d=8'h12; + 8'h3a: d=8'h80; + 8'h3b: d=8'he2; + 8'h3c: d=8'heb; + 8'h3d: d=8'h27; + 8'h3e: d=8'hb2; + 8'h3f: d=8'h75; + 8'h40: d=8'h09; + 8'h41: d=8'h83; + 8'h42: d=8'h2c; + 8'h43: d=8'h1a; + 8'h44: d=8'h1b; + 8'h45: d=8'h6e; + 8'h46: d=8'h5a; + 8'h47: d=8'ha0; + 8'h48: d=8'h52; + 8'h49: d=8'h3b; + 8'h4a: d=8'hd6; + 8'h4b: d=8'hb3; + 8'h4c: d=8'h29; + 8'h4d: d=8'he3; + 8'h4e: d=8'h2f; + 8'h4f: d=8'h84; + 8'h50: d=8'h53; + 8'h51: d=8'hd1; + 8'h52: d=8'h00; + 8'h53: d=8'hed; + 8'h54: d=8'h20; + 8'h55: d=8'hfc; + 8'h56: d=8'hb1; + 8'h57: d=8'h5b; + 8'h58: d=8'h6a; + 8'h59: d=8'hcb; + 8'h5a: d=8'hbe; + 8'h5b: d=8'h39; + 8'h5c: d=8'h4a; + 8'h5d: d=8'h4c; + 8'h5e: d=8'h58; + 8'h5f: d=8'hcf; + 8'h60: d=8'hd0; + 8'h61: d=8'hef; + 8'h62: d=8'haa; + 8'h63: d=8'hfb; + 8'h64: d=8'h43; + 8'h65: d=8'h4d; + 8'h66: d=8'h33; + 8'h67: d=8'h85; + 8'h68: d=8'h45; + 8'h69: d=8'hf9; + 8'h6a: d=8'h02; + 8'h6b: d=8'h7f; + 8'h6c: d=8'h50; + 8'h6d: d=8'h3c; + 8'h6e: d=8'h9f; + 8'h6f: d=8'ha8; + 8'h70: d=8'h51; + 8'h71: d=8'ha3; + 8'h72: d=8'h40; + 8'h73: d=8'h8f; + 8'h74: d=8'h92; + 8'h75: d=8'h9d; + 8'h76: d=8'h38; + 8'h77: d=8'hf5; + 8'h78: d=8'hbc; + 8'h79: d=8'hb6; + 8'h7a: d=8'hda; + 8'h7b: d=8'h21; + 8'h7c: d=8'h10; + 8'h7d: d=8'hff; + 8'h7e: d=8'hf3; + 8'h7f: d=8'hd2; + 8'h80: d=8'hcd; + 8'h81: d=8'h0c; + 8'h82: d=8'h13; + 8'h83: d=8'hec; + 8'h84: d=8'h5f; + 8'h85: d=8'h97; + 8'h86: d=8'h44; + 8'h87: d=8'h17; + 8'h88: d=8'hc4; + 8'h89: d=8'ha7; + 8'h8a: d=8'h7e; + 8'h8b: d=8'h3d; + 8'h8c: d=8'h64; + 8'h8d: d=8'h5d; + 8'h8e: d=8'h19; + 8'h8f: d=8'h73; + 8'h90: d=8'h60; + 8'h91: d=8'h81; + 8'h92: d=8'h4f; + 8'h93: d=8'hdc; + 8'h94: d=8'h22; + 8'h95: d=8'h2a; + 8'h96: d=8'h90; + 8'h97: d=8'h88; + 8'h98: d=8'h46; + 8'h99: d=8'hee; + 8'h9a: d=8'hb8; + 8'h9b: d=8'h14; + 8'h9c: d=8'hde; + 8'h9d: d=8'h5e; + 8'h9e: d=8'h0b; + 8'h9f: d=8'hdb; + 8'ha0: d=8'he0; + 8'ha1: d=8'h32; + 8'ha2: d=8'h3a; + 8'ha3: d=8'h0a; + 8'ha4: d=8'h49; + 8'ha5: d=8'h06; + 8'ha6: d=8'h24; + 8'ha7: d=8'h5c; + 8'ha8: d=8'hc2; + 8'ha9: d=8'hd3; + 8'haa: d=8'hac; + 8'hab: d=8'h62; + 8'hac: d=8'h91; + 8'had: d=8'h95; + 8'hae: d=8'he4; + 8'haf: d=8'h79; + 8'hb0: d=8'he7; + 8'hb1: d=8'hc8; + 8'hb2: d=8'h37; + 8'hb3: d=8'h6d; + 8'hb4: d=8'h8d; + 8'hb5: d=8'hd5; + 8'hb6: d=8'h4e; + 8'hb7: d=8'ha9; + 8'hb8: d=8'h6c; + 8'hb9: d=8'h56; + 8'hba: d=8'hf4; + 8'hbb: d=8'hea; + 8'hbc: d=8'h65; + 8'hbd: d=8'h7a; + 8'hbe: d=8'hae; + 8'hbf: d=8'h08; + 8'hc0: d=8'hba; + 8'hc1: d=8'h78; + 8'hc2: d=8'h25; + 8'hc3: d=8'h2e; + 8'hc4: d=8'h1c; + 8'hc5: d=8'ha6; + 8'hc6: d=8'hb4; + 8'hc7: d=8'hc6; + 8'hc8: d=8'he8; + 8'hc9: d=8'hdd; + 8'hca: d=8'h74; + 8'hcb: d=8'h1f; + 8'hcc: d=8'h4b; + 8'hcd: d=8'hbd; + 8'hce: d=8'h8b; + 8'hcf: d=8'h8a; + 8'hd0: d=8'h70; + 8'hd1: d=8'h3e; + 8'hd2: d=8'hb5; + 8'hd3: d=8'h66; + 8'hd4: d=8'h48; + 8'hd5: d=8'h03; + 8'hd6: d=8'hf6; + 8'hd7: d=8'h0e; + 8'hd8: d=8'h61; + 8'hd9: d=8'h35; + 8'hda: d=8'h57; + 8'hdb: d=8'hb9; + 8'hdc: d=8'h86; + 8'hdd: d=8'hc1; + 8'hde: d=8'h1d; + 8'hdf: d=8'h9e; + 8'he0: d=8'he1; + 8'he1: d=8'hf8; + 8'he2: d=8'h98; + 8'he3: d=8'h11; + 8'he4: d=8'h69; + 8'he5: d=8'hd9; + 8'he6: d=8'h8e; + 8'he7: d=8'h94; + 8'he8: d=8'h9b; + 8'he9: d=8'h1e; + 8'hea: d=8'h87; + 8'heb: d=8'he9; + 8'hec: d=8'hce; + 8'hed: d=8'h55; + 8'hee: d=8'h28; + 8'hef: d=8'hdf; + 8'hf0: d=8'h8c; + 8'hf1: d=8'ha1; + 8'hf2: d=8'h89; + 8'hf3: d=8'h0d; + 8'hf4: d=8'hbf; + 8'hf5: d=8'he6; + 8'hf6: d=8'h42; + 8'hf7: d=8'h68; + 8'hf8: d=8'h41; + 8'hf9: d=8'h99; + 8'hfa: d=8'h2d; + 8'hfb: d=8'h0f; + 8'hfc: d=8'hb0; + 8'hfd: d=8'h54; + 8'hfe: d=8'hbb; + 8'hff: d=8'h16; + endcase + +endmodule + + diff --git a/tests/iwls2005/aes_core/timescale.v b/tests/iwls2005/aes_core/timescale.v new file mode 100644 index 00000000..ff9e265a --- /dev/null +++ b/tests/iwls2005/aes_core/timescale.v @@ -0,0 +1 @@ +`timescale 1ns / 10ps diff --git a/tests/iwls2005/fpu/except.v b/tests/iwls2005/fpu/except.v new file mode 100644 index 00000000..007099fe --- /dev/null +++ b/tests/iwls2005/fpu/except.v @@ -0,0 +1,153 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// EXCEPT //// +//// Floating Point Exception/Special Numbers Unit //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + + +`timescale 1ns / 100ps + + +module except( clk, opa, opb, inf, ind, qnan, snan, opa_nan, opb_nan, + opa_00, opb_00, opa_inf, opb_inf, opa_dn, opb_dn); +input clk; +input [31:0] opa, opb; +output inf, ind, qnan, snan, opa_nan, opb_nan; +output opa_00, opb_00; +output opa_inf, opb_inf; +output opa_dn; +output opb_dn; + +//////////////////////////////////////////////////////////////////////// +// +// Local Wires and registers +// + +wire [7:0] expa, expb; // alias to opX exponent +wire [22:0] fracta, fractb; // alias to opX fraction +reg expa_ff, infa_f_r, qnan_r_a, snan_r_a; +reg expb_ff, infb_f_r, qnan_r_b, snan_r_b; +reg inf, ind, qnan, snan; // Output registers +reg opa_nan, opb_nan; +reg expa_00, expb_00, fracta_00, fractb_00; +reg opa_00, opb_00; +reg opa_inf, opb_inf; +reg opa_dn, opb_dn; + +//////////////////////////////////////////////////////////////////////// +// +// Aliases +// + +assign expa = opa[30:23]; +assign expb = opb[30:23]; +assign fracta = opa[22:0]; +assign fractb = opb[22:0]; + +//////////////////////////////////////////////////////////////////////// +// +// Determine if any of the input operators is a INF or NAN or any other special number +// + +always @(posedge clk) + expa_ff <= #1 &expa; + +always @(posedge clk) + expb_ff <= #1 &expb; + +always @(posedge clk) + infa_f_r <= #1 !(|fracta); + +always @(posedge clk) + infb_f_r <= #1 !(|fractb); + +always @(posedge clk) + qnan_r_a <= #1 fracta[22]; + +always @(posedge clk) + snan_r_a <= #1 !fracta[22] & |fracta[21:0]; + +always @(posedge clk) + qnan_r_b <= #1 fractb[22]; + +always @(posedge clk) + snan_r_b <= #1 !fractb[22] & |fractb[21:0]; + +always @(posedge clk) + ind <= #1 (expa_ff & infa_f_r) & (expb_ff & infb_f_r); + +always @(posedge clk) + inf <= #1 (expa_ff & infa_f_r) | (expb_ff & infb_f_r); + +always @(posedge clk) + qnan <= #1 (expa_ff & qnan_r_a) | (expb_ff & qnan_r_b); + +always @(posedge clk) + snan <= #1 (expa_ff & snan_r_a) | (expb_ff & snan_r_b); + +always @(posedge clk) + opa_nan <= #1 &expa & (|fracta[22:0]); + +always @(posedge clk) + opb_nan <= #1 &expb & (|fractb[22:0]); + +always @(posedge clk) + opa_inf <= #1 (expa_ff & infa_f_r); + +always @(posedge clk) + opb_inf <= #1 (expb_ff & infb_f_r); + +always @(posedge clk) + expa_00 <= #1 !(|expa); + +always @(posedge clk) + expb_00 <= #1 !(|expb); + +always @(posedge clk) + fracta_00 <= #1 !(|fracta); + +always @(posedge clk) + fractb_00 <= #1 !(|fractb); + +always @(posedge clk) + opa_00 <= #1 expa_00 & fracta_00; + +always @(posedge clk) + opb_00 <= #1 expb_00 & fractb_00; + +always @(posedge clk) + opa_dn <= #1 expa_00; + +always @(posedge clk) + opb_dn <= #1 expb_00; + +endmodule + diff --git a/tests/iwls2005/fpu/fpu.v b/tests/iwls2005/fpu/fpu.v new file mode 100644 index 00000000..165a1d24 --- /dev/null +++ b/tests/iwls2005/fpu/fpu.v @@ -0,0 +1,560 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// FPU //// +//// Floating Point Unit (Single precision) //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +`timescale 1ns / 100ps + +/* + +FPU Operations (fpu_op): +======================== + +0 = add +1 = sub +2 = mul +3 = div +4 = +5 = +6 = +7 = + +Rounding Modes (rmode): +======================= + +0 = round_nearest_even +1 = round_to_zero +2 = round_up +3 = round_down + +*/ + + +module fpu( clk, rmode, fpu_op, opa, opb, out, inf, snan, qnan, ine, overflow, underflow, zero, div_by_zero); +input clk; +input [1:0] rmode; +input [2:0] fpu_op; +input [31:0] opa, opb; +output [31:0] out; +output inf, snan, qnan; +output ine; +output overflow, underflow; +output zero; +output div_by_zero; + +parameter INF = 31'h7f800000, + QNAN = 31'h7fc00001, + SNAN = 31'h7f800001; + +//////////////////////////////////////////////////////////////////////// +// +// Local Wires +// +reg zero; +reg [31:0] opa_r, opb_r; // Input operand registers +reg [31:0] out; // Output register +reg div_by_zero; // Divide by zero output register +wire signa, signb; // alias to opX sign +wire sign_fasu; // sign output +wire [26:0] fracta, fractb; // Fraction Outputs from EQU block +wire [7:0] exp_fasu; // Exponent output from EQU block +reg [7:0] exp_r; // Exponent output (registerd) +wire [26:0] fract_out_d; // fraction output +wire co; // carry output +reg [27:0] fract_out_q; // fraction output (registerd) +wire [30:0] out_d; // Intermediate final result output +wire overflow_d, underflow_d;// Overflow/Underflow Indicators +reg overflow, underflow; // Output registers for Overflow & Underflow +reg inf, snan, qnan; // Output Registers for INF, SNAN and QNAN +reg ine; // Output Registers for INE +reg [1:0] rmode_r1, rmode_r2, // Pipeline registers for rounding mode + rmode_r3; +reg [2:0] fpu_op_r1, fpu_op_r2, // Pipeline registers for fp opration + fpu_op_r3; +wire mul_inf, div_inf; +wire mul_00, div_00; + +//////////////////////////////////////////////////////////////////////// +// +// Input Registers +// + +always @(posedge clk) + opa_r <= #1 opa; + +always @(posedge clk) + opb_r <= #1 opb; + +always @(posedge clk) + rmode_r1 <= #1 rmode; + +always @(posedge clk) + rmode_r2 <= #1 rmode_r1; + +always @(posedge clk) + rmode_r3 <= #1 rmode_r2; + +always @(posedge clk) + fpu_op_r1 <= #1 fpu_op; + +always @(posedge clk) + fpu_op_r2 <= #1 fpu_op_r1; + +always @(posedge clk) + fpu_op_r3 <= #1 fpu_op_r2; + +//////////////////////////////////////////////////////////////////////// +// +// Exceptions block +// +wire inf_d, ind_d, qnan_d, snan_d, opa_nan, opb_nan; +wire opa_00, opb_00; +wire opa_inf, opb_inf; +wire opa_dn, opb_dn; + +except u0( .clk(clk), + .opa(opa_r), .opb(opb_r), + .inf(inf_d), .ind(ind_d), + .qnan(qnan_d), .snan(snan_d), + .opa_nan(opa_nan), .opb_nan(opb_nan), + .opa_00(opa_00), .opb_00(opb_00), + .opa_inf(opa_inf), .opb_inf(opb_inf), + .opa_dn(opa_dn), .opb_dn(opb_dn) + ); + +//////////////////////////////////////////////////////////////////////// +// +// Pre-Normalize block +// - Adjusts the numbers to equal exponents and sorts them +// - determine result sign +// - determine actual operation to perform (add or sub) +// + +wire nan_sign_d, result_zero_sign_d; +reg sign_fasu_r; +wire [7:0] exp_mul; +wire sign_mul; +reg sign_mul_r; +wire [23:0] fracta_mul, fractb_mul; +wire inf_mul; +reg inf_mul_r; +wire [1:0] exp_ovf; +reg [1:0] exp_ovf_r; +wire sign_exe; +reg sign_exe_r; +wire [2:0] underflow_fmul_d; + + +pre_norm u1(.clk(clk), // System Clock + .rmode(rmode_r2), // Roundin Mode + .add(!fpu_op_r1[0]), // Add/Sub Input + .opa(opa_r), .opb(opb_r), // Registered OP Inputs + .opa_nan(opa_nan), // OpA is a NAN indicator + .opb_nan(opb_nan), // OpB is a NAN indicator + .fracta_out(fracta), // Equalized and sorted fraction + .fractb_out(fractb), // outputs (Registered) + .exp_dn_out(exp_fasu), // Selected exponent output (registered); + .sign(sign_fasu), // Encoded output Sign (registered) + .nan_sign(nan_sign_d), // Output Sign for NANs (registered) + .result_zero_sign(result_zero_sign_d), // Output Sign for zero result (registered) + .fasu_op(fasu_op) // Actual fasu operation output (registered) + ); + +always @(posedge clk) + sign_fasu_r <= #1 sign_fasu; + +pre_norm_fmul u2( + .clk(clk), + .fpu_op(fpu_op_r1), + .opa(opa_r), .opb(opb_r), + .fracta(fracta_mul), + .fractb(fractb_mul), + .exp_out(exp_mul), // FMUL exponent output (registered) + .sign(sign_mul), // FMUL sign output (registered) + .sign_exe(sign_exe), // FMUL exception sign output (registered) + .inf(inf_mul), // FMUL inf output (registered) + .exp_ovf(exp_ovf), // FMUL exponnent overflow output (registered) + .underflow(underflow_fmul_d) + ); + + +always @(posedge clk) + sign_mul_r <= #1 sign_mul; + +always @(posedge clk) + sign_exe_r <= #1 sign_exe; + +always @(posedge clk) + inf_mul_r <= #1 inf_mul; + +always @(posedge clk) + exp_ovf_r <= #1 exp_ovf; + + +//////////////////////////////////////////////////////////////////////// +// +// Add/Sub +// + +add_sub27 u3( + .add(fasu_op), // Add/Sub + .opa(fracta), // Fraction A input + .opb(fractb), // Fraction B Input + .sum(fract_out_d), // SUM output + .co(co_d) ); // Carry Output + +always @(posedge clk) + fract_out_q <= #1 {co_d, fract_out_d}; + +//////////////////////////////////////////////////////////////////////// +// +// Mul +// +wire [47:0] prod; + +mul_r2 u5(.clk(clk), .opa(fracta_mul), .opb(fractb_mul), .prod(prod)); + +//////////////////////////////////////////////////////////////////////// +// +// Divide +// +wire [49:0] quo; +wire [49:0] fdiv_opa; +wire [49:0] remainder; +wire remainder_00; +reg [4:0] div_opa_ldz_d, div_opa_ldz_r1, div_opa_ldz_r2; + +always @(fracta_mul) + casex(fracta_mul[22:0]) + 23'b1??????????????????????: div_opa_ldz_d = 1; + 23'b01?????????????????????: div_opa_ldz_d = 2; + 23'b001????????????????????: div_opa_ldz_d = 3; + 23'b0001???????????????????: div_opa_ldz_d = 4; + 23'b00001??????????????????: div_opa_ldz_d = 5; + 23'b000001?????????????????: div_opa_ldz_d = 6; + 23'b0000001????????????????: div_opa_ldz_d = 7; + 23'b00000001???????????????: div_opa_ldz_d = 8; + 23'b000000001??????????????: div_opa_ldz_d = 9; + 23'b0000000001?????????????: div_opa_ldz_d = 10; + 23'b00000000001????????????: div_opa_ldz_d = 11; + 23'b000000000001???????????: div_opa_ldz_d = 12; + 23'b0000000000001??????????: div_opa_ldz_d = 13; + 23'b00000000000001?????????: div_opa_ldz_d = 14; + 23'b000000000000001????????: div_opa_ldz_d = 15; + 23'b0000000000000001???????: div_opa_ldz_d = 16; + 23'b00000000000000001??????: div_opa_ldz_d = 17; + 23'b000000000000000001?????: div_opa_ldz_d = 18; + 23'b0000000000000000001????: div_opa_ldz_d = 19; + 23'b00000000000000000001???: div_opa_ldz_d = 20; + 23'b000000000000000000001??: div_opa_ldz_d = 21; + 23'b0000000000000000000001?: div_opa_ldz_d = 22; + 23'b0000000000000000000000?: div_opa_ldz_d = 23; + endcase + +assign fdiv_opa = !(|opa_r[30:23]) ? {(fracta_mul<f2i_emax)) | (opas & (exp_inf2i_emax)) | (opas & (exp_in8'h16); + +assign f2i_shft = exp_in-8'h7d; + +// Select shifting direction +assign left_right = op_div ? lr_div : op_mul ? lr_mul : 1; + +assign lr_div = (op_dn & !exp_ovf[1] & exp_ovf[0]) ? 1 : + (op_dn & exp_ovf[1]) ? 0 : + (op_dn & div_shft1_co) ? 0 : + (op_dn & exp_out_00) ? 1 : + (!op_dn & exp_out_00 & !exp_ovf[1]) ? 1 : + exp_ovf[1] ? 0 : + 1; +assign lr_mul = (shft_co | (!exp_ovf[1] & exp_in_00) | + (!exp_ovf[1] & !exp_in_00 & (exp_out1_co | exp_out_00) )) ? 1 : + ( exp_ovf[1] | exp_in_00 ) ? 0 : + 1; + +// Select Left and Right shift value +assign fasu_shift = (dn | exp_out_00) ? (exp_in_00 ? 8'h2 : exp_in_pl1[7:0]) : {2'h0, fi_ldz}; +assign shift_right = op_div ? shftr_div : shftr_mul; + +assign conv_shft = op_f2i ? f2i_shft : {2'h0, fi_ldz}; + +assign shift_left = op_div ? shftl_div : op_mul ? shftl_mul : (op_f2i | op_i2f) ? conv_shft : fasu_shift; + +assign shftl_mul = (shft_co | + (!exp_ovf[1] & exp_in_00) | + (!exp_ovf[1] & !exp_in_00 & (exp_out1_co | exp_out_00))) ? exp_in_pl1[7:0] : {2'h0, fi_ldz}; + +assign shftl_div = ( op_dn & exp_out_00 & !(!exp_ovf[1] & exp_ovf[0])) ? div_shft1[7:0] : + (!op_dn & exp_out_00 & !exp_ovf[1]) ? exp_in[7:0] : + {2'h0, fi_ldz}; +assign shftr_div = (op_dn & exp_ovf[1]) ? div_shft3 : + (op_dn & div_shft1_co) ? div_shft4 : + div_shft2; +// Do the actual shifting +assign fract_in_shftr = (|shift_right[7:6]) ? 0 : fract_in>>shift_right[5:0]; +assign fract_in_shftl = (|shift_left[7:6] | (f2i_zero & op_f2i)) ? 0 : fract_in<f2i_emax) ? 0 : opas) : + ((exp_inf2i_emax) ? 1 : opas); + +assign exp_i2f = fract_in_00 ? (opas ? 8'h9e : 0) : (8'h9e-fi_ldz); +assign exp_f2i_1 = {{8{fract_in[47]}}, fract_in }<9'hfe) )) ? div_exp2 : + (opa_dn | (exp_in_00 & !exp_ovf[1]) ) ? 0 : + exp_out1_mi1; + +assign div_inf = opb_dn & !opa_dn & (div_exp1[7:0] < 8'h7f); + +// --------------------------------------------------------------------- +// Round + +// Extract rounding (GRS) bits +assign grs_sel_div = op_div & (exp_ovf[1] | div_dn | exp_out1_co | exp_out_00); + +assign g = grs_sel_div ? fract_out[0] : fract_out[0]; +assign r = grs_sel_div ? (fract_trunc[24] & !div_nr) : fract_trunc[24]; +assign s = grs_sel_div ? |fract_trunc[24:0] : (|fract_trunc[23:0] | (fract_trunc[24] & op_div)); + +// Round to nearest even +assign round = (g & r) | (r & s) ; +assign {exp_rnd_adj0, fract_out_rnd0} = round ? fract_out_pl1 : {1'b0, fract_out}; +assign exp_out_rnd0 = exp_rnd_adj0 ? exp_out_pl1 : exp_out; +assign ovf0 = exp_out_final_ff & !rmode_01 & !op_f2i; + +// round to zero +assign fract_out_rnd1 = (exp_out_ff & !op_div & !dn & !op_f2i) ? 23'h7fffff : fract_out; +assign exp_fix_div = (fi_ldz>22) ? exp_fix_diva : exp_fix_divb; +assign exp_out_rnd1 = (g & r & s & exp_in_ff) ? (op_div ? exp_fix_div : exp_next_mi[7:0]) : + (exp_out_ff & !op_f2i) ? exp_in : exp_out; +assign ovf1 = exp_out_ff & !dn; + +// round to +inf (UP) and -inf (DOWN) +assign r_sign = sign; + +assign round2a = !exp_out_fe | !fract_out_7fffff | (exp_out_fe & fract_out_7fffff); +assign round2_fasu = ((r | s) & !r_sign) & (!exp_out[7] | (exp_out[7] & round2a)); + +assign round2_fmul = !r_sign & + ( + (exp_ovf[1] & !fract_in_00 & + ( ((!exp_out1_co | op_dn) & (r | s | (!rem_00 & op_div) )) | fract_out_00 | (!op_dn & !op_div)) + ) | + ( + (r | s | (!rem_00 & op_div)) & ( + (!exp_ovf[1] & (exp_in_80 | !exp_ovf[0])) | op_div | + ( exp_ovf[1] & !exp_ovf[0] & exp_out1_co) + ) + ) + ); + +assign round2_f2i = rmode_10 & (( |fract_in[23:0] & !opas & (exp_in<8'h80 )) | (|fract_trunc)); +assign round2 = (op_mul | op_div) ? round2_fmul : op_f2i ? round2_f2i : round2_fasu; + +assign {exp_rnd_adj2a, fract_out_rnd2a} = round2 ? fract_out_pl1 : {1'b0, fract_out}; +assign exp_out_rnd2a = exp_rnd_adj2a ? ((exp_ovf[1] & op_mul) ? exp_out_mi1 : exp_out_pl1) : exp_out; + +assign fract_out_rnd2 = (r_sign & exp_out_ff & !op_div & !dn & !op_f2i) ? 23'h7fffff : fract_out_rnd2a; +assign exp_out_rnd2 = (r_sign & exp_out_ff & !op_f2i) ? 8'hfe : exp_out_rnd2a; + + +// Choose rounding mode +always @(rmode or exp_out_rnd0 or exp_out_rnd1 or exp_out_rnd2) + case(rmode) // synopsys full_case parallel_case + 0: exp_out_rnd = exp_out_rnd0; + 1: exp_out_rnd = exp_out_rnd1; + 2,3: exp_out_rnd = exp_out_rnd2; + endcase + +always @(rmode or fract_out_rnd0 or fract_out_rnd1 or fract_out_rnd2) + case(rmode) // synopsys full_case parallel_case + 0: fract_out_rnd = fract_out_rnd0; + 1: fract_out_rnd = fract_out_rnd1; + 2,3: fract_out_rnd = fract_out_rnd2; + endcase + +// --------------------------------------------------------------------- +// Final Output Mux +// Fix Output for denormalized and special numbers +wire max_num, inf_out; + +assign max_num = ( !rmode_00 & (op_mul | op_div ) & ( + ( exp_ovf[1] & exp_ovf[0]) | + (!exp_ovf[1] & !exp_ovf[0] & exp_in_ff & (fi_ldz_2<24) & (exp_out!=8'hfe) ) + ) + ) | + + ( op_div & ( + ( rmode_01 & ( div_inf | + (exp_out_ff & !exp_ovf[1] ) | + (exp_ovf[1] & exp_ovf[0] ) + ) + ) | + + ( rmode[1] & !exp_ovf[1] & ( + ( exp_ovf[0] & exp_in_ff & r_sign & fract_in[47] + ) | + + ( r_sign & ( + (fract_in[47] & div_inf) | + (exp_in[7] & !exp_out_rnd[7] & !exp_in_80 & exp_out!=8'h7f ) | + (exp_in[7] & exp_out_rnd[7] & r_sign & exp_out_ff & op_dn & + div_exp1>9'h0fe ) + ) + ) | + + ( exp_in_00 & r_sign & ( + div_inf | + (r_sign & exp_out_ff & fi_ldz_2<24) + ) + ) + ) + ) + ) + ); + + +assign inf_out = (rmode[1] & (op_mul | op_div) & !r_sign & ( (exp_in_ff & !op_div) | + (exp_ovf[1] & exp_ovf[0] & (exp_in_00 | exp_in[7]) ) + ) + ) | (div_inf & op_div & ( + rmode_00 | + (rmode[1] & !exp_in_ff & !exp_ovf[1] & !exp_ovf[0] & !r_sign ) | + (rmode[1] & !exp_ovf[1] & exp_ovf[0] & exp_in_00 & !r_sign) + ) + ) | (op_div & rmode[1] & exp_in_ff & op_dn & !r_sign & (fi_ldz_2 < 24) & (exp_out_rnd!=8'hfe) ); + +assign fract_out_final = (inf_out | ovf0 | output_zero ) ? 23'h0 : + (max_num | (f2i_max & op_f2i) ) ? 23'h7fffff : + fract_out_rnd; + +assign exp_out_final = ((op_div & exp_ovf[1] & !exp_ovf[0]) | output_zero ) ? 8'h00 : + ((op_div & exp_ovf[1] & exp_ovf[0] & rmode_00) | inf_out | (f2i_max & op_f2i) ) ? 8'hff : + max_num ? 8'hfe : + exp_out_rnd; + + +// --------------------------------------------------------------------- +// Pack Result + +assign out = {exp_out_final, fract_out_final}; + +// --------------------------------------------------------------------- +// Exceptions +wire underflow_fmul; +wire overflow_fdiv; +wire undeflow_div; + +wire z = shft_co | ( exp_ovf[1] | exp_in_00) | + (!exp_ovf[1] & !exp_in_00 & (exp_out1_co | exp_out_00)); + +assign underflow_fmul = ( (|fract_trunc) & z & !exp_in_ff ) | + (fract_out_00 & !fract_in_00 & exp_ovf[1]); + +assign undeflow_div = !(exp_ovf[1] & exp_ovf[0] & rmode_00) & !inf_out & !max_num & exp_out_final!=8'hff & ( + + ((|fract_trunc) & !opb_dn & ( + ( op_dn & !exp_ovf[1] & exp_ovf[0]) | + ( op_dn & exp_ovf[1]) | + ( op_dn & div_shft1_co) | + exp_out_00 | + exp_ovf[1] + ) + + ) | + + ( exp_ovf[1] & !exp_ovf[0] & ( + ( op_dn & exp_in>8'h16 & fi_ldz<23) | + ( op_dn & exp_in<23 & fi_ldz<23 & !rem_00) | + ( !op_dn & (exp_in[7]==exp_div[7]) & !rem_00) | + ( !op_dn & exp_in_00 & (exp_div[7:1]==7'h7f) ) | + ( !op_dn & exp_in<8'h7f & exp_in>8'h20 ) + ) + ) | + + (!exp_ovf[1] & !exp_ovf[0] & ( + ( op_dn & fi_ldz<23 & exp_out_00) | + ( exp_in_00 & !rem_00) | + ( !op_dn & ldz_all<23 & exp_in==1 & exp_out_00 & !rem_00) + ) + ) + + ); + +assign underflow = op_div ? undeflow_div : op_mul ? underflow_fmul : (!fract_in[47] & exp_out1_co) & !dn; + +assign overflow_fdiv = inf_out | + (!rmode_00 & max_num) | + (exp_in[7] & op_dn & exp_out_ff) | + (exp_ovf[0] & (exp_ovf[1] | exp_out_ff) ); + +assign overflow = op_div ? overflow_fdiv : (ovf0 | ovf1); + +wire f2i_ine; + +assign f2i_ine = (f2i_zero & !fract_in_00 & !opas) | + (|fract_trunc) | + (f2i_zero & (exp_in<8'h80) & opas & !fract_in_00) | + (f2i_max & rmode_11 & (exp_in<8'h80)); + + + +assign ine = op_f2i ? f2i_ine : + op_i2f ? (|fract_trunc) : + ((r & !dn) | (s & !dn) | max_num | (op_div & !rem_00)); + +// --------------------------------------------------------------------- +// Debugging Stuff + +// synopsys translate_off + +wire [26:0] fracta_del, fractb_del; +wire [2:0] grs_del; +wire dn_del; +wire [7:0] exp_in_del; +wire [7:0] exp_out_del; +wire [22:0] fract_out_del; +wire [47:0] fract_in_del; +wire overflow_del; +wire [1:0] exp_ovf_del; +wire [22:0] fract_out_x_del, fract_out_rnd2a_del; +wire [24:0] trunc_xx_del; +wire exp_rnd_adj2a_del; +wire [22:0] fract_dn_del; +wire [4:0] div_opa_ldz_del; +wire [23:0] fracta_div_del; +wire [23:0] fractb_div_del; +wire div_inf_del; +wire [7:0] fi_ldz_2_del; +wire inf_out_del, max_out_del; +wire [5:0] fi_ldz_del; +wire rx_del; +wire ez_del; +wire lr; +wire [7:0] shr, shl, exp_div_del; + +delay2 #26 ud000(clk, test.u0.fracta, fracta_del); +delay2 #26 ud001(clk, test.u0.fractb, fractb_del); +delay1 #2 ud002(clk, {g,r,s}, grs_del); +delay1 #0 ud004(clk, dn, dn_del); +delay1 #7 ud005(clk, exp_in, exp_in_del); +delay1 #7 ud007(clk, exp_out_rnd, exp_out_del); +delay1 #47 ud009(clk, fract_in, fract_in_del); +delay1 #0 ud010(clk, overflow, overflow_del); +delay1 #1 ud011(clk, exp_ovf, exp_ovf_del); +delay1 #22 ud014(clk, fract_out, fract_out_x_del); +delay1 #24 ud015(clk, fract_trunc, trunc_xx_del); +delay1 #0 ud017(clk, exp_rnd_adj2a, exp_rnd_adj2a_del); +delay1 #4 ud019(clk, div_opa_ldz, div_opa_ldz_del); +delay3 #23 ud020(clk, test.u0.fdiv_opa[49:26], fracta_div_del); +delay3 #23 ud021(clk, test.u0.fractb_mul, fractb_div_del); +delay1 #0 ud023(clk, div_inf, div_inf_del); +delay1 #7 ud024(clk, fi_ldz_2, fi_ldz_2_del); +delay1 #0 ud025(clk, inf_out, inf_out_del); +delay1 #0 ud026(clk, max_num, max_num_del); +delay1 #5 ud027(clk, fi_ldz, fi_ldz_del); +delay1 #0 ud028(clk, rem_00, rx_del); + +delay1 #0 ud029(clk, left_right, lr); +delay1 #7 ud030(clk, shift_right, shr); +delay1 #7 ud031(clk, shift_left, shl); +delay1 #22 ud032(clk, fract_out_rnd2a, fract_out_rnd2a_del); + +delay1 #7 ud033(clk, exp_div, exp_div_del); + +always @(test.error_event) + begin + + $display("\n----------------------------------------------"); + + $display("ERROR: GRS: %b exp_ovf: %b dn: %h exp_in: %h exp_out: %h, exp_rnd_adj2a: %b", + grs_del, exp_ovf_del, dn_del, exp_in_del, exp_out_del, exp_rnd_adj2a_del); + + $display(" div_opa: %b, div_opb: %b, rem_00: %b, exp_div: %h", + fracta_div_del, fractb_div_del, rx_del, exp_div_del); + + $display(" lr: %b, shl: %h, shr: %h", + lr, shl, shr); + + + $display(" overflow: %b, fract_in=%b fa:%h fb:%h", + overflow_del, fract_in_del, fracta_del, fractb_del); + + $display(" div_opa_ldz: %h, div_inf: %b, inf_out: %b, max_num: %b, fi_ldz: %h, fi_ldz_2: %h", + div_opa_ldz_del, div_inf_del, inf_out_del, max_num_del, fi_ldz_del, fi_ldz_2_del); + + $display(" fract_out_x: %b, fract_out_rnd2a_del: %h, fract_trunc: %b\n", + fract_out_x_del, fract_out_rnd2a_del, trunc_xx_del); + end + + +// synopsys translate_on + +endmodule + +// synopsys translate_off + +module delay1(clk, in, out); +parameter N = 1; +input [N:0] in; +output [N:0] out; +input clk; + +reg [N:0] out; + +always @(posedge clk) + out <= #1 in; + +endmodule + + +module delay2(clk, in, out); +parameter N = 1; +input [N:0] in; +output [N:0] out; +input clk; + +reg [N:0] out, r1; + +always @(posedge clk) + r1 <= #1 in; + +always @(posedge clk) + out <= #1 r1; + +endmodule + +module delay3(clk, in, out); +parameter N = 1; +input [N:0] in; +output [N:0] out; +input clk; + +reg [N:0] out, r1, r2; + +always @(posedge clk) + r1 <= #1 in; + +always @(posedge clk) + r2 <= #1 r1; + +always @(posedge clk) + out <= #1 r2; + +endmodule + +// synopsys translate_on \ No newline at end of file diff --git a/tests/iwls2005/fpu/pre_norm.v b/tests/iwls2005/fpu/pre_norm.v new file mode 100644 index 00000000..c54c71fa --- /dev/null +++ b/tests/iwls2005/fpu/pre_norm.v @@ -0,0 +1,270 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Pre Normalize //// +//// Pre Normalization Unit for Add/Sub Operations //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +`timescale 1ns / 100ps + + +module pre_norm(clk, rmode, add, opa, opb, opa_nan, opb_nan, fracta_out, + fractb_out, exp_dn_out, sign, nan_sign, result_zero_sign, + fasu_op); +input clk; +input [1:0] rmode; +input add; +input [31:0] opa, opb; +input opa_nan, opb_nan; +output [26:0] fracta_out, fractb_out; +output [7:0] exp_dn_out; +output sign; +output nan_sign, result_zero_sign; +output fasu_op; // Operation Output + +//////////////////////////////////////////////////////////////////////// +// +// Local Wires and registers +// + +wire signa, signb; // alias to opX sign +wire [7:0] expa, expb; // alias to opX exponent +wire [22:0] fracta, fractb; // alias to opX fraction +wire expa_lt_expb; // expa is larger than expb indicator +wire fractb_lt_fracta; // fractb is larger than fracta indicator +reg [7:0] exp_dn_out; // de normalized exponent output +wire [7:0] exp_small, exp_large; +wire [7:0] exp_diff; // Numeric difference of the two exponents +wire [22:0] adj_op; // Fraction adjustment: input +wire [26:0] adj_op_tmp; +wire [26:0] adj_op_out; // Fraction adjustment: output +wire [26:0] fracta_n, fractb_n; // Fraction selection after normalizing +wire [26:0] fracta_s, fractb_s; // Fraction Sorting out +reg [26:0] fracta_out, fractb_out; // Fraction Output +reg sign, sign_d; // Sign Output +reg add_d; // operation (add/sub) +reg fasu_op; // operation (add/sub) register +wire expa_dn, expb_dn; +reg sticky; +reg result_zero_sign; +reg add_r, signa_r, signb_r; +wire [4:0] exp_diff_sft; +wire exp_lt_27; +wire op_dn; +wire [26:0] adj_op_out_sft; +reg fracta_lt_fractb, fracta_eq_fractb; +wire nan_sign1; +reg nan_sign; + +//////////////////////////////////////////////////////////////////////// +// +// Aliases +// + +assign signa = opa[31]; +assign signb = opb[31]; +assign expa = opa[30:23]; +assign expb = opb[30:23]; +assign fracta = opa[22:0]; +assign fractb = opb[22:0]; + +//////////////////////////////////////////////////////////////////////// +// +// Pre-Normalize exponents (and fractions) +// + +assign expa_lt_expb = expa > expb; // expa is larger than expb + +// --------------------------------------------------------------------- +// Normalize + +assign expa_dn = !(|expa); // opa denormalized +assign expb_dn = !(|expb); // opb denormalized + +// --------------------------------------------------------------------- +// Calculate the difference between the smaller and larger exponent + +wire [7:0] exp_diff1, exp_diff1a, exp_diff2; + +assign exp_small = expa_lt_expb ? expb : expa; +assign exp_large = expa_lt_expb ? expa : expb; +assign exp_diff1 = exp_large - exp_small; +assign exp_diff1a = exp_diff1-1; +assign exp_diff2 = (expa_dn | expb_dn) ? exp_diff1a : exp_diff1; +assign exp_diff = (expa_dn & expb_dn) ? 8'h0 : exp_diff2; + +always @(posedge clk) // If numbers are equal we should return zero + exp_dn_out <= #1 (!add_d & expa==expb & fracta==fractb) ? 8'h0 : exp_large; + +// --------------------------------------------------------------------- +// Adjust the smaller fraction + + +assign op_dn = expa_lt_expb ? expb_dn : expa_dn; +assign adj_op = expa_lt_expb ? fractb : fracta; +assign adj_op_tmp = { ~op_dn, adj_op, 3'b0 }; // recover hidden bit (op_dn) + +// adj_op_out is 27 bits wide, so can only be shifted 27 bits to the right +assign exp_lt_27 = exp_diff > 8'd27; +assign exp_diff_sft = exp_lt_27 ? 5'd27 : exp_diff[4:0]; +assign adj_op_out_sft = adj_op_tmp >> exp_diff_sft; +assign adj_op_out = {adj_op_out_sft[26:1], adj_op_out_sft[0] | sticky }; + +// --------------------------------------------------------------------- +// Get truncated portion (sticky bit) + +always @(exp_diff_sft or adj_op_tmp) + case(exp_diff_sft) // synopsys full_case parallel_case + 00: sticky = 1'h0; + 01: sticky = adj_op_tmp[0]; + 02: sticky = |adj_op_tmp[01:0]; + 03: sticky = |adj_op_tmp[02:0]; + 04: sticky = |adj_op_tmp[03:0]; + 05: sticky = |adj_op_tmp[04:0]; + 06: sticky = |adj_op_tmp[05:0]; + 07: sticky = |adj_op_tmp[06:0]; + 08: sticky = |adj_op_tmp[07:0]; + 09: sticky = |adj_op_tmp[08:0]; + 10: sticky = |adj_op_tmp[09:0]; + 11: sticky = |adj_op_tmp[10:0]; + 12: sticky = |adj_op_tmp[11:0]; + 13: sticky = |adj_op_tmp[12:0]; + 14: sticky = |adj_op_tmp[13:0]; + 15: sticky = |adj_op_tmp[14:0]; + 16: sticky = |adj_op_tmp[15:0]; + 17: sticky = |adj_op_tmp[16:0]; + 18: sticky = |adj_op_tmp[17:0]; + 19: sticky = |adj_op_tmp[18:0]; + 20: sticky = |adj_op_tmp[19:0]; + 21: sticky = |adj_op_tmp[20:0]; + 22: sticky = |adj_op_tmp[21:0]; + 23: sticky = |adj_op_tmp[22:0]; + 24: sticky = |adj_op_tmp[23:0]; + 25: sticky = |adj_op_tmp[24:0]; + 26: sticky = |adj_op_tmp[25:0]; + 27: sticky = |adj_op_tmp[26:0]; + endcase + +// --------------------------------------------------------------------- +// Select operands for add/sub (recover hidden bit) + +assign fracta_n = expa_lt_expb ? {~expa_dn, fracta, 3'b0} : adj_op_out; +assign fractb_n = expa_lt_expb ? adj_op_out : {~expb_dn, fractb, 3'b0}; + +// --------------------------------------------------------------------- +// Sort operands (for sub only) + +assign fractb_lt_fracta = fractb_n > fracta_n; // fractb is larger than fracta +assign fracta_s = fractb_lt_fracta ? fractb_n : fracta_n; +assign fractb_s = fractb_lt_fracta ? fracta_n : fractb_n; + +always @(posedge clk) + fracta_out <= #1 fracta_s; + +always @(posedge clk) + fractb_out <= #1 fractb_s; + +// --------------------------------------------------------------------- +// Determine sign for the output + +// sign: 0=Positive Number; 1=Negative Number +always @(signa or signb or add or fractb_lt_fracta) + case({signa, signb, add}) // synopsys full_case parallel_case + + // Add + 3'b0_0_1: sign_d = 0; + 3'b0_1_1: sign_d = fractb_lt_fracta; + 3'b1_0_1: sign_d = !fractb_lt_fracta; + 3'b1_1_1: sign_d = 1; + + // Sub + 3'b0_0_0: sign_d = fractb_lt_fracta; + 3'b0_1_0: sign_d = 0; + 3'b1_0_0: sign_d = 1; + 3'b1_1_0: sign_d = !fractb_lt_fracta; + endcase + +always @(posedge clk) + sign <= #1 sign_d; + +// Fix sign for ZERO result +always @(posedge clk) + signa_r <= #1 signa; + +always @(posedge clk) + signb_r <= #1 signb; + +always @(posedge clk) + add_r <= #1 add; + +always @(posedge clk) + result_zero_sign <= #1 ( add_r & signa_r & signb_r) | + (!add_r & signa_r & !signb_r) | + ( add_r & (signa_r | signb_r) & (rmode==3)) | + (!add_r & (signa_r == signb_r) & (rmode==3)); + +// Fix sign for NAN result +always @(posedge clk) + fracta_lt_fractb <= #1 fracta < fractb; + +always @(posedge clk) + fracta_eq_fractb <= #1 fracta == fractb; + +assign nan_sign1 = fracta_eq_fractb ? (signa_r & signb_r) : fracta_lt_fractb ? signb_r : signa_r; + +always @(posedge clk) + nan_sign <= #1 (opa_nan & opb_nan) ? nan_sign1 : opb_nan ? signb_r : signa_r; + +//////////////////////////////////////////////////////////////////////// +// +// Decode Add/Sub operation +// + +// add: 1=Add; 0=Subtract +always @(signa or signb or add) + case({signa, signb, add}) // synopsys full_case parallel_case + + // Add + 3'b0_0_1: add_d = 1; + 3'b0_1_1: add_d = 0; + 3'b1_0_1: add_d = 0; + 3'b1_1_1: add_d = 1; + + // Sub + 3'b0_0_0: add_d = 0; + 3'b0_1_0: add_d = 1; + 3'b1_0_0: add_d = 1; + 3'b1_1_0: add_d = 0; + endcase + +always @(posedge clk) + fasu_op <= #1 add_d; + +endmodule diff --git a/tests/iwls2005/fpu/pre_norm_fmul.v b/tests/iwls2005/fpu/pre_norm_fmul.v new file mode 100644 index 00000000..26ddfeb7 --- /dev/null +++ b/tests/iwls2005/fpu/pre_norm_fmul.v @@ -0,0 +1,150 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Pre Normalize //// +//// Floating Point Pre Normalization Unit for FMUL //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +`timescale 1ns / 100ps + +module pre_norm_fmul(clk, fpu_op, opa, opb, fracta, fractb, exp_out, sign, + sign_exe, inf, exp_ovf, underflow); +input clk; +input [2:0] fpu_op; +input [31:0] opa, opb; +output [23:0] fracta, fractb; +output [7:0] exp_out; +output sign, sign_exe; +output inf; +output [1:0] exp_ovf; +output [2:0] underflow; + +//////////////////////////////////////////////////////////////////////// +// +// Local Wires and registers +// + +reg [7:0] exp_out; +wire signa, signb; +reg sign, sign_d; +reg sign_exe; +reg inf; +wire [1:0] exp_ovf_d; +reg [1:0] exp_ovf; +wire [7:0] expa, expb; +wire [7:0] exp_tmp1, exp_tmp2; +wire co1, co2; +wire expa_dn, expb_dn; +wire [7:0] exp_out_a; +wire opa_00, opb_00, fracta_00, fractb_00; +wire [7:0] exp_tmp3, exp_tmp4, exp_tmp5; +wire [2:0] underflow_d; +reg [2:0] underflow; +wire op_div = (fpu_op == 3'b011); +wire [7:0] exp_out_mul, exp_out_div; + +//////////////////////////////////////////////////////////////////////// +// +// Aliases +// + +assign signa = opa[31]; +assign signb = opb[31]; +assign expa = opa[30:23]; +assign expb = opb[30:23]; + +//////////////////////////////////////////////////////////////////////// +// +// Calculate Exponenet +// + +assign expa_dn = !(|expa); +assign expb_dn = !(|expb); +assign opa_00 = !(|opa[30:0]); +assign opb_00 = !(|opb[30:0]); +assign fracta_00 = !(|opa[22:0]); +assign fractb_00 = !(|opb[22:0]); + +assign fracta = {!expa_dn,opa[22:0]}; // Recover hidden bit +assign fractb = {!expb_dn,opb[22:0]}; // Recover hidden bit + +assign {co1,exp_tmp1} = op_div ? (expa - expb) : (expa + expb); +assign {co2,exp_tmp2} = op_div ? ({co1,exp_tmp1} + 8'h7f) : ({co1,exp_tmp1} - 8'h7f); + +assign exp_tmp3 = exp_tmp2 + 1; +assign exp_tmp4 = 8'h7f - exp_tmp1; +assign exp_tmp5 = op_div ? (exp_tmp4+1) : (exp_tmp4-1); + + +always@(posedge clk) + exp_out <= #1 op_div ? exp_out_div : exp_out_mul; + +assign exp_out_div = (expa_dn | expb_dn) ? (co2 ? exp_tmp5 : exp_tmp3 ) : co2 ? exp_tmp4 : exp_tmp2; +assign exp_out_mul = exp_ovf_d[1] ? exp_out_a : (expa_dn | expb_dn) ? exp_tmp3 : exp_tmp2; +assign exp_out_a = (expa_dn | expb_dn) ? exp_tmp5 : exp_tmp4; +assign exp_ovf_d[0] = op_div ? (expa[7] & !expb[7]) : (co2 & expa[7] & expb[7]); +assign exp_ovf_d[1] = op_div ? co2 : ((!expa[7] & !expb[7] & exp_tmp2[7]) | co2); + +always @(posedge clk) + exp_ovf <= #1 exp_ovf_d; + +assign underflow_d[0] = (exp_tmp1 < 8'h7f) & !co1 & !(opa_00 | opb_00 | expa_dn | expb_dn); +assign underflow_d[1] = ((expa[7] | expb[7]) & !opa_00 & !opb_00) | + (expa_dn & !fracta_00) | (expb_dn & !fractb_00); +assign underflow_d[2] = !opa_00 & !opb_00 & (exp_tmp1 == 8'h7f); + +always @(posedge clk) + underflow <= #1 underflow_d; + +always @(posedge clk) + inf <= #1 op_div ? (expb_dn & !expa[7]) : ({co1,exp_tmp1} > 9'h17e) ; + + +//////////////////////////////////////////////////////////////////////// +// +// Determine sign for the output +// + +// sign: 0=Posetive Number; 1=Negative Number +always @(signa or signb) + case({signa, signb}) // synopsys full_case parallel_case + 2'b0_0: sign_d = 0; + 2'b0_1: sign_d = 1; + 2'b1_0: sign_d = 1; + 2'b1_1: sign_d = 0; + endcase + +always @(posedge clk) + sign <= #1 sign_d; + +always @(posedge clk) + sign_exe <= #1 signa & signb; + +endmodule \ No newline at end of file diff --git a/tests/iwls2005/fpu/primitives.v b/tests/iwls2005/fpu/primitives.v new file mode 100644 index 00000000..2e7f050e --- /dev/null +++ b/tests/iwls2005/fpu/primitives.v @@ -0,0 +1,103 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Primitives //// +//// FPU Primitives //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + + +`timescale 1ns / 100ps + + +//////////////////////////////////////////////////////////////////////// +// +// Add/Sub +// + +module add_sub27(add, opa, opb, sum, co); +input add; +input [26:0] opa, opb; +output [26:0] sum; +output co; + + + +assign {co, sum} = add ? (opa + opb) : (opa - opb); + +endmodule + +//////////////////////////////////////////////////////////////////////// +// +// Multiply +// + +module mul_r2(clk, opa, opb, prod); +input clk; +input [23:0] opa, opb; +output [47:0] prod; + +reg [47:0] prod1, prod; + +always @(posedge clk) + prod1 <= #1 opa * opb; + +always @(posedge clk) + prod <= #1 prod1; + +endmodule + +//////////////////////////////////////////////////////////////////////// +// +// Divide +// + +module div_r2(clk, opa, opb, quo, rem); +input clk; +input [49:0] opa; +input [23:0] opb; +output [49:0] quo, rem; + +reg [49:0] quo, rem, quo1, remainder; + +always @(posedge clk) + quo1 <= #1 opa / opb; + +always @(posedge clk) + quo <= #1 quo1; + +always @(posedge clk) + remainder <= #1 opa % opb; + +always @(posedge clk) + rem <= #1 remainder; + +endmodule + + diff --git a/tests/iwls2005/i2c/i2c_master_bit_ctrl.v b/tests/iwls2005/i2c/i2c_master_bit_ctrl.v new file mode 100644 index 00000000..17b2c8b1 --- /dev/null +++ b/tests/iwls2005/i2c/i2c_master_bit_ctrl.v @@ -0,0 +1,535 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant I2C Master bit-controller //// +//// //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/i2c/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: i2c_master_bit_ctrl.v,v 1.11 2004/05/07 11:02:26 rherveille Exp $ +// +// $Date: 2004/05/07 11:02:26 $ +// $Revision: 1.11 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: i2c_master_bit_ctrl.v,v $ +// Revision 1.11 2004/05/07 11:02:26 rherveille +// Fixed a bug where the core would signal an arbitration lost (AL bit set), when another master controls the bus and the other master generates a STOP bit. +// +// Revision 1.10 2003/08/09 07:01:33 rherveille +// Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. +// Fixed a potential bug in the byte controller's host-acknowledge generation. +// +// Revision 1.9 2003/03/10 14:26:37 rherveille +// Fixed cmd_ack generation item (no bug). +// +// Revision 1.8 2003/02/05 00:06:10 rherveille +// Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles. +// +// Revision 1.7 2002/12/26 16:05:12 rherveille +// Small code simplifications +// +// Revision 1.6 2002/12/26 15:02:32 rherveille +// Core is now a Multimaster I2C controller +// +// Revision 1.5 2002/11/30 22:24:40 rherveille +// Cleaned up code +// +// Revision 1.4 2002/10/30 18:10:07 rherveille +// Fixed some reported minor start/stop generation timing issuess. +// +// Revision 1.3 2002/06/15 07:37:03 rherveille +// Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment. +// +// Revision 1.2 2001/11/05 11:59:25 rherveille +// Fixed wb_ack_o generation bug. +// Fixed bug in the byte_controller statemachine. +// Added headers. +// + +// +///////////////////////////////////// +// Bit controller section +///////////////////////////////////// +// +// Translate simple commands into SCL/SDA transitions +// Each command has 5 states, A/B/C/D/idle +// +// start: SCL ~~~~~~~~~~\____ +// SDA ~~~~~~~~\______ +// x | A | B | C | D | i +// +// repstart SCL ____/~~~~\___ +// SDA __/~~~\______ +// x | A | B | C | D | i +// +// stop SCL ____/~~~~~~~~ +// SDA ==\____/~~~~~ +// x | A | B | C | D | i +// +//- write SCL ____/~~~~\____ +// SDA ==X=========X= +// x | A | B | C | D | i +// +//- read SCL ____/~~~~\____ +// SDA XXXX=====XXXX +// x | A | B | C | D | i +// + +// Timing: Normal mode Fast mode +/////////////////////////////////////////////////////////////////////// +// Fscl 100KHz 400KHz +// Th_scl 4.0us 0.6us High period of SCL +// Tl_scl 4.7us 1.3us Low period of SCL +// Tsu:sta 4.7us 0.6us setup time for a repeated start condition +// Tsu:sto 4.0us 0.6us setup time for a stop conditon +// Tbuf 4.7us 1.3us Bus free time between a stop and start condition +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +`include "i2c_master_defines.v" + +module i2c_master_bit_ctrl( + clk, rst, nReset, + clk_cnt, ena, cmd, cmd_ack, busy, al, din, dout, + scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen + ); + + // + // inputs & outputs + // + input clk; + input rst; + input nReset; + input ena; // core enable signal + + input [15:0] clk_cnt; // clock prescale value + + input [3:0] cmd; + output cmd_ack; // command complete acknowledge + reg cmd_ack; + output busy; // i2c bus busy + reg busy; + output al; // i2c bus arbitration lost + reg al; + + input din; + output dout; + reg dout; + + // I2C lines + input scl_i; // i2c clock line input + output scl_o; // i2c clock line output + output scl_oen; // i2c clock line output enable (active low) + reg scl_oen; + input sda_i; // i2c data line input + output sda_o; // i2c data line output + output sda_oen; // i2c data line output enable (active low) + reg sda_oen; + + + // + // variable declarations + // + + reg sSCL, sSDA; // synchronized SCL and SDA inputs + reg dscl_oen; // delayed scl_oen + reg sda_chk; // check SDA output (Multi-master arbitration) + reg clk_en; // clock generation signals + wire slave_wait; +// reg [15:0] cnt = clk_cnt; // clock divider counter (simulation) + reg [15:0] cnt; // clock divider counter (synthesis) + + // state machine variable + reg [16:0] c_state; // synopsys enum_state + + // + // module body + // + + // whenever the slave is not ready it can delay the cycle by pulling SCL low + // delay scl_oen + always @(posedge clk) + dscl_oen <= #1 scl_oen; + + assign slave_wait = dscl_oen && !sSCL; + + + // generate clk enable signal + always @(posedge clk or negedge nReset) + if(~nReset) + begin + cnt <= #1 16'h0; + clk_en <= #1 1'b1; + end + else if (rst) + begin + cnt <= #1 16'h0; + clk_en <= #1 1'b1; + end + else if ( ~|cnt || ~ena) + if (~slave_wait) + begin + cnt <= #1 clk_cnt; + clk_en <= #1 1'b1; + end + else + begin + cnt <= #1 cnt; + clk_en <= #1 1'b0; + end + else + begin + cnt <= #1 cnt - 16'h1; + clk_en <= #1 1'b0; + end + + + // generate bus status controller + reg dSCL, dSDA; + reg sta_condition; + reg sto_condition; + + // synchronize SCL and SDA inputs + // reduce metastability risc + always @(posedge clk or negedge nReset) + if (~nReset) + begin + sSCL <= #1 1'b1; + sSDA <= #1 1'b1; + + dSCL <= #1 1'b1; + dSDA <= #1 1'b1; + end + else if (rst) + begin + sSCL <= #1 1'b1; + sSDA <= #1 1'b1; + + dSCL <= #1 1'b1; + dSDA <= #1 1'b1; + end + else + begin + sSCL <= #1 scl_i; + sSDA <= #1 sda_i; + + dSCL <= #1 sSCL; + dSDA <= #1 sSDA; + end + + // detect start condition => detect falling edge on SDA while SCL is high + // detect stop condition => detect rising edge on SDA while SCL is high + always @(posedge clk or negedge nReset) + if (~nReset) + begin + sta_condition <= #1 1'b0; + sto_condition <= #1 1'b0; + end + else if (rst) + begin + sta_condition <= #1 1'b0; + sto_condition <= #1 1'b0; + end + else + begin + sta_condition <= #1 ~sSDA & dSDA & sSCL; + sto_condition <= #1 sSDA & ~dSDA & sSCL; + end + + // generate i2c bus busy signal + always @(posedge clk or negedge nReset) + if(!nReset) + busy <= #1 1'b0; + else if (rst) + busy <= #1 1'b0; + else + busy <= #1 (sta_condition | busy) & ~sto_condition; + + // generate arbitration lost signal + // aribitration lost when: + // 1) master drives SDA high, but the i2c bus is low + // 2) stop detected while not requested + reg cmd_stop; + always @(posedge clk or negedge nReset) + if (~nReset) + cmd_stop <= #1 1'b0; + else if (rst) + cmd_stop <= #1 1'b0; + else if (clk_en) + cmd_stop <= #1 cmd == `I2C_CMD_STOP; + + always @(posedge clk or negedge nReset) + if (~nReset) + al <= #1 1'b0; + else if (rst) + al <= #1 1'b0; + else + al <= #1 (sda_chk & ~sSDA & sda_oen) | (|c_state & sto_condition & ~cmd_stop); + + + // generate dout signal (store SDA on rising edge of SCL) + always @(posedge clk) + if(sSCL & ~dSCL) + dout <= #1 sSDA; + + // generate statemachine + + // nxt_state decoder + parameter [16:0] idle = 17'b0_0000_0000_0000_0000; + parameter [16:0] start_a = 17'b0_0000_0000_0000_0001; + parameter [16:0] start_b = 17'b0_0000_0000_0000_0010; + parameter [16:0] start_c = 17'b0_0000_0000_0000_0100; + parameter [16:0] start_d = 17'b0_0000_0000_0000_1000; + parameter [16:0] start_e = 17'b0_0000_0000_0001_0000; + parameter [16:0] stop_a = 17'b0_0000_0000_0010_0000; + parameter [16:0] stop_b = 17'b0_0000_0000_0100_0000; + parameter [16:0] stop_c = 17'b0_0000_0000_1000_0000; + parameter [16:0] stop_d = 17'b0_0000_0001_0000_0000; + parameter [16:0] rd_a = 17'b0_0000_0010_0000_0000; + parameter [16:0] rd_b = 17'b0_0000_0100_0000_0000; + parameter [16:0] rd_c = 17'b0_0000_1000_0000_0000; + parameter [16:0] rd_d = 17'b0_0001_0000_0000_0000; + parameter [16:0] wr_a = 17'b0_0010_0000_0000_0000; + parameter [16:0] wr_b = 17'b0_0100_0000_0000_0000; + parameter [16:0] wr_c = 17'b0_1000_0000_0000_0000; + parameter [16:0] wr_d = 17'b1_0000_0000_0000_0000; + + always @(posedge clk or negedge nReset) + if (!nReset) + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b0; + scl_oen <= #1 1'b1; + sda_oen <= #1 1'b1; + sda_chk <= #1 1'b0; + end + else if (rst | al) + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b0; + scl_oen <= #1 1'b1; + sda_oen <= #1 1'b1; + sda_chk <= #1 1'b0; + end + else + begin + cmd_ack <= #1 1'b0; // default no command acknowledge + assert cmd_ack only 1clk cycle + + if (clk_en) + case (c_state) // synopsys full_case parallel_case + // idle state + idle: + begin + case (cmd) // synopsys full_case parallel_case + `I2C_CMD_START: + c_state <= #1 start_a; + + `I2C_CMD_STOP: + c_state <= #1 stop_a; + + `I2C_CMD_WRITE: + c_state <= #1 wr_a; + + `I2C_CMD_READ: + c_state <= #1 rd_a; + + default: + c_state <= #1 idle; + endcase + + scl_oen <= #1 scl_oen; // keep SCL in same state + sda_oen <= #1 sda_oen; // keep SDA in same state + sda_chk <= #1 1'b0; // don't check SDA output + end + + // start + start_a: + begin + c_state <= #1 start_b; + scl_oen <= #1 scl_oen; // keep SCL in same state + sda_oen <= #1 1'b1; // set SDA high + sda_chk <= #1 1'b0; // don't check SDA output + end + + start_b: + begin + c_state <= #1 start_c; + scl_oen <= #1 1'b1; // set SCL high + sda_oen <= #1 1'b1; // keep SDA high + sda_chk <= #1 1'b0; // don't check SDA output + end + + start_c: + begin + c_state <= #1 start_d; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b0; // set SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + start_d: + begin + c_state <= #1 start_e; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b0; // keep SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + start_e: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b0; // set SCL low + sda_oen <= #1 1'b0; // keep SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + // stop + stop_a: + begin + c_state <= #1 stop_b; + scl_oen <= #1 1'b0; // keep SCL low + sda_oen <= #1 1'b0; // set SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + stop_b: + begin + c_state <= #1 stop_c; + scl_oen <= #1 1'b1; // set SCL high + sda_oen <= #1 1'b0; // keep SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + stop_c: + begin + c_state <= #1 stop_d; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b0; // keep SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + stop_d: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b1; // set SDA high + sda_chk <= #1 1'b0; // don't check SDA output + end + + // read + rd_a: + begin + c_state <= #1 rd_b; + scl_oen <= #1 1'b0; // keep SCL low + sda_oen <= #1 1'b1; // tri-state SDA + sda_chk <= #1 1'b0; // don't check SDA output + end + + rd_b: + begin + c_state <= #1 rd_c; + scl_oen <= #1 1'b1; // set SCL high + sda_oen <= #1 1'b1; // keep SDA tri-stated + sda_chk <= #1 1'b0; // don't check SDA output + end + + rd_c: + begin + c_state <= #1 rd_d; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b1; // keep SDA tri-stated + sda_chk <= #1 1'b0; // don't check SDA output + end + + rd_d: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b0; // set SCL low + sda_oen <= #1 1'b1; // keep SDA tri-stated + sda_chk <= #1 1'b0; // don't check SDA output + end + + // write + wr_a: + begin + c_state <= #1 wr_b; + scl_oen <= #1 1'b0; // keep SCL low + sda_oen <= #1 din; // set SDA + sda_chk <= #1 1'b0; // don't check SDA output (SCL low) + end + + wr_b: + begin + c_state <= #1 wr_c; + scl_oen <= #1 1'b1; // set SCL high + sda_oen <= #1 din; // keep SDA + sda_chk <= #1 1'b1; // check SDA output + end + + wr_c: + begin + c_state <= #1 wr_d; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 din; + sda_chk <= #1 1'b1; // check SDA output + end + + wr_d: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b0; // set SCL low + sda_oen <= #1 din; + sda_chk <= #1 1'b0; // don't check SDA output (SCL low) + end + + endcase + end + + + // assign scl and sda output (always gnd) + assign scl_o = 1'b0; + assign sda_o = 1'b0; + +endmodule diff --git a/tests/iwls2005/i2c/i2c_master_byte_ctrl.v b/tests/iwls2005/i2c/i2c_master_byte_ctrl.v new file mode 100644 index 00000000..d091d1e3 --- /dev/null +++ b/tests/iwls2005/i2c/i2c_master_byte_ctrl.v @@ -0,0 +1,344 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant I2C Master byte-controller //// +//// //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/i2c/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: i2c_master_byte_ctrl.v,v 1.7 2004/02/18 11:40:46 rherveille Exp $ +// +// $Date: 2004/02/18 11:40:46 $ +// $Revision: 1.7 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: i2c_master_byte_ctrl.v,v $ +// Revision 1.7 2004/02/18 11:40:46 rherveille +// Fixed a potential bug in the statemachine. During a 'stop' 2 cmd_ack signals were generated. Possibly canceling a new start command. +// +// Revision 1.6 2003/08/09 07:01:33 rherveille +// Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. +// Fixed a potential bug in the byte controller's host-acknowledge generation. +// +// Revision 1.5 2002/12/26 15:02:32 rherveille +// Core is now a Multimaster I2C controller +// +// Revision 1.4 2002/11/30 22:24:40 rherveille +// Cleaned up code +// +// Revision 1.3 2001/11/05 11:59:25 rherveille +// Fixed wb_ack_o generation bug. +// Fixed bug in the byte_controller statemachine. +// Added headers. +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +`include "i2c_master_defines.v" + +module i2c_master_byte_ctrl ( + clk, rst, nReset, ena, clk_cnt, start, stop, read, write, ack_in, din, + cmd_ack, ack_out, dout, i2c_busy, i2c_al, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen ); + + // + // inputs & outputs + // + input clk; // master clock + input rst; // synchronous active high reset + input nReset; // asynchronous active low reset + input ena; // core enable signal + + input [15:0] clk_cnt; // 4x SCL + + // control inputs + input start; + input stop; + input read; + input write; + input ack_in; + input [7:0] din; + + // status outputs + output cmd_ack; + reg cmd_ack; + output ack_out; + reg ack_out; + output i2c_busy; + output i2c_al; + output [7:0] dout; + + // I2C signals + input scl_i; + output scl_o; + output scl_oen; + input sda_i; + output sda_o; + output sda_oen; + + + // + // Variable declarations + // + + // statemachine + parameter [4:0] ST_IDLE = 5'b0_0000; + parameter [4:0] ST_START = 5'b0_0001; + parameter [4:0] ST_READ = 5'b0_0010; + parameter [4:0] ST_WRITE = 5'b0_0100; + parameter [4:0] ST_ACK = 5'b0_1000; + parameter [4:0] ST_STOP = 5'b1_0000; + + // signals for bit_controller + reg [3:0] core_cmd; + reg core_txd; + wire core_ack, core_rxd; + + // signals for shift register + reg [7:0] sr; //8bit shift register + reg shift, ld; + + // signals for state machine + wire go; + reg [2:0] dcnt; + wire cnt_done; + + // + // Module body + // + + // hookup bit_controller + i2c_master_bit_ctrl bit_controller ( + .clk ( clk ), + .rst ( rst ), + .nReset ( nReset ), + .ena ( ena ), + .clk_cnt ( clk_cnt ), + .cmd ( core_cmd ), + .cmd_ack ( core_ack ), + .busy ( i2c_busy ), + .al ( i2c_al ), + .din ( core_txd ), + .dout ( core_rxd ), + .scl_i ( scl_i ), + .scl_o ( scl_o ), + .scl_oen ( scl_oen ), + .sda_i ( sda_i ), + .sda_o ( sda_o ), + .sda_oen ( sda_oen ) + ); + + // generate go-signal + assign go = (read | write | stop) & ~cmd_ack; + + // assign dout output to shift-register + assign dout = sr; + + // generate shift register + always @(posedge clk or negedge nReset) + if (!nReset) + sr <= #1 8'h0; + else if (rst) + sr <= #1 8'h0; + else if (ld) + sr <= #1 din; + else if (shift) + sr <= #1 {sr[6:0], core_rxd}; + + // generate counter + always @(posedge clk or negedge nReset) + if (!nReset) + dcnt <= #1 3'h0; + else if (rst) + dcnt <= #1 3'h0; + else if (ld) + dcnt <= #1 3'h7; + else if (shift) + dcnt <= #1 dcnt - 3'h1; + + assign cnt_done = ~(|dcnt); + + // + // state machine + // + reg [4:0] c_state; // synopsis enum_state + + always @(posedge clk or negedge nReset) + if (!nReset) + begin + core_cmd <= #1 `I2C_CMD_NOP; + core_txd <= #1 1'b0; + shift <= #1 1'b0; + ld <= #1 1'b0; + cmd_ack <= #1 1'b0; + c_state <= #1 ST_IDLE; + ack_out <= #1 1'b0; + end + else if (rst | i2c_al) + begin + core_cmd <= #1 `I2C_CMD_NOP; + core_txd <= #1 1'b0; + shift <= #1 1'b0; + ld <= #1 1'b0; + cmd_ack <= #1 1'b0; + c_state <= #1 ST_IDLE; + ack_out <= #1 1'b0; + end + else + begin + // initially reset all signals + core_txd <= #1 sr[7]; + shift <= #1 1'b0; + ld <= #1 1'b0; + cmd_ack <= #1 1'b0; + + case (c_state) // synopsys full_case parallel_case + ST_IDLE: + if (go) + begin + if (start) + begin + c_state <= #1 ST_START; + core_cmd <= #1 `I2C_CMD_START; + end + else if (read) + begin + c_state <= #1 ST_READ; + core_cmd <= #1 `I2C_CMD_READ; + end + else if (write) + begin + c_state <= #1 ST_WRITE; + core_cmd <= #1 `I2C_CMD_WRITE; + end + else // stop + begin + c_state <= #1 ST_STOP; + core_cmd <= #1 `I2C_CMD_STOP; + end + + ld <= #1 1'b1; + end + + ST_START: + if (core_ack) + begin + if (read) + begin + c_state <= #1 ST_READ; + core_cmd <= #1 `I2C_CMD_READ; + end + else + begin + c_state <= #1 ST_WRITE; + core_cmd <= #1 `I2C_CMD_WRITE; + end + + ld <= #1 1'b1; + end + + ST_WRITE: + if (core_ack) + if (cnt_done) + begin + c_state <= #1 ST_ACK; + core_cmd <= #1 `I2C_CMD_READ; + end + else + begin + c_state <= #1 ST_WRITE; // stay in same state + core_cmd <= #1 `I2C_CMD_WRITE; // write next bit + shift <= #1 1'b1; + end + + ST_READ: + if (core_ack) + begin + if (cnt_done) + begin + c_state <= #1 ST_ACK; + core_cmd <= #1 `I2C_CMD_WRITE; + end + else + begin + c_state <= #1 ST_READ; // stay in same state + core_cmd <= #1 `I2C_CMD_READ; // read next bit + end + + shift <= #1 1'b1; + core_txd <= #1 ack_in; + end + + ST_ACK: + if (core_ack) + begin + if (stop) + begin + c_state <= #1 ST_STOP; + core_cmd <= #1 `I2C_CMD_STOP; + end + else + begin + c_state <= #1 ST_IDLE; + core_cmd <= #1 `I2C_CMD_NOP; + + // generate command acknowledge signal + cmd_ack <= #1 1'b1; + end + + // assign ack_out output to bit_controller_rxd (contains last received bit) + ack_out <= #1 core_rxd; + + core_txd <= #1 1'b1; + end + else + core_txd <= #1 ack_in; + + ST_STOP: + if (core_ack) + begin + c_state <= #1 ST_IDLE; + core_cmd <= #1 `I2C_CMD_NOP; + + // generate command acknowledge signal + cmd_ack <= #1 1'b1; + end + + endcase + end +endmodule diff --git a/tests/iwls2005/i2c/i2c_master_defines.v b/tests/iwls2005/i2c/i2c_master_defines.v new file mode 100644 index 00000000..ee3b694f --- /dev/null +++ b/tests/iwls2005/i2c/i2c_master_defines.v @@ -0,0 +1,64 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant I2C Master controller defines //// +//// //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/i2c/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: i2c_master_defines.v,v 1.3 2001/11/05 11:59:25 rherveille Exp $ +// +// $Date: 2001/11/05 11:59:25 $ +// $Revision: 1.3 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: i2c_master_defines.v,v $ +// Revision 1.3 2001/11/05 11:59:25 rherveille +// Fixed wb_ack_o generation bug. +// Fixed bug in the byte_controller statemachine. +// Added headers. +// + + +// I2C registers wishbone addresses + +// bitcontroller states +`define I2C_CMD_NOP 4'b0000 +`define I2C_CMD_START 4'b0001 +`define I2C_CMD_STOP 4'b0010 +`define I2C_CMD_WRITE 4'b0100 +`define I2C_CMD_READ 4'b1000 diff --git a/tests/iwls2005/i2c/i2c_master_top.v b/tests/iwls2005/i2c/i2c_master_top.v new file mode 100644 index 00000000..30689bd7 --- /dev/null +++ b/tests/iwls2005/i2c/i2c_master_top.v @@ -0,0 +1,301 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE revB.2 compliant I2C Master controller Top-level //// +//// //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/i2c/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: i2c_master_top.v,v 1.11 2005/02/27 09:26:24 rherveille Exp $ +// +// $Date: 2005/02/27 09:26:24 $ +// $Revision: 1.11 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: i2c_master_top.v,v $ +// Revision 1.11 2005/02/27 09:26:24 rherveille +// Fixed register overwrite issue. +// Removed full_case pragma, replaced it by a default statement. +// +// Revision 1.10 2003/09/01 10:34:38 rherveille +// Fix a blocking vs. non-blocking error in the wb_dat output mux. +// +// Revision 1.9 2003/01/09 16:44:45 rherveille +// Fixed a bug in the Command Register declaration. +// +// Revision 1.8 2002/12/26 16:05:12 rherveille +// Small code simplifications +// +// Revision 1.7 2002/12/26 15:02:32 rherveille +// Core is now a Multimaster I2C controller +// +// Revision 1.6 2002/11/30 22:24:40 rherveille +// Cleaned up code +// +// Revision 1.5 2001/11/10 10:52:55 rherveille +// Changed PRER reset value from 0x0000 to 0xffff, conform specs. +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +`include "i2c_master_defines.v" + +module i2c_master_top( + wb_clk_i, wb_rst_i, arst_i, wb_adr_i, wb_dat_i, wb_dat_o, + wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_inta_o, + scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o ); + + // parameters + parameter ARST_LVL = 1'b0; // asynchronous reset level + + // + // inputs & outputs + // + + // wishbone signals + input wb_clk_i; // master clock input + input wb_rst_i; // synchronous active high reset + input arst_i; // asynchronous reset + input [2:0] wb_adr_i; // lower address bits + input [7:0] wb_dat_i; // databus input + output [7:0] wb_dat_o; // databus output + input wb_we_i; // write enable input + input wb_stb_i; // stobe/core select signal + input wb_cyc_i; // valid bus cycle input + output wb_ack_o; // bus cycle acknowledge output + output wb_inta_o; // interrupt request signal output + + reg [7:0] wb_dat_o; + reg wb_ack_o; + reg wb_inta_o; + + // I2C signals + // i2c clock line + input scl_pad_i; // SCL-line input + output scl_pad_o; // SCL-line output (always 1'b0) + output scl_padoen_o; // SCL-line output enable (active low) + + // i2c data line + input sda_pad_i; // SDA-line input + output sda_pad_o; // SDA-line output (always 1'b0) + output sda_padoen_o; // SDA-line output enable (active low) + + + // + // variable declarations + // + + // registers + reg [15:0] prer; // clock prescale register + reg [ 7:0] ctr; // control register + reg [ 7:0] txr; // transmit register + wire [ 7:0] rxr; // receive register + reg [ 7:0] cr; // command register + wire [ 7:0] sr; // status register + + // done signal: command completed, clear command register + wire done; + + // core enable signal + wire core_en; + wire ien; + + // status register signals + wire irxack; + reg rxack; // received aknowledge from slave + reg tip; // transfer in progress + reg irq_flag; // interrupt pending flag + wire i2c_busy; // bus busy (start signal detected) + wire i2c_al; // i2c bus arbitration lost + reg al; // status register arbitration lost bit + + // + // module body + // + + // generate internal reset + wire rst_i = arst_i ^ ARST_LVL; + + // generate wishbone signals + wire wb_wacc = wb_cyc_i & wb_stb_i & wb_we_i; + + // generate acknowledge output signal + always @(posedge wb_clk_i) + wb_ack_o <= #1 wb_cyc_i & wb_stb_i & ~wb_ack_o; // because timing is always honored + + // assign DAT_O + always @(posedge wb_clk_i) + begin + case (wb_adr_i) // synopsis parallel_case + 3'b000: wb_dat_o <= #1 prer[ 7:0]; + 3'b001: wb_dat_o <= #1 prer[15:8]; + 3'b010: wb_dat_o <= #1 ctr; + 3'b011: wb_dat_o <= #1 rxr; // write is transmit register (txr) + 3'b100: wb_dat_o <= #1 sr; // write is command register (cr) + 3'b101: wb_dat_o <= #1 txr; + 3'b110: wb_dat_o <= #1 cr; + 3'b111: wb_dat_o <= #1 0; // reserved + endcase + end + + // generate registers + always @(posedge wb_clk_i or negedge rst_i) + if (!rst_i) + begin + prer <= #1 16'hffff; + ctr <= #1 8'h0; + txr <= #1 8'h0; + end + else if (wb_rst_i) + begin + prer <= #1 16'hffff; + ctr <= #1 8'h0; + txr <= #1 8'h0; + end + else + if (wb_wacc) + case (wb_adr_i) // synopsis parallel_case + 3'b000 : prer [ 7:0] <= #1 wb_dat_i; + 3'b001 : prer [15:8] <= #1 wb_dat_i; + 3'b010 : ctr <= #1 wb_dat_i; + 3'b011 : txr <= #1 wb_dat_i; + default: ; + endcase + + // generate command register (special case) + always @(posedge wb_clk_i or negedge rst_i) + if (~rst_i) + cr <= #1 8'h0; + else if (wb_rst_i) + cr <= #1 8'h0; + else if (wb_wacc) + begin + if (core_en & (wb_adr_i == 3'b100) ) + cr <= #1 wb_dat_i; + end + else + begin + if (done | i2c_al) + cr[7:4] <= #1 4'h0; // clear command bits when done + // or when aribitration lost + cr[2:1] <= #1 2'b0; // reserved bits + cr[0] <= #1 2'b0; // clear IRQ_ACK bit + end + + + // decode command register + wire sta = cr[7]; + wire sto = cr[6]; + wire rd = cr[5]; + wire wr = cr[4]; + wire ack = cr[3]; + wire iack = cr[0]; + + // decode control register + assign core_en = ctr[7]; + assign ien = ctr[6]; + + // hookup byte controller block + i2c_master_byte_ctrl byte_controller ( + .clk ( wb_clk_i ), + .rst ( wb_rst_i ), + .nReset ( rst_i ), + .ena ( core_en ), + .clk_cnt ( prer ), + .start ( sta ), + .stop ( sto ), + .read ( rd ), + .write ( wr ), + .ack_in ( ack ), + .din ( txr ), + .cmd_ack ( done ), + .ack_out ( irxack ), + .dout ( rxr ), + .i2c_busy ( i2c_busy ), + .i2c_al ( i2c_al ), + .scl_i ( scl_pad_i ), + .scl_o ( scl_pad_o ), + .scl_oen ( scl_padoen_o ), + .sda_i ( sda_pad_i ), + .sda_o ( sda_pad_o ), + .sda_oen ( sda_padoen_o ) + ); + + // status register block + interrupt request signal + always @(posedge wb_clk_i or negedge rst_i) + if (!rst_i) + begin + al <= #1 1'b0; + rxack <= #1 1'b0; + tip <= #1 1'b0; + irq_flag <= #1 1'b0; + end + else if (wb_rst_i) + begin + al <= #1 1'b0; + rxack <= #1 1'b0; + tip <= #1 1'b0; + irq_flag <= #1 1'b0; + end + else + begin + al <= #1 i2c_al | (al & ~sta); + rxack <= #1 irxack; + tip <= #1 (rd | wr); + irq_flag <= #1 (done | i2c_al | irq_flag) & ~iack; // interrupt request flag is always generated + end + + // generate interrupt request signals + always @(posedge wb_clk_i or negedge rst_i) + if (!rst_i) + wb_inta_o <= #1 1'b0; + else if (wb_rst_i) + wb_inta_o <= #1 1'b0; + else + wb_inta_o <= #1 irq_flag && ien; // interrupt signal is only generated when IEN (interrupt enable bit is set) + + // assign status register bits + assign sr[7] = rxack; + assign sr[6] = i2c_busy; + assign sr[5] = al; + assign sr[4:2] = 3'h0; // reserved + assign sr[1] = tip; + assign sr[0] = irq_flag; + +endmodule diff --git a/tests/iwls2005/i2c/timescale.v b/tests/iwls2005/i2c/timescale.v new file mode 100644 index 00000000..60d4ecbd --- /dev/null +++ b/tests/iwls2005/i2c/timescale.v @@ -0,0 +1,2 @@ +`timescale 1ns / 10ps + diff --git a/tests/iwls2005/run-fm.sh b/tests/iwls2005/run-fm.sh new file mode 100755 index 00000000..14bb4e82 --- /dev/null +++ b/tests/iwls2005/run-fm.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +if [ -n "$REMOTE_YOSYS_ROOT" ]; then + rsync --exclude=".svn" --exclude="synth.log" --exclude="run-fm.sh" -rv -e "${REMOTE_YOSYS_SSH:-ssh}" "$REMOTE_YOSYS_ROOT"/tests/iwls2005/. . +fi + +exec_fm() +{ + dir=$1; top=$2; shift; shift + cat > $dir/fm.do <<- EOT + set hdlin_ignore_full_case false + set hdlin_warn_on_mismatch_message "FMR_ELAB-115 FMR_ELAB-146 FMR_ELAB-147" + read_verilog -container r -libname WORK -01 { $* } + set_top r:/WORK/$top + read_verilog -container i -libname WORK -01 synth.v + # read_verilog -container i -technology_library -libname TECH_WORK -01 ../../../techlibs/stdcells_sim.v + set_top i:/WORK/$top + if ![verify] start_gui exit + EOT + ( cd $dir; fm_shell -64 -file fm.do 2>&1 | tee fm.log; ) +} + +# cores that validated +exec_fm aes_core aes_cipher_top aes_cipher_top.v aes_inv_cipher_top.v aes_inv_sbox.v aes_key_expand_128.v aes_rcon.v aes_sbox.v +exec_fm i2c i2c_master_top i2c_master_top.v i2c_master_bit_ctrl.v i2c_master_byte_ctrl.v +exec_fm sasc sasc_top sasc_top.v sasc_brg.v sasc_fifo4.v +exec_fm simple_spi simple_spi_top simple_spi_top.v fifo4.v +exec_fm spi spi_top spi_top.v spi_clgen.v spi_shift.v +exec_fm ss_pcm pcm_slv_top pcm_slv_top.v +exec_fm systemcaes aes aes.v byte_mixcolum.v keysched.v mixcolum.v sbox.v subbytes.v word_mixcolum.v +exec_fm usb_phy usb_phy usb_phy.v usb_rx_phy.v usb_tx_phy.v + +# cores with known problems (the fpu core unfortunately was designed with logic loops) +#exec_fm fpu fpu fpu.v except.v post_norm.v pre_norm_fmul.v pre_norm.v primitives.v + +# summary +echo; echo +for x in */fm.log; do + echo -e "${x%/*}\\t$( egrep '^Verification (SUCCEEDED|FAILED)' $x; )" +done | expand -t15 +echo; echo + diff --git a/tests/iwls2005/run-synth.sh b/tests/iwls2005/run-synth.sh new file mode 100755 index 00000000..2f1e3066 --- /dev/null +++ b/tests/iwls2005/run-synth.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +make -C ../.. +set -x + +vg="" +# vg="valgrind --leak-check=full --show-reachable=yes --log-file=valgrind.log" + +cd aes_core +time $vg ../../../yosys -qt -l synth.log -o synth.v -s ../run-synth.ys \ + aes_cipher_top.v aes_inv_cipher_top.v aes_inv_sbox.v \ + aes_key_expand_128.v aes_rcon.v aes_sbox.v + +cd ../fpu +time $vg ../../../yosys -qt -l synth.log -o synth.v -f "verilog -nolatches" -s ../run-synth.ys \ + fpu.v except.v post_norm.v pre_norm_fmul.v pre_norm.v primitives.v + +cd ../i2c +time $vg ../../../yosys -qt -l synth.log -o synth.v -s ../run-synth.ys \ + i2c_master_top.v i2c_master_bit_ctrl.v i2c_master_byte_ctrl.v + +cd ../sasc +time $vg ../../../yosys -qt -l synth.log -o synth.v -s ../run-synth.ys \ + sasc_top.v sasc_brg.v sasc_fifo4.v + +cd ../simple_spi +time $vg ../../../yosys -qt -l synth.log -o synth.v -s ../run-synth.ys \ + simple_spi_top.v fifo4.v + +cd ../spi +time $vg ../../../yosys -qt -l synth.log -o synth.v -s ../run-synth.ys \ + spi_top.v spi_clgen.v spi_shift.v + +cd ../ss_pcm +time $vg ../../../yosys -qt -l synth.log -o synth.v -s ../run-synth.ys \ + pcm_slv_top.v + +cd ../systemcaes +time $vg ../../../yosys -qt -l synth.log -o synth.v -s ../run-synth.ys \ + aes.v byte_mixcolum.v keysched.v mixcolum.v sbox.v subbytes.v word_mixcolum.v + +cd ../usb_phy +time $vg ../../../yosys -qt -l synth.log -o synth.v -s ../run-synth.ys \ + usb_phy.v usb_rx_phy.v usb_tx_phy.v + diff --git a/tests/iwls2005/run-synth.ys b/tests/iwls2005/run-synth.ys new file mode 100644 index 00000000..f3253d5f --- /dev/null +++ b/tests/iwls2005/run-synth.ys @@ -0,0 +1,11 @@ +hierarchy +proc +opt +memory +opt +# fsm -norecode +# opt +techmap +opt +abc +opt diff --git a/tests/iwls2005/sasc/sasc_brg.v b/tests/iwls2005/sasc/sasc_brg.v new file mode 100644 index 00000000..74a7cc5b --- /dev/null +++ b/tests/iwls2005/sasc/sasc_brg.v @@ -0,0 +1,160 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Simple Baud Rate Generator //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/sasc/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: sasc_brg.v,v 1.2 2002/11/08 15:22:49 rudi Exp $ +// +// $Date: 2002/11/08 15:22:49 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: sasc_brg.v,v $ +// Revision 1.2 2002/11/08 15:22:49 rudi +// +// Fixed a typo in brg +// +// Revision 1.1.1.1 2002/09/16 16:16:40 rudi +// Initial Checkin +// +// +// +// +// +// +// +// + +`include "timescale.v" + +/* + Baud rate Generator + ================== + + div0 - is the first stage divider + Set this to the desired number of cycles less two + div1 - is the second stage divider + Set this to the actual number of cycles + + Remember you have to generate a baud rate that is 4 higher than what + you really want. This is because of the DPLL in the RX section ... + + Example: + If your system clock is 50MHz and you want to generate a 9.6 Kbps baud rate: + 9600*4 = 38400KHz + 50MHz/38400KHz=1302 or 6*217 + set div0=4 (6-2) and set div1=217 + +*/ + +module sasc_brg(clk, rst, div0, div1, sio_ce, sio_ce_x4); +input clk; +input rst; +input [7:0] div0, div1; +output sio_ce, sio_ce_x4; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +reg [7:0] ps; +reg ps_clr; +reg [7:0] br_cnt; +reg br_clr; +reg sio_ce_x4_r; +reg [1:0] cnt; +reg sio_ce, sio_ce_x4; +reg sio_ce_r ; +reg sio_ce_x4_t; + +/////////////////////////////////////////////////////////////////// +// +// Boud Rate Generator +// + +// ----------------------------------------------------- +// Prescaler +always @(posedge clk) + if(!rst) ps <= #1 8'h0; + else + if(ps_clr) ps <= #1 8'h0; + else ps <= #1 ps + 8'h1; + +always @(posedge clk) + ps_clr <= #1 (ps == div0); // Desired number of cycles less 2 + +// ----------------------------------------------------- +// Oversampled Boud Rate (x4) +always @(posedge clk) + if(!rst) br_cnt <= #1 8'h0; + else + if(br_clr) br_cnt <= #1 8'h0; + else + if(ps_clr) br_cnt <= #1 br_cnt + 8'h1; + +always @(posedge clk) + br_clr <= #1 (br_cnt == div1); // Prciese number of PS cycles + +always @(posedge clk) + sio_ce_x4_r <= #1 br_clr; + +always @(posedge clk) + sio_ce_x4_t <= #1 !sio_ce_x4_r & br_clr; + +always @(posedge clk) + sio_ce_x4 <= #1 sio_ce_x4_t; + +// ----------------------------------------------------- +// Actual Boud rate +always @(posedge clk) + if(!rst) cnt <= #1 2'h0; + else + if(!sio_ce_x4_r & br_clr) cnt <= #1 cnt + 2'h1; + +always @(posedge clk) + sio_ce_r <= #1 (cnt == 2'h0); + +always @(posedge clk) + sio_ce <= #1 !sio_ce_r & (cnt == 2'h0); + +endmodule + diff --git a/tests/iwls2005/sasc/sasc_fifo4.v b/tests/iwls2005/sasc/sasc_fifo4.v new file mode 100644 index 00000000..ab9b9fef --- /dev/null +++ b/tests/iwls2005/sasc/sasc_fifo4.v @@ -0,0 +1,135 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// FIFO 4 entries deep //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/sasc/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: sasc_fifo4.v,v 1.1.1.1 2002/09/16 16:16:41 rudi Exp $ +// +// $Date: 2002/09/16 16:16:41 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: sasc_fifo4.v,v $ +// Revision 1.1.1.1 2002/09/16 16:16:41 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "timescale.v" + +// 4 entry deep fast fifo +module sasc_fifo4(clk, rst, clr, din, we, dout, re, full, empty); + +input clk, rst; +input clr; +input [7:0] din; +input we; +output [7:0] dout; +input re; +output full, empty; + + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [7:0] mem[0:3]; +reg [1:0] wp; +reg [1:0] rp; +wire [1:0] wp_p1; +wire [1:0] wp_p2; +wire [1:0] rp_p1; +wire full, empty; +reg gb; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk or negedge rst) + if(!rst) wp <= #1 2'h0; + else + if(clr) wp <= #1 2'h0; + else + if(we) wp <= #1 wp_p1; + +assign wp_p1 = wp + 2'h1; +assign wp_p2 = wp + 2'h2; + +always @(posedge clk or negedge rst) + if(!rst) rp <= #1 2'h0; + else + if(clr) rp <= #1 2'h0; + else + if(re) rp <= #1 rp_p1; + +assign rp_p1 = rp + 2'h1; + +// Fifo Output +assign dout = mem[ rp ]; + +// Fifo Input +always @(posedge clk) + if(we) mem[ wp ] <= #1 din; + +// Status +assign empty = (wp == rp) & !gb; +assign full = (wp == rp) & gb; + +// Guard Bit ... +always @(posedge clk) + if(!rst) gb <= #1 1'b0; + else + if(clr) gb <= #1 1'b0; + else + if((wp_p1 == rp) & we) gb <= #1 1'b1; + else + if(re) gb <= #1 1'b0; + +endmodule + + diff --git a/tests/iwls2005/sasc/sasc_top.v b/tests/iwls2005/sasc/sasc_top.v new file mode 100644 index 00000000..a59329ad --- /dev/null +++ b/tests/iwls2005/sasc/sasc_top.v @@ -0,0 +1,301 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Simple Asynchronous Serial Comm. Device //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/sasc/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: sasc_top.v,v 1.1.1.1 2002/09/16 16:16:42 rudi Exp $ +// +// $Date: 2002/09/16 16:16:42 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: sasc_top.v,v $ +// Revision 1.1.1.1 2002/09/16 16:16:42 rudi +// Initial Checkin +// +// +// +// +// +// +// +// + +`include "timescale.v" + +/* +Serial IO Interface +=============================== +RTS I Request To Send +CTS O Clear to send +TD I Transmit Data +RD O Receive Data +*/ + +module sasc_top( clk, rst, + + // SIO + rxd_i, txd_o, cts_i, rts_o, + + // External Baud Rate Generator + sio_ce, sio_ce_x4, + + // Internal Interface + din_i, dout_o, re_i, we_i, full_o, empty_o); + +input clk; +input rst; +input rxd_i; +output txd_o; +input cts_i; +output rts_o; +input sio_ce; +input sio_ce_x4; +input [7:0] din_i; +output [7:0] dout_o; +input re_i, we_i; +output full_o, empty_o; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +parameter START_BIT = 1'b0, + STOP_BIT = 1'b1, + IDLE_BIT = 1'b1; + +wire [7:0] txd_p; +reg load; +reg load_r; +wire load_e; +reg [9:0] hold_reg; +wire txf_empty; +reg txd_o; +reg shift_en; +reg [3:0] tx_bit_cnt; +reg rxd_s, rxd_r; +wire start; +reg [3:0] rx_bit_cnt; +reg rx_go; +reg [9:0] rxr; +reg rx_valid, rx_valid_r; +wire rx_we; +wire rxf_full; +reg rts_o; +reg txf_empty_r; +reg shift_en_r; +reg rxd_r1, rxd_r2; +wire lock_en; +reg change; +reg rx_sio_ce_d, rx_sio_ce_r1, rx_sio_ce_r2, rx_sio_ce; +reg [1:0] dpll_state, dpll_next_state; + +/////////////////////////////////////////////////////////////////// +// +// IO Fifo's +// + +sasc_fifo4 tx_fifo( .clk( clk ), + .rst( rst ), + .clr( 1'b0 ), + .din( din_i ), + .we( we_i ), + .dout( txd_p ), + .re( load_e ), + .full( full_o ), + .empty( txf_empty ) + ); + +sasc_fifo4 rx_fifo( .clk( clk ), + .rst( rst ), + .clr( 1'b0 ), + .din( rxr[9:2] ), + .we( rx_we ), + .dout( dout_o ), + .re( re_i ), + .full( rxf_full ), + .empty( empty_o ) + ); + +/////////////////////////////////////////////////////////////////// +// +// Transmit Logic +// +always @(posedge clk) + if(!rst) txf_empty_r <= #1 1'b1; + else + if(sio_ce) txf_empty_r <= #1 txf_empty; + +always @(posedge clk) + load <= #1 !txf_empty_r & !shift_en & !cts_i; + +always @(posedge clk) + load_r <= #1 load; + +assign load_e = load & sio_ce; + +always @(posedge clk) + if(load_e) hold_reg <= #1 {STOP_BIT, txd_p, START_BIT}; + else + if(shift_en & sio_ce) hold_reg <= #1 {IDLE_BIT, hold_reg[9:1]}; + +always @(posedge clk) + if(!rst) txd_o <= #1 IDLE_BIT; + else + if(sio_ce) + if(shift_en | shift_en_r) txd_o <= #1 hold_reg[0]; + else txd_o <= #1 IDLE_BIT; + +always @(posedge clk) + if(!rst) tx_bit_cnt <= #1 4'h9; + else + if(load_e) tx_bit_cnt <= #1 4'h0; + else + if(shift_en & sio_ce) tx_bit_cnt <= #1 tx_bit_cnt + 4'h1; + +always @(posedge clk) + shift_en <= #1 (tx_bit_cnt != 4'h9); + +always @(posedge clk) + if(!rst) shift_en_r <= #1 1'b0; + else + if(sio_ce) shift_en_r <= #1 shift_en; + +/////////////////////////////////////////////////////////////////// +// +// Recieve Logic +// + +always @(posedge clk) + rxd_s <= #1 rxd_i; + +always @(posedge clk) + rxd_r <= #1 rxd_s; + +assign start = (rxd_r == IDLE_BIT) & (rxd_s == START_BIT); + +always @(posedge clk) + if(!rst) rx_bit_cnt <= #1 4'ha; + else + if(!rx_go & start) rx_bit_cnt <= #1 4'h0; + else + if(rx_go & rx_sio_ce) rx_bit_cnt <= #1 rx_bit_cnt + 4'h1; + +always @(posedge clk) + rx_go <= #1 (rx_bit_cnt != 4'ha); + +always @(posedge clk) + rx_valid <= #1 (rx_bit_cnt == 4'h9); + +always @(posedge clk) + rx_valid_r <= #1 rx_valid; + +assign rx_we = !rx_valid_r & rx_valid & !rxf_full; + +always @(posedge clk) + if(rx_go & rx_sio_ce) rxr <= {rxd_s, rxr[9:1]}; + +always @(posedge clk) + rts_o <= #1 rxf_full; + +/////////////////////////////////////////////////////////////////// +// +// Reciever DPLL +// + +// Uses 4x baud clock to lock to incoming stream + +// Edge detector +always @(posedge clk) + if(sio_ce_x4) rxd_r1 <= #1 rxd_s; + +always @(posedge clk) + if(sio_ce_x4) rxd_r2 <= #1 rxd_r1; + +always @(posedge clk) + if(!rst) change <= #1 1'b0; + else + if(rxd_r != rxd_s) change <= #1 1'b1; + else + if(sio_ce_x4) change <= #1 1'b0; + +// DPLL FSM +always @(posedge clk or negedge rst) + if(!rst) dpll_state <= #1 2'h1; + else + if(sio_ce_x4) dpll_state <= #1 dpll_next_state; + +always @(dpll_state or change) + begin + rx_sio_ce_d = 1'b0; + case(dpll_state) + 2'h0: + if(change) dpll_next_state = 3'h0; + else dpll_next_state = 3'h1; + 2'h1:begin + rx_sio_ce_d = 1'b1; + if(change) dpll_next_state = 3'h3; + else dpll_next_state = 3'h2; + end + 2'h2: + if(change) dpll_next_state = 3'h0; + else dpll_next_state = 3'h3; + 2'h3: + if(change) dpll_next_state = 3'h0; + else dpll_next_state = 3'h0; + endcase + end + +// Compensate for sync registers at the input - allign sio +// clock enable to be in the middle between two bit changes ... +always @(posedge clk) + rx_sio_ce_r1 <= #1 rx_sio_ce_d; + +always @(posedge clk) + rx_sio_ce_r2 <= #1 rx_sio_ce_r1; + +always @(posedge clk) + rx_sio_ce <= #1 rx_sio_ce_r1 & !rx_sio_ce_r2; + +endmodule + + diff --git a/tests/iwls2005/sasc/timescale.v b/tests/iwls2005/sasc/timescale.v new file mode 100644 index 00000000..ff9e265a --- /dev/null +++ b/tests/iwls2005/sasc/timescale.v @@ -0,0 +1 @@ +`timescale 1ns / 10ps diff --git a/tests/iwls2005/simple_spi/fifo4.v b/tests/iwls2005/simple_spi/fifo4.v new file mode 100644 index 00000000..f041c7d2 --- /dev/null +++ b/tests/iwls2005/simple_spi/fifo4.v @@ -0,0 +1,134 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// FIFO 4 entries deep //// +//// //// +//// Authors: Rudolf Usselmann, Richard Herveille //// +//// rudi@asics.ws richard@asics.ws //// +//// //// +//// //// +//// Download from: http://www.opencores.org/projects/sasc //// +//// http://www.opencores.org/projects/simple_spi //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann, Richard Herveille //// +//// www.asics.ws //// +//// rudi@asics.ws, richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: fifo4.v,v 1.1.1.1 2002/12/22 16:07:14 rherveille Exp $ +// +// $Date: 2002/12/22 16:07:14 $ +// $Revision: 1.1.1.1 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: fifo4.v,v $ +// Revision 1.1.1.1 2002/12/22 16:07:14 rherveille +// Initial release +// +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + + +// 4 entry deep fast fifo +module fifo4(clk, rst, clr, din, we, dout, re, full, empty); + +parameter dw = 8; + +input clk, rst; +input clr; +input [dw:1] din; +input we; +output [dw:1] dout; +input re; +output full, empty; + + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [dw:1] mem[0:3]; +reg [1:0] wp; +reg [1:0] rp; +wire [1:0] wp_p1; +wire [1:0] wp_p2; +wire [1:0] rp_p1; +wire full, empty; +reg gb; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk or negedge rst) + if(!rst) wp <= #1 2'h0; + else + if(clr) wp <= #1 2'h0; + else + if(we) wp <= #1 wp_p1; + +assign wp_p1 = wp + 2'h1; +assign wp_p2 = wp + 2'h2; + +always @(posedge clk or negedge rst) + if(!rst) rp <= #1 2'h0; + else + if(clr) rp <= #1 2'h0; + else + if(re) rp <= #1 rp_p1; + +assign rp_p1 = rp + 2'h1; + +// Fifo Output +assign dout = mem[ rp ]; + +// Fifo Input +always @(posedge clk) + if(we) mem[ wp ] <= #1 din; + +// Status +assign empty = (wp == rp) & !gb; +assign full = (wp == rp) & gb; + +// Guard Bit ... +always @(posedge clk) + if(!rst) gb <= #1 1'b0; + else + if(clr) gb <= #1 1'b0; + else + if((wp_p1 == rp) & we) gb <= #1 1'b1; + else + if(re) gb <= #1 1'b0; + +endmodule diff --git a/tests/iwls2005/simple_spi/simple_spi_top.v b/tests/iwls2005/simple_spi/simple_spi_top.v new file mode 100644 index 00000000..e952f4be --- /dev/null +++ b/tests/iwls2005/simple_spi/simple_spi_top.v @@ -0,0 +1,329 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// OpenCores MC68HC11E based SPI interface //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2002 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: simple_spi_top.v,v 1.5 2004/02/28 15:59:50 rherveille Exp $ +// +// $Date: 2004/02/28 15:59:50 $ +// $Revision: 1.5 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: simple_spi_top.v,v $ +// Revision 1.5 2004/02/28 15:59:50 rherveille +// Fixed SCK_O generation bug. +// This resulted in a major rewrite of the serial interface engine. +// +// Revision 1.4 2003/08/01 11:41:54 rherveille +// Fixed some timing bugs. +// +// Revision 1.3 2003/01/09 16:47:59 rherveille +// Updated clkcnt size and decoding due to new SPR bit assignments. +// +// Revision 1.2 2003/01/07 13:29:52 rherveille +// Changed SPR bits coding. +// +// Revision 1.1.1.1 2002/12/22 16:07:15 rherveille +// Initial release +// +// + + + +// +// Motorola MC68HC11E based SPI interface +// +// Currently only MASTER mode is supported +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +module simple_spi_top( + // 8bit WISHBONE bus slave interface + input wire clk_i, // clock + input wire rst_i, // reset (asynchronous active low) + input wire cyc_i, // cycle + input wire stb_i, // strobe + input wire [1:0] adr_i, // address + input wire we_i, // write enable + input wire [7:0] dat_i, // data input + output reg [7:0] dat_o, // data output + output reg ack_o, // normal bus termination + output reg inta_o, // interrupt output + + // SPI port + output reg sck_o, // serial clock output + output wire mosi_o, // MasterOut SlaveIN + input wire miso_i // MasterIn SlaveOut +); + + // + // Module body + // + reg [7:0] spcr; // Serial Peripheral Control Register ('HC11 naming) + wire [7:0] spsr; // Serial Peripheral Status register ('HC11 naming) + reg [7:0] sper; // Serial Peripheral Extension register + reg [7:0] treg, rreg; // Transmit/Receive register + + // fifo signals + wire [7:0] rfdout; + reg wfre, rfwe; + wire rfre, rffull, rfempty; + wire [7:0] wfdout; + wire wfwe, wffull, wfempty; + + // misc signals + wire tirq; // transfer interrupt (selected number of transfers done) + wire wfov; // write fifo overrun (writing while fifo full) + reg [1:0] state; // statemachine state + reg [2:0] bcnt; + + // + // Wishbone interface + wire wb_acc = cyc_i & stb_i; // WISHBONE access + wire wb_wr = wb_acc & we_i; // WISHBONE write access + + // dat_i + always @(posedge clk_i or negedge rst_i) + if (~rst_i) + begin + spcr <= #1 8'h10; // set master bit + sper <= #1 8'h00; + end + else if (wb_wr) + begin + if (adr_i == 2'b00) + spcr <= #1 dat_i | 8'h10; // always set master bit + + if (adr_i == 2'b11) + sper <= #1 dat_i; + end + + // write fifo + assign wfwe = wb_acc & (adr_i == 2'b10) & ack_o & we_i; + assign wfov = wfwe & wffull; + + // dat_o + always @(posedge clk_i) + case(adr_i) // synopsys full_case parallel_case + 2'b00: dat_o <= #1 spcr; + 2'b01: dat_o <= #1 spsr; + 2'b10: dat_o <= #1 rfdout; + 2'b11: dat_o <= #1 sper; + endcase + + // read fifo + assign rfre = wb_acc & (adr_i == 2'b10) & ack_o & ~we_i; + + // ack_o + always @(posedge clk_i or negedge rst_i) + if (~rst_i) + ack_o <= #1 1'b0; + else + ack_o <= #1 wb_acc & !ack_o; + + // decode Serial Peripheral Control Register + wire spie = spcr[7]; // Interrupt enable bit + wire spe = spcr[6]; // System Enable bit + wire dwom = spcr[5]; // Port D Wired-OR Mode Bit + wire mstr = spcr[4]; // Master Mode Select Bit + wire cpol = spcr[3]; // Clock Polarity Bit + wire cpha = spcr[2]; // Clock Phase Bit + wire [1:0] spr = spcr[1:0]; // Clock Rate Select Bits + + // decode Serial Peripheral Extension Register + wire [1:0] icnt = sper[7:6]; // interrupt on transfer count + wire [1:0] spre = sper[1:0]; // extended clock rate select + + wire [3:0] espr = {spre, spr}; + + // generate status register + wire wr_spsr = wb_wr & (adr_i == 2'b01); + + reg spif; + always @(posedge clk_i) + if (~spe) + spif <= #1 1'b0; + else + spif <= #1 (tirq | spif) & ~(wr_spsr & dat_i[7]); + + reg wcol; + always @(posedge clk_i) + if (~spe) + wcol <= #1 1'b0; + else + wcol <= #1 (wfov | wcol) & ~(wr_spsr & dat_i[6]); + + assign spsr[7] = spif; + assign spsr[6] = wcol; + assign spsr[5:4] = 2'b00; + assign spsr[3] = wffull; + assign spsr[2] = wfempty; + assign spsr[1] = rffull; + assign spsr[0] = rfempty; + + + // generate IRQ output (inta_o) + always @(posedge clk_i) + inta_o <= #1 spif & spie; + + // + // hookup read/write buffer fifo + fifo4 #(8) + rfifo( + .clk ( clk_i ), + .rst ( rst_i ), + .clr ( ~spe ), + .din ( treg ), + .we ( rfwe ), + .dout ( rfdout ), + .re ( rfre ), + .full ( rffull ), + .empty ( rfempty ) + ), + wfifo( + .clk ( clk_i ), + .rst ( rst_i ), + .clr ( ~spe ), + .din ( dat_i ), + .we ( wfwe ), + .dout ( wfdout ), + .re ( wfre ), + .full ( wffull ), + .empty ( wfempty ) + ); + + // + // generate clk divider + reg [11:0] clkcnt; + always @(posedge clk_i) + if(spe & (|clkcnt & |state)) + clkcnt <= #1 clkcnt - 11'h1; + else + case (espr) // synopsys full_case parallel_case + 4'b0000: clkcnt <= #1 12'h0; // 2 -- original M68HC11 coding + 4'b0001: clkcnt <= #1 12'h1; // 4 -- original M68HC11 coding + 4'b0010: clkcnt <= #1 12'h3; // 16 -- original M68HC11 coding + 4'b0011: clkcnt <= #1 12'hf; // 32 -- original M68HC11 coding + 4'b0100: clkcnt <= #1 12'h1f; // 8 + 4'b0101: clkcnt <= #1 12'h7; // 64 + 4'b0110: clkcnt <= #1 12'h3f; // 128 + 4'b0111: clkcnt <= #1 12'h7f; // 256 + 4'b1000: clkcnt <= #1 12'hff; // 512 + 4'b1001: clkcnt <= #1 12'h1ff; // 1024 + 4'b1010: clkcnt <= #1 12'h3ff; // 2048 + 4'b1011: clkcnt <= #1 12'h7ff; // 4096 + endcase + + // generate clock enable signal + wire ena = ~|clkcnt; + + // transfer statemachine + always @(posedge clk_i) + if (~spe) + begin + state <= #1 2'b00; // idle + bcnt <= #1 3'h0; + treg <= #1 8'h00; + wfre <= #1 1'b0; + rfwe <= #1 1'b0; + sck_o <= #1 1'b0; + end + else + begin + wfre <= #1 1'b0; + rfwe <= #1 1'b0; + + case (state) //synopsys full_case parallel_case + 2'b00: // idle state + begin + bcnt <= #1 3'h7; // set transfer counter + treg <= #1 wfdout; // load transfer register + sck_o <= #1 cpol; // set sck + + if (~wfempty) begin + wfre <= #1 1'b1; + state <= #1 2'b01; + if (cpha) sck_o <= #1 ~sck_o; + end + end + + 2'b01: // clock-phase2, next data + if (ena) begin + sck_o <= #1 ~sck_o; + state <= #1 2'b11; + end + + 2'b11: // clock phase1 + if (ena) begin + treg <= #1 {treg[6:0], miso_i}; + bcnt <= #1 bcnt -3'h1; + + if (~|bcnt) begin + state <= #1 2'b00; + sck_o <= #1 cpol; + rfwe <= #1 1'b1; + end else begin + state <= #1 2'b01; + sck_o <= #1 ~sck_o; + end + end + + 2'b10: state <= #1 2'b00; + endcase + end + + assign mosi_o = treg[7]; + + + // count number of transfers (for interrupt generation) + reg [1:0] tcnt; // transfer count + always @(posedge clk_i) + if (~spe) + tcnt <= #1 icnt; + else if (rfwe) // rfwe gets asserted when all bits have been transfered + if (|tcnt) + tcnt <= #1 tcnt - 2'h1; + else + tcnt <= #1 icnt; + + assign tirq = ~|tcnt & rfwe; + +endmodule + diff --git a/tests/iwls2005/spi/spi_clgen.v b/tests/iwls2005/spi/spi_clgen.v new file mode 100644 index 00000000..7bc4f6e5 --- /dev/null +++ b/tests/iwls2005/spi/spi_clgen.v @@ -0,0 +1,108 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// spi_clgen.v //// +//// //// +//// This file is part of the SPI IP core project //// +//// http://www.opencores.org/projects/spi/ //// +//// //// +//// Author(s): //// +//// - Simon Srot (simons@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +`include "spi_defines.v" +`include "timescale.v" + +module spi_clgen (clk_in, rst, go, enable, last_clk, divider, clk_out, pos_edge, neg_edge); + + parameter Tp = 1; + + input clk_in; // input clock (system clock) + input rst; // reset + input enable; // clock enable + input go; // start transfer + input last_clk; // last clock + input [`SPI_DIVIDER_LEN-1:0] divider; // clock divider (output clock is divided by this value) + output clk_out; // output clock + output pos_edge; // pulse marking positive edge of clk_out + output neg_edge; // pulse marking negative edge of clk_out + + reg clk_out; + reg pos_edge; + reg neg_edge; + + reg [`SPI_DIVIDER_LEN-1:0] cnt; // clock counter + wire cnt_zero; // conter is equal to zero + wire cnt_one; // conter is equal to one + + + assign cnt_zero = cnt == {`SPI_DIVIDER_LEN{1'b0}}; + assign cnt_one = cnt == {{`SPI_DIVIDER_LEN-1{1'b0}}, 1'b1}; + + // Counter counts half period + always @(posedge clk_in or posedge rst) + begin + if(rst) + cnt <= #Tp {`SPI_DIVIDER_LEN{1'b1}}; + else + begin + if(!enable || cnt_zero) + cnt <= #Tp divider; + else + cnt <= #Tp cnt - {{`SPI_DIVIDER_LEN-1{1'b0}}, 1'b1}; + end + end + + // clk_out is asserted every other half period + always @(posedge clk_in or posedge rst) + begin + if(rst) + clk_out <= #Tp 1'b0; + else + clk_out <= #Tp (enable && cnt_zero && (!last_clk || clk_out)) ? ~clk_out : clk_out; + end + + // Pos and neg edge signals + always @(posedge clk_in or posedge rst) + begin + if(rst) + begin + pos_edge <= #Tp 1'b0; + neg_edge <= #Tp 1'b0; + end + else + begin + pos_edge <= #Tp (enable && !clk_out && cnt_one) || (!(|divider) && clk_out) || (!(|divider) && go && !enable); + neg_edge <= #Tp (enable && clk_out && cnt_one) || (!(|divider) && !clk_out && enable); + end + end +endmodule + diff --git a/tests/iwls2005/spi/spi_defines.v b/tests/iwls2005/spi/spi_defines.v new file mode 100644 index 00000000..a6925918 --- /dev/null +++ b/tests/iwls2005/spi/spi_defines.v @@ -0,0 +1,159 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// spi_define.v //// +//// //// +//// This file is part of the SPI IP core project //// +//// http://www.opencores.org/projects/spi/ //// +//// //// +//// Author(s): //// +//// - Simon Srot (simons@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +// +// Number of bits used for devider register. If used in system with +// low frequency of system clock this can be reduced. +// Use SPI_DIVIDER_LEN for fine tuning theexact number. +// +//`define SPI_DIVIDER_LEN_8 +`define SPI_DIVIDER_LEN_16 +//`define SPI_DIVIDER_LEN_24 +//`define SPI_DIVIDER_LEN_32 + +`ifdef SPI_DIVIDER_LEN_8 + `define SPI_DIVIDER_LEN 8 // Can be set from 1 to 8 +`endif +`ifdef SPI_DIVIDER_LEN_16 + `define SPI_DIVIDER_LEN 16 // Can be set from 9 to 16 +`endif +`ifdef SPI_DIVIDER_LEN_24 + `define SPI_DIVIDER_LEN 24 // Can be set from 17 to 24 +`endif +`ifdef SPI_DIVIDER_LEN_32 + `define SPI_DIVIDER_LEN 32 // Can be set from 25 to 32 +`endif + +// +// Maximum nuber of bits that can be send/received at once. +// Use SPI_MAX_CHAR for fine tuning the exact number, when using +// SPI_MAX_CHAR_32, SPI_MAX_CHAR_24, SPI_MAX_CHAR_16, SPI_MAX_CHAR_8. +// +`define SPI_MAX_CHAR_128 +//`define SPI_MAX_CHAR_64 +//`define SPI_MAX_CHAR_32 +//`define SPI_MAX_CHAR_24 +//`define SPI_MAX_CHAR_16 +//`define SPI_MAX_CHAR_8 + +`ifdef SPI_MAX_CHAR_128 + `define SPI_MAX_CHAR 128 // Can only be set to 128 + `define SPI_CHAR_LEN_BITS 7 +`endif +`ifdef SPI_MAX_CHAR_64 + `define SPI_MAX_CHAR 64 // Can only be set to 64 + `define SPI_CHAR_LEN_BITS 6 +`endif +`ifdef SPI_MAX_CHAR_32 + `define SPI_MAX_CHAR 32 // Can be set from 25 to 32 + `define SPI_CHAR_LEN_BITS 5 +`endif +`ifdef SPI_MAX_CHAR_24 + `define SPI_MAX_CHAR 24 // Can be set from 17 to 24 + `define SPI_CHAR_LEN_BITS 5 +`endif +`ifdef SPI_MAX_CHAR_16 + `define SPI_MAX_CHAR 16 // Can be set from 9 to 16 + `define SPI_CHAR_LEN_BITS 4 +`endif +`ifdef SPI_MAX_CHAR_8 + `define SPI_MAX_CHAR 8 // Can be set from 1 to 8 + `define SPI_CHAR_LEN_BITS 3 +`endif + +// +// Number of device select signals. Use SPI_SS_NB for fine tuning the +// exact number. +// +`define SPI_SS_NB_8 +//`define SPI_SS_NB_16 +//`define SPI_SS_NB_24 +//`define SPI_SS_NB_32 + +`ifdef SPI_SS_NB_8 + `define SPI_SS_NB 8 // Can be set from 1 to 8 +`endif +`ifdef SPI_SS_NB_16 + `define SPI_SS_NB 16 // Can be set from 9 to 16 +`endif +`ifdef SPI_SS_NB_24 + `define SPI_SS_NB 24 // Can be set from 17 to 24 +`endif +`ifdef SPI_SS_NB_32 + `define SPI_SS_NB 32 // Can be set from 25 to 32 +`endif + +// +// Bits of WISHBONE address used for partial decoding of SPI registers. +// +`define SPI_OFS_BITS 4:2 + +// +// Register offset +// +`define SPI_RX_0 0 +`define SPI_RX_1 1 +`define SPI_RX_2 2 +`define SPI_RX_3 3 +`define SPI_TX_0 0 +`define SPI_TX_1 1 +`define SPI_TX_2 2 +`define SPI_TX_3 3 +`define SPI_CTRL 4 +`define SPI_DEVIDE 5 +`define SPI_SS 6 + +// +// Number of bits in ctrl register +// +`define SPI_CTRL_BIT_NB 14 + +// +// Control register bit position +// +`define SPI_CTRL_ASS 13 +`define SPI_CTRL_IE 12 +`define SPI_CTRL_LSB 11 +`define SPI_CTRL_TX_NEGEDGE 10 +`define SPI_CTRL_RX_NEGEDGE 9 +`define SPI_CTRL_GO 8 +`define SPI_CTRL_RES_1 7 +`define SPI_CTRL_CHAR_LEN 6:0 + diff --git a/tests/iwls2005/spi/spi_shift.v b/tests/iwls2005/spi/spi_shift.v new file mode 100644 index 00000000..b17ac8b1 --- /dev/null +++ b/tests/iwls2005/spi/spi_shift.v @@ -0,0 +1,238 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// spi_shift.v //// +//// //// +//// This file is part of the SPI IP core project //// +//// http://www.opencores.org/projects/spi/ //// +//// //// +//// Author(s): //// +//// - Simon Srot (simons@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +`include "spi_defines.v" +`include "timescale.v" + +module spi_shift (clk, rst, latch, byte_sel, len, lsb, go, + pos_edge, neg_edge, rx_negedge, tx_negedge, + tip, last, + p_in, p_out, s_clk, s_in, s_out); + + parameter Tp = 1; + + input clk; // system clock + input rst; // reset + input [3:0] latch; // latch signal for storing the data in shift register + input [3:0] byte_sel; // byte select signals for storing the data in shift register + input [`SPI_CHAR_LEN_BITS-1:0] len; // data len in bits (minus one) + input lsb; // lbs first on the line + input go; // start stansfer + input pos_edge; // recognize posedge of sclk + input neg_edge; // recognize negedge of sclk + input rx_negedge; // s_in is sampled on negative edge + input tx_negedge; // s_out is driven on negative edge + output tip; // transfer in progress + output last; // last bit + input [31:0] p_in; // parallel in + output [`SPI_MAX_CHAR-1:0] p_out; // parallel out + input s_clk; // serial clock + input s_in; // serial in + output s_out; // serial out + + reg s_out; + reg tip; + + reg [`SPI_CHAR_LEN_BITS:0] cnt; // data bit count + reg [`SPI_MAX_CHAR-1:0] data; // shift register + wire [`SPI_CHAR_LEN_BITS:0] tx_bit_pos; // next bit position + wire [`SPI_CHAR_LEN_BITS:0] rx_bit_pos; // next bit position + wire rx_clk; // rx clock enable + wire tx_clk; // tx clock enable + + assign p_out = data; + + assign tx_bit_pos = lsb ? {!(|len), len} - cnt : cnt - {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1}; + assign rx_bit_pos = lsb ? {!(|len), len} - (rx_negedge ? cnt + {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1} : cnt) : + (rx_negedge ? cnt : cnt - {{`SPI_CHAR_LEN_BITS{1'b0}},1'b1}); + + assign last = !(|cnt); + + assign rx_clk = (rx_negedge ? neg_edge : pos_edge) && (!last || s_clk); + assign tx_clk = (tx_negedge ? neg_edge : pos_edge) && !last; + + // Character bit counter + always @(posedge clk or posedge rst) + begin + if(rst) + cnt <= #Tp {`SPI_CHAR_LEN_BITS+1{1'b0}}; + else + begin + if(tip) + cnt <= #Tp pos_edge ? (cnt - {{`SPI_CHAR_LEN_BITS{1'b0}}, 1'b1}) : cnt; + else + cnt <= #Tp !(|len) ? {1'b1, {`SPI_CHAR_LEN_BITS{1'b0}}} : {1'b0, len}; + end + end + + // Transfer in progress + always @(posedge clk or posedge rst) + begin + if(rst) + tip <= #Tp 1'b0; + else if(go && ~tip) + tip <= #Tp 1'b1; + else if(tip && last && pos_edge) + tip <= #Tp 1'b0; + end + + // Sending bits to the line + always @(posedge clk or posedge rst) + begin + if (rst) + s_out <= #Tp 1'b0; + else + s_out <= #Tp (tx_clk || !tip) ? data[tx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] : s_out; + end + + // Receiving bits from the line + always @(posedge clk or posedge rst) + begin + if (rst) + data <= #Tp {`SPI_MAX_CHAR{1'b0}}; +`ifdef SPI_MAX_CHAR_128 + else if (latch[0] && !tip) + begin + if (byte_sel[3]) + data[31:24] <= #Tp p_in[31:24]; + if (byte_sel[2]) + data[23:16] <= #Tp p_in[23:16]; + if (byte_sel[1]) + data[15:8] <= #Tp p_in[15:8]; + if (byte_sel[0]) + data[7:0] <= #Tp p_in[7:0]; + end + else if (latch[1] && !tip) + begin + if (byte_sel[3]) + data[63:56] <= #Tp p_in[31:24]; + if (byte_sel[2]) + data[55:48] <= #Tp p_in[23:16]; + if (byte_sel[1]) + data[47:40] <= #Tp p_in[15:8]; + if (byte_sel[0]) + data[39:32] <= #Tp p_in[7:0]; + end + else if (latch[2] && !tip) + begin + if (byte_sel[3]) + data[95:88] <= #Tp p_in[31:24]; + if (byte_sel[2]) + data[87:80] <= #Tp p_in[23:16]; + if (byte_sel[1]) + data[79:72] <= #Tp p_in[15:8]; + if (byte_sel[0]) + data[71:64] <= #Tp p_in[7:0]; + end + else if (latch[3] && !tip) + begin + if (byte_sel[3]) + data[127:120] <= #Tp p_in[31:24]; + if (byte_sel[2]) + data[119:112] <= #Tp p_in[23:16]; + if (byte_sel[1]) + data[111:104] <= #Tp p_in[15:8]; + if (byte_sel[0]) + data[103:96] <= #Tp p_in[7:0]; + end +`else +`ifdef SPI_MAX_CHAR_64 + else if (latch[0] && !tip) + begin + if (byte_sel[3]) + data[31:24] <= #Tp p_in[31:24]; + if (byte_sel[2]) + data[23:16] <= #Tp p_in[23:16]; + if (byte_sel[1]) + data[15:8] <= #Tp p_in[15:8]; + if (byte_sel[0]) + data[7:0] <= #Tp p_in[7:0]; + end + else if (latch[1] && !tip) + begin + if (byte_sel[3]) + data[63:56] <= #Tp p_in[31:24]; + if (byte_sel[2]) + data[55:48] <= #Tp p_in[23:16]; + if (byte_sel[1]) + data[47:40] <= #Tp p_in[15:8]; + if (byte_sel[0]) + data[39:32] <= #Tp p_in[7:0]; + end +`else + else if (latch[0] && !tip) + begin + `ifdef SPI_MAX_CHAR_8 + if (byte_sel[0]) + data[`SPI_MAX_CHAR-1:0] <= #Tp p_in[`SPI_MAX_CHAR-1:0]; + `endif + `ifdef SPI_MAX_CHAR_16 + if (byte_sel[0]) + data[7:0] <= #Tp p_in[7:0]; + if (byte_sel[1]) + data[`SPI_MAX_CHAR-1:8] <= #Tp p_in[`SPI_MAX_CHAR-1:8]; + `endif + `ifdef SPI_MAX_CHAR_24 + if (byte_sel[0]) + data[7:0] <= #Tp p_in[7:0]; + if (byte_sel[1]) + data[15:8] <= #Tp p_in[15:8]; + if (byte_sel[2]) + data[`SPI_MAX_CHAR-1:16] <= #Tp p_in[`SPI_MAX_CHAR-1:16]; + `endif + `ifdef SPI_MAX_CHAR_32 + if (byte_sel[0]) + data[7:0] <= #Tp p_in[7:0]; + if (byte_sel[1]) + data[15:8] <= #Tp p_in[15:8]; + if (byte_sel[2]) + data[23:16] <= #Tp p_in[23:16]; + if (byte_sel[3]) + data[`SPI_MAX_CHAR-1:24] <= #Tp p_in[`SPI_MAX_CHAR-1:24]; + `endif + end +`endif +`endif + else + data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]] <= #Tp rx_clk ? s_in : data[rx_bit_pos[`SPI_CHAR_LEN_BITS-1:0]]; + end + +endmodule + diff --git a/tests/iwls2005/spi/spi_top.v b/tests/iwls2005/spi/spi_top.v new file mode 100644 index 00000000..09b2e50e --- /dev/null +++ b/tests/iwls2005/spi/spi_top.v @@ -0,0 +1,287 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// spi_top.v //// +//// //// +//// This file is part of the SPI IP core project //// +//// http://www.opencores.org/projects/spi/ //// +//// //// +//// Author(s): //// +//// - Simon Srot (simons@opencores.org) //// +//// //// +//// All additional information is avaliable in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + + +`include "spi_defines.v" +`include "timescale.v" + +module spi_top +( + // Wishbone signals + wb_clk_i, wb_rst_i, wb_adr_i, wb_dat_i, wb_dat_o, wb_sel_i, + wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_err_o, wb_int_o, + + // SPI signals + ss_pad_o, sclk_pad_o, mosi_pad_o, miso_pad_i +); + + parameter Tp = 1; + + // Wishbone signals + input wb_clk_i; // master clock input + input wb_rst_i; // synchronous active high reset + input [4:0] wb_adr_i; // lower address bits + input [32-1:0] wb_dat_i; // databus input + output [32-1:0] wb_dat_o; // databus output + input [3:0] wb_sel_i; // byte select inputs + input wb_we_i; // write enable input + input wb_stb_i; // stobe/core select signal + input wb_cyc_i; // valid bus cycle input + output wb_ack_o; // bus cycle acknowledge output + output wb_err_o; // termination w/ error + output wb_int_o; // interrupt request signal output + + // SPI signals + output [`SPI_SS_NB-1:0] ss_pad_o; // slave select + output sclk_pad_o; // serial clock + output mosi_pad_o; // master out slave in + input miso_pad_i; // master in slave out + + reg [32-1:0] wb_dat_o; + reg wb_ack_o; + reg wb_int_o; + + // Internal signals + reg [`SPI_DIVIDER_LEN-1:0] divider; // Divider register + reg [`SPI_CTRL_BIT_NB-1:0] ctrl; // Control and status register + reg [`SPI_SS_NB-1:0] ss; // Slave select register + reg [32-1:0] wb_dat; // wb data out + wire [`SPI_MAX_CHAR-1:0] rx; // Rx register + wire rx_negedge; // miso is sampled on negative edge + wire tx_negedge; // mosi is driven on negative edge + wire [`SPI_CHAR_LEN_BITS-1:0] char_len; // char len + wire go; // go + wire lsb; // lsb first on line + wire ie; // interrupt enable + wire ass; // automatic slave select + wire spi_divider_sel; // divider register select + wire spi_ctrl_sel; // ctrl register select + wire [3:0] spi_tx_sel; // tx_l register select + wire spi_ss_sel; // ss register select + wire tip; // transfer in progress + wire pos_edge; // recognize posedge of sclk + wire neg_edge; // recognize negedge of sclk + wire last_bit; // marks last character bit + + // Address decoder + assign spi_divider_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_DEVIDE); + assign spi_ctrl_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_CTRL); + assign spi_tx_sel[0] = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX_0); + assign spi_tx_sel[1] = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX_1); + assign spi_tx_sel[2] = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX_2); + assign spi_tx_sel[3] = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_TX_3); + assign spi_ss_sel = wb_cyc_i & wb_stb_i & (wb_adr_i[`SPI_OFS_BITS] == `SPI_SS); + + // Read from registers + always @(wb_adr_i or rx or ctrl or divider or ss) + begin + case (wb_adr_i[`SPI_OFS_BITS]) +`ifdef SPI_MAX_CHAR_128 + `SPI_RX_0: wb_dat = rx[31:0]; + `SPI_RX_1: wb_dat = rx[63:32]; + `SPI_RX_2: wb_dat = rx[95:64]; + `SPI_RX_3: wb_dat = {{128-`SPI_MAX_CHAR{1'b0}}, rx[`SPI_MAX_CHAR-1:96]}; +`else +`ifdef SPI_MAX_CHAR_64 + `SPI_RX_0: wb_dat = rx[31:0]; + `SPI_RX_1: wb_dat = {{64-`SPI_MAX_CHAR{1'b0}}, rx[`SPI_MAX_CHAR-1:32]}; + `SPI_RX_2: wb_dat = 32'b0; + `SPI_RX_3: wb_dat = 32'b0; +`else + `SPI_RX_0: wb_dat = {{32-`SPI_MAX_CHAR{1'b0}}, rx[`SPI_MAX_CHAR-1:0]}; + `SPI_RX_1: wb_dat = 32'b0; + `SPI_RX_2: wb_dat = 32'b0; + `SPI_RX_3: wb_dat = 32'b0; +`endif +`endif + `SPI_CTRL: wb_dat = {{32-`SPI_CTRL_BIT_NB{1'b0}}, ctrl}; + `SPI_DEVIDE: wb_dat = {{32-`SPI_DIVIDER_LEN{1'b0}}, divider}; + `SPI_SS: wb_dat = {{32-`SPI_SS_NB{1'b0}}, ss}; + default: wb_dat = 32'bx; + endcase + end + + // Wb data out + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + wb_dat_o <= #Tp 32'b0; + else + wb_dat_o <= #Tp wb_dat; + end + + // Wb acknowledge + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + wb_ack_o <= #Tp 1'b0; + else + wb_ack_o <= #Tp wb_cyc_i & wb_stb_i & ~wb_ack_o; + end + + // Wb error + assign wb_err_o = 1'b0; + + // Interrupt + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + wb_int_o <= #Tp 1'b0; + else if (ie && tip && last_bit && pos_edge) + wb_int_o <= #Tp 1'b1; + else if (wb_ack_o) + wb_int_o <= #Tp 1'b0; + end + + // Divider register + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + divider <= #Tp {`SPI_DIVIDER_LEN{1'b0}}; + else if (spi_divider_sel && wb_we_i && !tip) + begin + `ifdef SPI_DIVIDER_LEN_8 + if (wb_sel_i[0]) + divider <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:0]; + `endif + `ifdef SPI_DIVIDER_LEN_16 + if (wb_sel_i[0]) + divider[7:0] <= #Tp wb_dat_i[7:0]; + if (wb_sel_i[1]) + divider[`SPI_DIVIDER_LEN-1:8] <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:8]; + `endif + `ifdef SPI_DIVIDER_LEN_24 + if (wb_sel_i[0]) + divider[7:0] <= #Tp wb_dat_i[7:0]; + if (wb_sel_i[1]) + divider[15:8] <= #Tp wb_dat_i[15:8]; + if (wb_sel_i[2]) + divider[`SPI_DIVIDER_LEN-1:16] <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:16]; + `endif + `ifdef SPI_DIVIDER_LEN_32 + if (wb_sel_i[0]) + divider[7:0] <= #Tp wb_dat_i[7:0]; + if (wb_sel_i[1]) + divider[15:8] <= #Tp wb_dat_i[15:8]; + if (wb_sel_i[2]) + divider[23:16] <= #Tp wb_dat_i[23:16]; + if (wb_sel_i[3]) + divider[`SPI_DIVIDER_LEN-1:24] <= #Tp wb_dat_i[`SPI_DIVIDER_LEN-1:24]; + `endif + end + end + + // Ctrl register + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + ctrl <= #Tp {`SPI_CTRL_BIT_NB{1'b0}}; + else if(spi_ctrl_sel && wb_we_i && !tip) + begin + if (wb_sel_i[0]) + ctrl[7:0] <= #Tp wb_dat_i[7:0] | {7'b0, ctrl[0]}; + if (wb_sel_i[1]) + ctrl[`SPI_CTRL_BIT_NB-1:8] <= #Tp wb_dat_i[`SPI_CTRL_BIT_NB-1:8]; + end + else if(tip && last_bit && pos_edge) + ctrl[`SPI_CTRL_GO] <= #Tp 1'b0; + end + + assign rx_negedge = ctrl[`SPI_CTRL_RX_NEGEDGE]; + assign tx_negedge = ctrl[`SPI_CTRL_TX_NEGEDGE]; + assign go = ctrl[`SPI_CTRL_GO]; + assign char_len = ctrl[`SPI_CTRL_CHAR_LEN]; + assign lsb = ctrl[`SPI_CTRL_LSB]; + assign ie = ctrl[`SPI_CTRL_IE]; + assign ass = ctrl[`SPI_CTRL_ASS]; + + // Slave select register + always @(posedge wb_clk_i or posedge wb_rst_i) + begin + if (wb_rst_i) + ss <= #Tp {`SPI_SS_NB{1'b0}}; + else if(spi_ss_sel && wb_we_i && !tip) + begin + `ifdef SPI_SS_NB_8 + if (wb_sel_i[0]) + ss <= #Tp wb_dat_i[`SPI_SS_NB-1:0]; + `endif + `ifdef SPI_SS_NB_16 + if (wb_sel_i[0]) + ss[7:0] <= #Tp wb_dat_i[7:0]; + if (wb_sel_i[1]) + ss[`SPI_SS_NB-1:8] <= #Tp wb_dat_i[`SPI_SS_NB-1:8]; + `endif + `ifdef SPI_SS_NB_24 + if (wb_sel_i[0]) + ss[7:0] <= #Tp wb_dat_i[7:0]; + if (wb_sel_i[1]) + ss[15:8] <= #Tp wb_dat_i[15:8]; + if (wb_sel_i[2]) + ss[`SPI_SS_NB-1:16] <= #Tp wb_dat_i[`SPI_SS_NB-1:16]; + `endif + `ifdef SPI_SS_NB_32 + if (wb_sel_i[0]) + ss[7:0] <= #Tp wb_dat_i[7:0]; + if (wb_sel_i[1]) + ss[15:8] <= #Tp wb_dat_i[15:8]; + if (wb_sel_i[2]) + ss[23:16] <= #Tp wb_dat_i[23:16]; + if (wb_sel_i[3]) + ss[`SPI_SS_NB-1:24] <= #Tp wb_dat_i[`SPI_SS_NB-1:24]; + `endif + end + end + + assign ss_pad_o = ~((ss & {`SPI_SS_NB{tip & ass}}) | (ss & {`SPI_SS_NB{!ass}})); + + spi_clgen clgen (.clk_in(wb_clk_i), .rst(wb_rst_i), .go(go), .enable(tip), .last_clk(last_bit), + .divider(divider), .clk_out(sclk_pad_o), .pos_edge(pos_edge), + .neg_edge(neg_edge)); + + spi_shift shift (.clk(wb_clk_i), .rst(wb_rst_i), .len(char_len[`SPI_CHAR_LEN_BITS-1:0]), + .latch(spi_tx_sel[3:0] & {4{wb_we_i}}), .byte_sel(wb_sel_i), .lsb(lsb), + .go(go), .pos_edge(pos_edge), .neg_edge(neg_edge), + .rx_negedge(rx_negedge), .tx_negedge(tx_negedge), + .tip(tip), .last(last_bit), + .p_in(wb_dat_i), .p_out(rx), + .s_clk(sclk_pad_o), .s_in(miso_pad_i), .s_out(mosi_pad_o)); +endmodule + diff --git a/tests/iwls2005/spi/timescale.v b/tests/iwls2005/spi/timescale.v new file mode 100644 index 00000000..60d4ecbd --- /dev/null +++ b/tests/iwls2005/spi/timescale.v @@ -0,0 +1,2 @@ +`timescale 1ns / 10ps + diff --git a/tests/iwls2005/ss_pcm/pcm_slv_top.v b/tests/iwls2005/ss_pcm/pcm_slv_top.v new file mode 100644 index 00000000..2548d35f --- /dev/null +++ b/tests/iwls2005/ss_pcm/pcm_slv_top.v @@ -0,0 +1,222 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// PCM IO Slave Module //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ss_pcm/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: pcm_slv_top.v,v 1.2 2002/09/17 15:32:50 rudi Exp $ +// +// $Date: 2002/09/17 15:32:50 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: pcm_slv_top.v,v $ +// Revision 1.2 2002/09/17 15:32:50 rudi +// *** empty log message *** +// +// Revision 1.1.1.1 2002/09/17 15:17:25 rudi +// Initial Checkin +// +// +// +// +// +// +// +// + +`include "timescale.v" + +/* +PCM Interface +=============================== +PCM_CLK +PCM_SYNC +PCM_DIN +PCM_DOUT +*/ + +module pcm_slv_top( clk, rst, + + ssel, + + // PCM + pcm_clk_i, pcm_sync_i, pcm_din_i, pcm_dout_o, + + // Internal Interface + din_i, dout_o, re_i, we_i); + +input clk, rst; +input [2:0] ssel; // Number of bits to delay (0-7) +input pcm_clk_i, pcm_sync_i, pcm_din_i; +output pcm_dout_o; +input [7:0] din_i; +output [7:0] dout_o; +input re_i; +input [1:0] we_i; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +reg pclk_t, pclk_s, pclk_r; +wire pclk_ris, pclk_fal; +reg psync; +reg pcm_sync_r1, pcm_sync_r2, pcm_sync_r3; +reg tx_go; +wire tx_data_le; +reg [15:0] tx_hold_reg; +reg [7:0] tx_hold_byte_h, tx_hold_byte_l; +reg [3:0] tx_cnt; +wire tx_done; +reg [15:0] rx_hold_reg, rx_reg; +wire rx_data_le; +reg rxd_t, rxd; +reg tx_go_r1, tx_go_r2; +reg [7:0] psa; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk) + pclk_t <= #1 pcm_clk_i; + +always @(posedge clk) + pclk_s <= #1 pclk_t; + +always @(posedge clk) + pclk_r <= #1 pclk_s; + +assign pclk_ris = !pclk_r & pclk_s; +assign pclk_fal = pclk_r & !pclk_s; + +/////////////////////////////////////////////////////////////////// +// +// Retrieve Sync Signal +// + +always @(posedge clk) // Latch it at falling edge + if(pclk_fal) pcm_sync_r1 <= #1 pcm_sync_i; + +always @(posedge clk) // resync to rising edge + if(pclk_ris) psa <= #1 {psa[6:0], pcm_sync_r1}; + +always @(posedge clk) //delay bit N + pcm_sync_r2 <= #1 psa[ssel]; + +always @(posedge clk) // edge detector + pcm_sync_r3 <= #1 pcm_sync_r2; + +always @(posedge clk) + psync <= #1 !pcm_sync_r3 & pcm_sync_r2; + +/////////////////////////////////////////////////////////////////// +// +// Transmit Logic +// + +assign tx_data_le = tx_go & pclk_ris; + +always @(posedge clk) + if(we_i[1]) tx_hold_byte_h <= #1 din_i; + +always @(posedge clk) + if(we_i[0]) tx_hold_byte_l <= #1 din_i; + +always @(posedge clk) + if(!rst) tx_go <= #1 1'b0; + else + if(psync) tx_go <= #1 1'b1; + else + if(tx_done) tx_go <= #1 1'b0; + +always @(posedge clk) + if(!rst) tx_hold_reg <= #1 16'h0; + else + if(psync) tx_hold_reg <= #1 {tx_hold_byte_h, tx_hold_byte_l}; + else + if(tx_data_le) tx_hold_reg <= #1 {tx_hold_reg[14:0],1'b0}; + +assign pcm_dout_o = tx_hold_reg[15]; + +always @(posedge clk) + if(!rst) tx_cnt <= #1 4'h0; + else + if(tx_data_le) tx_cnt <= tx_cnt + 4'h1; + +assign tx_done = (tx_cnt == 4'hf) & tx_data_le; + +/////////////////////////////////////////////////////////////////// +// +// Recieve Logic +// + +always @(posedge clk) + if(pclk_ris) tx_go_r1 <= #1 tx_go; + +always @(posedge clk) + if(pclk_ris) tx_go_r2 <= #1 tx_go_r1; + +// Receive is in sync with transmit ... +always @(posedge clk) + if(pclk_fal) rxd_t <= #1 pcm_din_i; + +always @(posedge clk) + rxd <= #1 rxd_t; + +assign rx_data_le = (tx_go_r1 | tx_go) & pclk_fal; + +always @(posedge clk) + if(!rst) rx_hold_reg <= #1 16'h0; + else + if(rx_data_le) rx_hold_reg <= #1 {rx_hold_reg[14:0], rxd}; + +always @(posedge clk) + if(!rst) rx_reg <= #1 16'h0; + else + if(tx_go_r1 & !tx_go & pclk_ris) rx_reg <= #1 rx_hold_reg; + +assign dout_o = re_i ? rx_reg[15:8] : rx_reg[7:0]; + +endmodule + diff --git a/tests/iwls2005/ss_pcm/timescale.v b/tests/iwls2005/ss_pcm/timescale.v new file mode 100644 index 00000000..ff9e265a --- /dev/null +++ b/tests/iwls2005/ss_pcm/timescale.v @@ -0,0 +1 @@ +`timescale 1ns / 10ps diff --git a/tests/iwls2005/systemcaes/aes.v b/tests/iwls2005/systemcaes/aes.v new file mode 100644 index 00000000..e5021ed1 --- /dev/null +++ b/tests/iwls2005/systemcaes/aes.v @@ -0,0 +1,358 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// AES top file //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// AES top //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: aes.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + +module aes(clk,reset,load_i,decrypt_i,data_i,key_i,ready_o,data_o); +input clk; +input reset; +input load_i; +input decrypt_i; +input [127:0] data_i; +input [127:0] key_i; +output ready_o; +output [127:0] data_o; + +reg ready_o; +reg [127:0] data_o; + +reg next_ready_o; +reg keysched_start_i; +reg [3:0] keysched_round_i; +reg [127:0] keysched_last_key_i; +wire [127:0] keysched_new_key_o; + +wire keysched_ready_o; + +wire keysched_sbox_access_o; + +wire [7:0] keysched_sbox_data_o; + +wire keysched_sbox_decrypt_o; + +reg mixcol_start_i; +reg [127:0] mixcol_data_i; +wire mixcol_ready_o; + +wire [127:0] mixcol_data_o; + +reg subbytes_start_i; +reg [127:0] subbytes_data_i; +wire subbytes_ready_o; + +wire [127:0] subbytes_data_o; + +wire [7:0] subbytes_sbox_data_o; + +wire subbytes_sbox_decrypt_o; + +wire [7:0] sbox_data_o; + +reg [7:0] sbox_data_i; +reg sbox_decrypt_i; +reg state; +reg next_state; +reg [3:0] round; +reg [3:0] next_round; +reg [127:0] addroundkey_data_o; +reg [127:0] next_addroundkey_data_reg; +reg [127:0] addroundkey_data_reg; +reg [127:0] addroundkey_data_i; +reg addroundkey_ready_o; +reg next_addroundkey_ready_o; +reg addroundkey_start_i; +reg next_addroundkey_start_i; +reg [3:0] addroundkey_round; +reg [3:0] next_addroundkey_round; +reg first_round_reg; +reg next_first_round_reg; + +sbox sbox1 (.clk(clk), .reset(reset), .data_i(sbox_data_i), .decrypt_i(sbox_decrypt_i), .data_o(sbox_data_o)); +subbytes sub1 (.clk(clk), .reset(reset), .start_i(subbytes_start_i), .decrypt_i(decrypt_i), .data_i(subbytes_data_i), .ready_o(subbytes_ready_o), .data_o(subbytes_data_o), .sbox_data_o(subbytes_sbox_data_o), .sbox_data_i(sbox_data_o), .sbox_decrypt_o(subbytes_sbox_decrypt_o)); +mixcolum mix1 (.clk(clk), .reset(reset), .decrypt_i(decrypt_i), .start_i(mixcol_start_i), .data_i(mixcol_data_i), .ready_o(mixcol_ready_o), .data_o(mixcol_data_o)); +keysched ks1 (.clk(clk), .reset(reset), .start_i(keysched_start_i), .round_i(keysched_round_i), .last_key_i(keysched_last_key_i), .new_key_o(keysched_new_key_o), .ready_o(keysched_ready_o), .sbox_access_o(keysched_sbox_access_o), .sbox_data_o(keysched_sbox_data_o), .sbox_data_i(sbox_data_o), .sbox_decrypt_o(keysched_sbox_decrypt_o)); + +//registers: +always @(posedge clk or negedge reset) + +begin + + if(!reset) +begin + + state = (0); + ready_o = (0); + round = (0); + addroundkey_round = (0); + addroundkey_data_reg = (0); + addroundkey_ready_o = (0); + addroundkey_start_i = (0); + first_round_reg = (0); + +end +else +begin + + state = (next_state); + ready_o = (next_ready_o); + round = (next_round); + addroundkey_round = (next_addroundkey_round); + addroundkey_data_reg = (next_addroundkey_data_reg); + addroundkey_ready_o = (next_addroundkey_ready_o); + first_round_reg = (next_first_round_reg); + addroundkey_start_i = (next_addroundkey_start_i); + +end + + +end +//control: +always @( state or round or addroundkey_data_o or data_i or load_i or decrypt_i or addroundkey_ready_o or mixcol_ready_o or subbytes_ready_o or subbytes_data_o or mixcol_data_o or first_round_reg) + +begin + + + next_state = (state); + next_round = (round); + data_o = (addroundkey_data_o); + next_ready_o = (0); + + //Tokeyschedulemodule + + next_first_round_reg = (0); + + + subbytes_data_i = (0); + mixcol_data_i = (0); + addroundkey_data_i = (0); + next_addroundkey_start_i = (first_round_reg); + mixcol_start_i = ((addroundkey_ready_o&decrypt_i&round!=10)|(subbytes_ready_o&!decrypt_i)); + subbytes_start_i = ((addroundkey_ready_o&!decrypt_i)|(mixcol_ready_o&decrypt_i)|(addroundkey_ready_o&decrypt_i&round==10)); + + if(decrypt_i&&round!=10) + begin + addroundkey_data_i = (subbytes_data_o); + subbytes_data_i = (mixcol_data_o); + mixcol_data_i = (addroundkey_data_o); + end + else if(!decrypt_i&&round!=0) + begin + addroundkey_data_i = (mixcol_data_o); + subbytes_data_i = (addroundkey_data_o); + mixcol_data_i = (subbytes_data_o); + end + else + begin + mixcol_data_i = (subbytes_data_o); + subbytes_data_i = (addroundkey_data_o); + addroundkey_data_i = (data_i); + end + + + case(state) + + 0: + begin + if(load_i) + begin + next_state = (1); + if(decrypt_i) + next_round = (10); + else + next_round = (0); + next_first_round_reg = (1); + end + end + + 1: + begin + + //Counter + if(!decrypt_i&&mixcol_ready_o) + begin + next_addroundkey_start_i = (1); + addroundkey_data_i = (mixcol_data_o); + next_round = (round+1); + end + else if(decrypt_i&&subbytes_ready_o) + begin + next_addroundkey_start_i = (1); + addroundkey_data_i = (subbytes_data_o); + next_round = (round-1); + end + + //Output + if((round==9&&!decrypt_i)||(round==0&&decrypt_i)) + begin + next_addroundkey_start_i = (0); + mixcol_start_i = (0); + if(subbytes_ready_o) + begin + addroundkey_data_i = (subbytes_data_o); + next_addroundkey_start_i = (1); + next_round = (round+1); + end + end + + if((round==10&&!decrypt_i)||(round==0&&decrypt_i)) + begin + addroundkey_data_i = (subbytes_data_o); + subbytes_start_i = (0); + if(addroundkey_ready_o) + begin + next_ready_o = (1); + next_state = (0); + next_addroundkey_start_i = (0); + next_round = (0); + end + + end + + + end + + default: +begin + next_state = (0); + end + endcase + + +end +//addroundkey: +reg[127:0] data_var,round_data_var,round_key_var; +always @( addroundkey_data_i or addroundkey_start_i or addroundkey_data_reg or addroundkey_round or keysched_new_key_o or keysched_ready_o or key_i or round) + +begin + + + + round_data_var=addroundkey_data_reg; + next_addroundkey_data_reg = (addroundkey_data_reg); +next_addroundkey_ready_o = (0); + next_addroundkey_round = (addroundkey_round); + addroundkey_data_o = (addroundkey_data_reg); + + if(addroundkey_round==1||addroundkey_round==0) + keysched_last_key_i = (key_i); +else + keysched_last_key_i = (keysched_new_key_o); + + keysched_start_i = (0); + + keysched_round_i = (addroundkey_round); + + if(round==0&&addroundkey_start_i) +begin + + //Taketheinputandxorthemwithdataifround==0; + data_var=addroundkey_data_i; + round_key_var=key_i; + round_data_var=round_key_var^data_var; + next_addroundkey_data_reg = (round_data_var); +next_addroundkey_ready_o = (1); + +end +else if(addroundkey_start_i&&round!=0) +begin + + keysched_last_key_i = (key_i); + keysched_start_i = (1); + keysched_round_i = (1); + next_addroundkey_round = (1); + +end +else if(addroundkey_round!=round&&keysched_ready_o) +begin + +next_addroundkey_round = (addroundkey_round+1); + keysched_last_key_i = (keysched_new_key_o); + keysched_start_i = (1); + keysched_round_i = (addroundkey_round+1); + +end +else if(addroundkey_round==round&&keysched_ready_o) +begin + + data_var=addroundkey_data_i; + round_key_var=keysched_new_key_o; + round_data_var=round_key_var^data_var; + next_addroundkey_data_reg = (round_data_var); +next_addroundkey_ready_o = (1); + next_addroundkey_round = (0); + +end + + +end +//sbox_muxes: +always @( keysched_sbox_access_o or keysched_sbox_decrypt_o or keysched_sbox_data_o or subbytes_sbox_decrypt_o or subbytes_sbox_data_o) + +begin + + + if(keysched_sbox_access_o) +begin + + sbox_decrypt_i = (keysched_sbox_decrypt_o); + sbox_data_i = (keysched_sbox_data_o); + +end +else +begin + + sbox_decrypt_i = (subbytes_sbox_decrypt_o); +sbox_data_i = (subbytes_sbox_data_o); + +end + + +end + +endmodule diff --git a/tests/iwls2005/systemcaes/byte_mixcolum.v b/tests/iwls2005/systemcaes/byte_mixcolum.v new file mode 100644 index 00000000..b248cc40 --- /dev/null +++ b/tests/iwls2005/systemcaes/byte_mixcolum.v @@ -0,0 +1,92 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Mixcolumns for 8 bit //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// Mixcolum for a byte //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: byte_mixcolum.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + +module byte_mixcolum(a,b,c,d,outx,outy); + +input [7:0] a,b,c,d; +output [7:0] outx, outy; + +reg [7:0] outx, outy; + +function [7:0] xtime; +input [7:0] in; +reg [3:0] xtime_t; + +begin +xtime[7:5] = in[6:4]; +xtime_t[3] = in[7]; +xtime_t[2] = in[7]; +xtime_t[1] = 0; +xtime_t[0] = in[7]; +xtime[4:1] =xtime_t^in[3:0]; +xtime[0] = in[7]; +end +endfunction + +reg [7:0] w1,w2,w3,w4,w5,w6,w7,w8,outx_var; +always @ (a, b, c, d) +begin +w1 = a ^b; +w2 = a ^c; +w3 = c ^d; +w4 = xtime(w1); +w5 = xtime(w3); +w6 = w2 ^w4 ^w5; +w7 = xtime(w6); +w8 = xtime(w7); + +outx_var = b^w3^w4; +outx=outx_var; +outy=w8^outx_var; + +end + +endmodule diff --git a/tests/iwls2005/systemcaes/keysched.v b/tests/iwls2005/systemcaes/keysched.v new file mode 100644 index 00000000..f242c567 --- /dev/null +++ b/tests/iwls2005/systemcaes/keysched.v @@ -0,0 +1,248 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Key schedule //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// Generate the next round key from the previous one //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: keysched.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + +module keysched(clk,reset,start_i,round_i,last_key_i,new_key_o,ready_o,sbox_access_o,sbox_data_o,sbox_data_i,sbox_decrypt_o); +input clk; +input reset; +input start_i; +input [3:0] round_i; +input [127:0] last_key_i; +output [127:0] new_key_o; +output ready_o; +output sbox_access_o; +output [7:0] sbox_data_o; +input [7:0] sbox_data_i; +output sbox_decrypt_o; + +reg [127:0] new_key_o; +reg ready_o; +reg sbox_access_o; +reg [7:0] sbox_data_o; +reg sbox_decrypt_o; + +reg [2:0] next_state; +reg [2:0] state; +reg [7:0] rcon_o; +reg [31:0] next_col; +reg [31:0] col; +reg [127:0] key_reg; +reg [127:0] next_key_reg; +reg next_ready_o; + + +//rcon: +always @( round_i) + +begin + + + case(round_i) + 1: +begin +rcon_o = (1); +end + 2: +begin +rcon_o = (2); +end + 3: +begin +rcon_o = (4); +end + 4: +begin +rcon_o = (8); +end + 5: +begin +rcon_o = ('h10); +end + 6: +begin +rcon_o = ('h20); +end + 7: +begin +rcon_o = ('h40); +end + 8: +begin +rcon_o = ('h80); +end + 9: +begin +rcon_o = ('h1B); +end + 10: +begin +rcon_o = ('h36); +end +default: +begin + rcon_o = (0); +end + endcase + + +end +//registers: +always @(posedge clk or negedge reset) + +begin + + if(!reset) + begin + state = (0); + col = (0); + key_reg = (0); + ready_o = (0); + end +else + begin + state = (next_state); + col = (next_col); + key_reg = (next_key_reg); + ready_o = (next_ready_o); + end + + +end +//generate_key: +reg[127:0] K_var,W_var; + reg[31:0] col_t; + reg[23:0] zero; + +always @( start_i or last_key_i or sbox_data_i or state or rcon_o or col or key_reg) + +begin + + + zero=0; + + col_t=col; + W_var=0; + + next_state = (state); + next_col = (col); + + next_ready_o = (0); + next_key_reg = (key_reg); + new_key_o = (key_reg); + +sbox_decrypt_o = (0); + sbox_access_o = (0); + sbox_data_o = (0); + K_var=last_key_i; + + case(state) + //Substitutethebyteswhilerotatingthem + //FouraccessestoSBoxareneeded + 0: +begin + if(start_i) +begin + + col_t=0; + sbox_access_o = (1); + sbox_data_o = (K_var[31:24]); + next_state = (1); + +end + + end + 1: +begin + sbox_access_o = (1); + sbox_data_o = (K_var[23:16]); + col_t[7:0]=sbox_data_i; + next_col = (col_t); + next_state = (2); + end + 2: +begin + sbox_access_o = (1); + sbox_data_o = (K_var[15:8]); + col_t[31:24]=sbox_data_i; + next_col = (col_t); + next_state = (3); + end + 3: +begin + sbox_access_o = (1); + sbox_data_o = (K_var[7:0]); + col_t[23:16]=sbox_data_i; + next_col = (col_t); + next_state = (4); + end + 4: +begin + sbox_access_o = (1); + col_t[15:8]=sbox_data_i; + next_col = (col_t); + W_var[127:96]=col_t^K_var[127:96]^{rcon_o,zero}; + W_var[95:64]=W_var[127:96]^K_var[95:64]; + W_var[63:32]=W_var[95:64]^K_var[63:32]; + W_var[31:0]=W_var[63:32]^K_var[31:0]; +next_ready_o = (1); +next_key_reg = (W_var); + next_state = (0); + end + +default: +begin + next_state = (0); + end +endcase + + +end + +endmodule diff --git a/tests/iwls2005/systemcaes/mixcolum.v b/tests/iwls2005/systemcaes/mixcolum.v new file mode 100644 index 00000000..ab6dc1e6 --- /dev/null +++ b/tests/iwls2005/systemcaes/mixcolum.v @@ -0,0 +1,188 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Mixcolumns module implementation //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// Mixcolum module //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: mixcolum.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + + +module mixcolum(clk,reset,decrypt_i,start_i,data_i,ready_o,data_o); +input clk; +input reset; +input decrypt_i; +input start_i; +input [127:0] data_i; +output ready_o; +output [127:0] data_o; + +reg ready_o; +reg [127:0] data_o; + +reg [127:0] data_reg; +reg [127:0] next_data_reg; +reg [127:0] data_o_reg; +reg [127:0] next_data_o; +reg next_ready_o; +reg [1:0] state; +reg [1:0] next_state; +wire [31:0] outx; + +wire [31:0] outy; + +reg [31:0] mix_word; +reg [31:0] outmux; + +word_mixcolum w1 (.in(mix_word), .outx(outx), .outy(outy)); + +//assign_data_o: +always @( data_o_reg) + +begin + + data_o = (data_o_reg); + +end +//mux: +always @( outx or outy or decrypt_i) + +begin + + outmux = (decrypt_i?outy:outx); + +end +//registers: +always @(posedge clk or negedge reset) + +begin + +if(!reset) + begin + data_reg = (0); + state = (0); + ready_o = (0); + data_o_reg = (0); + end +else + begin + data_reg = (next_data_reg); + state = (next_state); + ready_o = (next_ready_o); + data_o_reg = (next_data_o); + end + + +end +//mixcol: +reg[127:0] data_i_var; + reg[31:0] aux; + reg[127:0] data_reg_var; + +always @( decrypt_i or start_i or state or data_reg or outmux or data_o_reg or data_i) + +begin + + + data_i_var=data_i; + data_reg_var=data_reg; + next_data_reg = (data_reg); + next_state = (state); + + mix_word = (0); + + next_ready_o = (0); + next_data_o = (data_o_reg); + + case(state) + + 0: +begin + if(start_i) +begin + + aux=data_i_var[127:96]; + mix_word = (aux); + data_reg_var[127:96]=outmux; + next_data_reg = (data_reg_var); + next_state = (1); + +end + + end + 1: +begin + aux=data_i_var[95:64]; + mix_word = (aux); + data_reg_var[95:64]=outmux; + next_data_reg = (data_reg_var); + next_state = (2); + end + 2: +begin + aux=data_i_var[63:32]; + mix_word = (aux); + data_reg_var[63:32]=outmux; + next_data_reg = (data_reg_var); + next_state = (3); + end + 3: +begin + aux=data_i_var[31:0]; + mix_word = (aux); + data_reg_var[31:0]=outmux; + next_data_o = (data_reg_var); + next_ready_o = (1); + next_state = (0); + end + default: + begin + end + endcase + + +end + +endmodule diff --git a/tests/iwls2005/systemcaes/sbox.v b/tests/iwls2005/systemcaes/sbox.v new file mode 100644 index 00000000..b5f741c3 --- /dev/null +++ b/tests/iwls2005/systemcaes/sbox.v @@ -0,0 +1,392 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// S-Box calculation //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// S-box calculation calculating inverse on gallois field //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: sbox.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + +module sbox(clk,reset,data_i,decrypt_i,data_o); +input clk; +input reset; +input [7:0] data_i; +input decrypt_i; +output [7:0] data_o; + +reg [7:0] data_o; + +reg [7:0] inva; +reg [3:0] ah; +reg [3:0] al; +reg [3:0] ah2; +reg [3:0] al2; +reg [3:0] alxh; +reg [3:0] alph; +reg [3:0] d; +reg [3:0] ahp; +reg [3:0] alp; +reg [3:0] to_invert; +reg [3:0] next_to_invert; +reg [3:0] ah_reg; +reg [3:0] next_ah_reg; +reg [3:0] next_alph; + + +//registers: +always @(posedge clk or negedge reset) + +begin + +if(!reset) +begin + +to_invert = (0); + ah_reg = (0); +alph = (0); + +end +else +begin + + to_invert = (next_to_invert); + ah_reg = (next_ah_reg); +alph = (next_alph); + +end + + +end +//first_mux: +reg[7:0] first_mux_data_var; + reg[7:0] first_mux_InvInput; + reg[3:0] first_mux_ah_t,first_mux_al_t; + reg first_mux_aA,first_mux_aB,first_mux_aC,first_mux_aD; + +always @( data_i or decrypt_i) + +begin + + + first_mux_data_var=data_i; + first_mux_InvInput=first_mux_data_var; + + case(decrypt_i) + 1: +begin + //Applyinverseaffinetrasformation +first_mux_aA=first_mux_data_var[0]^first_mux_data_var[5];first_mux_aB=first_mux_data_var[1]^first_mux_data_var[4]; + first_mux_aC=first_mux_data_var[2]^first_mux_data_var[7];first_mux_aD=first_mux_data_var[3]^first_mux_data_var[6]; + first_mux_InvInput[0]=(!first_mux_data_var[5])^first_mux_aC; + first_mux_InvInput[1]=first_mux_data_var[0]^first_mux_aD; + first_mux_InvInput[2]=(!first_mux_data_var[7])^first_mux_aB; + first_mux_InvInput[3]=first_mux_data_var[2]^first_mux_aA; + first_mux_InvInput[4]=first_mux_data_var[1]^first_mux_aD; + first_mux_InvInput[5]=first_mux_data_var[4]^first_mux_aC; + first_mux_InvInput[6]=first_mux_data_var[3]^first_mux_aA; + first_mux_InvInput[7]=first_mux_data_var[6]^first_mux_aB; + end + default: +begin +first_mux_InvInput=first_mux_data_var; + end + endcase + + + //ConvertelementsfromGF(2^8)intotwoelementsofGF(2^4^2) + + first_mux_aA=first_mux_InvInput[1]^first_mux_InvInput[7]; + first_mux_aB=first_mux_InvInput[5]^first_mux_InvInput[7]; + first_mux_aC=first_mux_InvInput[4]^first_mux_InvInput[6]; + + + first_mux_al_t[0]=first_mux_aC^first_mux_InvInput[0]^first_mux_InvInput[5]; + first_mux_al_t[1]=first_mux_InvInput[1]^first_mux_InvInput[2]; + first_mux_al_t[2]=first_mux_aA; + first_mux_al_t[3]=first_mux_InvInput[2]^first_mux_InvInput[4]; + + first_mux_ah_t[0]=first_mux_aC^first_mux_InvInput[5]; + first_mux_ah_t[1]=first_mux_aA^first_mux_aC; + first_mux_ah_t[2]=first_mux_aB^first_mux_InvInput[2]^first_mux_InvInput[3]; + first_mux_ah_t[3]=first_mux_aB; + + al = (first_mux_al_t); + ah = (first_mux_ah_t); + next_ah_reg = (first_mux_ah_t); + +end +//end_mux: +reg[7:0] end_mux_data_var,end_mux_data_o_var; + reg end_mux_aA,end_mux_aB,end_mux_aC,end_mux_aD; + +always @( decrypt_i or inva) + +begin + + + + //Taketheoutputoftheinverter + end_mux_data_var=inva; + + case(decrypt_i) + 0: +begin + //Applyaffinetrasformation +end_mux_aA=end_mux_data_var[0]^end_mux_data_var[1];end_mux_aB=end_mux_data_var[2]^end_mux_data_var[3]; + end_mux_aC=end_mux_data_var[4]^end_mux_data_var[5];end_mux_aD=end_mux_data_var[6]^end_mux_data_var[7]; + end_mux_data_o_var[0]=(!end_mux_data_var[0])^end_mux_aC^end_mux_aD; + end_mux_data_o_var[1]=(!end_mux_data_var[5])^end_mux_aA^end_mux_aD; + end_mux_data_o_var[2]=end_mux_data_var[2]^end_mux_aA^end_mux_aD; + end_mux_data_o_var[3]=end_mux_data_var[7]^end_mux_aA^end_mux_aB; + end_mux_data_o_var[4]=end_mux_data_var[4]^end_mux_aA^end_mux_aB; + end_mux_data_o_var[5]=(!end_mux_data_var[1])^end_mux_aB^end_mux_aC; + end_mux_data_o_var[6]=(!end_mux_data_var[6])^end_mux_aB^end_mux_aC; + end_mux_data_o_var[7]=end_mux_data_var[3]^end_mux_aC^end_mux_aD; + data_o = (end_mux_data_o_var); + end + default: +begin +data_o = (end_mux_data_var); + end + endcase + + + +end +//inversemap: +reg[3:0] aA,aB; + reg[3:0] inversemap_alp_t,inversemap_ahp_t; + reg[7:0] inversemap_inva_t; + +always @( alp or ahp) +begin + + + inversemap_alp_t=alp; + inversemap_ahp_t=ahp; + + aA=inversemap_alp_t[1]^inversemap_ahp_t[3]; + aB=inversemap_ahp_t[0]^inversemap_ahp_t[1]; + + inversemap_inva_t[0]=inversemap_alp_t[0]^inversemap_ahp_t[0]; + inversemap_inva_t[1]=aB^inversemap_ahp_t[3]; + inversemap_inva_t[2]=aA^aB; + inversemap_inva_t[3]=aB^inversemap_alp_t[1]^inversemap_ahp_t[2]; + inversemap_inva_t[4]=aA^aB^inversemap_alp_t[3]; + inversemap_inva_t[5]=aB^inversemap_alp_t[2]; + inversemap_inva_t[6]=aA^inversemap_alp_t[2]^inversemap_alp_t[3]^inversemap_ahp_t[0]; + inversemap_inva_t[7]=aB^inversemap_alp_t[2]^inversemap_ahp_t[3]; + + inva = (inversemap_inva_t); + +end +//mul1: +reg[3:0] mul1_alxh_t; + reg[3:0] mul1_aA,mul1_a; + +always @( ah or al) + +begin + + //alxah + + mul1_aA=al[0]^al[3]; + mul1_a=al[2]^al[3]; + + mul1_alxh_t[0]=(al[0]&ah[0])^(al[3]&ah[1])^(al[2]&ah[2])^(al[1]&ah[3]); + mul1_alxh_t[1]=(al[1]&ah[0])^(mul1_aA&ah[1])^(mul1_a&ah[2])^((al[1]^al[2])&ah[3]); + mul1_alxh_t[2]=(al[2]&ah[0])^(al[1]&ah[1])^(mul1_aA&ah[2])^(mul1_a&ah[3]); + mul1_alxh_t[3]=(al[3]&ah[0])^(al[2]&ah[1])^(al[1]&ah[2])^(mul1_aA&ah[3]); + + alxh = (mul1_alxh_t); + +end +//mul2: +reg[3:0] mul2_ahp_t; + reg[3:0] mul2_aA,mul2_aB; + +always @( d or ah_reg) + +begin + + //ahxd + + mul2_aA=ah_reg[0]^ah_reg[3]; + mul2_aB=ah_reg[2]^ah_reg[3]; + + mul2_ahp_t[0]=(ah_reg[0]&d[0])^(ah_reg[3]&d[1])^(ah_reg[2]&d[2])^(ah_reg[1]&d[3]); + mul2_ahp_t[1]=(ah_reg[1]&d[0])^(mul2_aA&d[1])^(mul2_aB&d[2])^((ah_reg[1]^ah_reg[2])&d[3]); + mul2_ahp_t[2]=(ah_reg[2]&d[0])^(ah_reg[1]&d[1])^(mul2_aA&d[2])^(mul2_aB&d[3]); + mul2_ahp_t[3]=(ah_reg[3]&d[0])^(ah_reg[2]&d[1])^(ah_reg[1]&d[2])^(mul2_aA&d[3]); + + ahp = (mul2_ahp_t); + +end +//mul3: +reg[3:0] mul3_alp_t; + reg[3:0] mul3_aA,mul3_aB; + +always @( d or alph) + +begin + + //dxal + + mul3_aA=d[0]^d[3]; + mul3_aB=d[2]^d[3]; + + mul3_alp_t[0]=(d[0]&alph[0])^(d[3]&alph[1])^(d[2]&alph[2])^(d[1]&alph[3]); + mul3_alp_t[1]=(d[1]&alph[0])^(mul3_aA&alph[1])^(mul3_aB&alph[2])^((d[1]^d[2])&alph[3]); + mul3_alp_t[2]=(d[2]&alph[0])^(d[1]&alph[1])^(mul3_aA&alph[2])^(mul3_aB&alph[3]); + mul3_alp_t[3]=(d[3]&alph[0])^(d[2]&alph[1])^(d[1]&alph[2])^(mul3_aA&alph[3]); + + alp = (mul3_alp_t); + +end +//intermediate: +reg[3:0] intermediate_aA,intermediate_aB; + reg[3:0] intermediate_ah2e,intermediate_ah2epl2,intermediate_to_invert_var; + +always @( ah2 or al2 or alxh) + +begin + + + //ahsquareismultipliedwithe + intermediate_aA=ah2[0]^ah2[1]; + intermediate_aB=ah2[2]^ah2[3]; + intermediate_ah2e[0]=ah2[1]^intermediate_aB; + intermediate_ah2e[1]=intermediate_aA; + intermediate_ah2e[2]=intermediate_aA^ah2[2]; + intermediate_ah2e[3]=intermediate_aA^intermediate_aB; + + //Additionofintermediate_ah2eplusal2 + intermediate_ah2epl2[0]=intermediate_ah2e[0]^al2[0]; + intermediate_ah2epl2[1]=intermediate_ah2e[1]^al2[1]; + intermediate_ah2epl2[2]=intermediate_ah2e[2]^al2[2]; + intermediate_ah2epl2[3]=intermediate_ah2e[3]^al2[3]; + + //Additionoflastresultwiththeresultof(alxah) + intermediate_to_invert_var[0]=intermediate_ah2epl2[0]^alxh[0]; + intermediate_to_invert_var[1]=intermediate_ah2epl2[1]^alxh[1]; + intermediate_to_invert_var[2]=intermediate_ah2epl2[2]^alxh[2]; + intermediate_to_invert_var[3]=intermediate_ah2epl2[3]^alxh[3]; + +//Registers + next_to_invert = (intermediate_to_invert_var); + +end +//inversion: +reg[3:0] inversion_to_invert_var; + reg[3:0] inversion_aA,inversion_d_t; + +always @( to_invert) + +begin + + + inversion_to_invert_var=to_invert; + + //InverttheresultinGF(2^4) + inversion_aA=inversion_to_invert_var[1]^inversion_to_invert_var[2]^inversion_to_invert_var[3]^(inversion_to_invert_var[1]&inversion_to_invert_var[2]&inversion_to_invert_var[3]); + inversion_d_t[0]=inversion_aA^inversion_to_invert_var[0]^(inversion_to_invert_var[0]&inversion_to_invert_var[2])^(inversion_to_invert_var[1]&inversion_to_invert_var[2])^(inversion_to_invert_var[0]&inversion_to_invert_var[1]&inversion_to_invert_var[2]); + inversion_d_t[1]=(inversion_to_invert_var[0]&inversion_to_invert_var[1])^(inversion_to_invert_var[0]&inversion_to_invert_var[2])^(inversion_to_invert_var[1]&inversion_to_invert_var[2])^inversion_to_invert_var[3]^(inversion_to_invert_var[1]&inversion_to_invert_var[3])^(inversion_to_invert_var[0]&inversion_to_invert_var[1]&inversion_to_invert_var[3]); + inversion_d_t[2]=(inversion_to_invert_var[0]&inversion_to_invert_var[1])^inversion_to_invert_var[2]^(inversion_to_invert_var[0]&inversion_to_invert_var[2])^inversion_to_invert_var[3]^(inversion_to_invert_var[0]&inversion_to_invert_var[3])^(inversion_to_invert_var[0]&inversion_to_invert_var[2]&inversion_to_invert_var[3]); + inversion_d_t[3]=inversion_aA^(inversion_to_invert_var[0]&inversion_to_invert_var[3])^(inversion_to_invert_var[1]&inversion_to_invert_var[3])^(inversion_to_invert_var[2]&inversion_to_invert_var[3]); + + d = (inversion_d_t); + + +end +//sum1: +reg[3:0] sum1_alph_t; + +always @( ah or al) + +begin + + + sum1_alph_t[0]=al[0]^ah[0]; + sum1_alph_t[1]=al[1]^ah[1]; + sum1_alph_t[2]=al[2]^ah[2]; + sum1_alph_t[3]=al[3]^ah[3]; + + next_alph = (sum1_alph_t); + +end +//square1: +reg[3:0] square1_ah_t; + +always @( ah) + +begin + + + square1_ah_t[0]=ah[0]^ah[2]; + square1_ah_t[1]=ah[2]; + square1_ah_t[2]=ah[1]^ah[3]; + square1_ah_t[3]=ah[3]; + + ah2 = (square1_ah_t); + +end +//square2: +reg[3:0] square2_al_t; + +always @( al) + +begin + + + square2_al_t[0]=al[0]^al[2]; + square2_al_t[1]=al[2]; + square2_al_t[2]=al[1]^al[3]; + square2_al_t[3]=al[3]; + + al2 = (square2_al_t); + +end + +endmodule diff --git a/tests/iwls2005/systemcaes/subbytes.v b/tests/iwls2005/systemcaes/subbytes.v new file mode 100644 index 00000000..6c6bd20c --- /dev/null +++ b/tests/iwls2005/systemcaes/subbytes.v @@ -0,0 +1,259 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Subbytes module implementation //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// Subbytes module implementation //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: subbytes.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + +module subbytes(clk,reset,start_i,decrypt_i,data_i,ready_o,data_o,sbox_data_o,sbox_data_i,sbox_decrypt_o); +input clk; +input reset; +input start_i; +input decrypt_i; +input [127:0] data_i; +output ready_o; +output [127:0] data_o; +output [7:0] sbox_data_o; +input [7:0] sbox_data_i; +output sbox_decrypt_o; + +reg ready_o; +reg [127:0] data_o; +reg [7:0] sbox_data_o; +reg sbox_decrypt_o; + +reg [4:0] state; +reg [4:0] next_state; +reg [127:0] data_reg; +reg [127:0] next_data_reg; +reg next_ready_o; + +`define assign_array_to_128 \ + data_reg_128[127:120]=data_reg_var[0]; \ + data_reg_128[119:112]=data_reg_var[1]; \ + data_reg_128[111:104]=data_reg_var[2]; \ + data_reg_128[103:96]=data_reg_var[3]; \ + data_reg_128[95:88]=data_reg_var[4]; \ + data_reg_128[87:80]=data_reg_var[5]; \ + data_reg_128[79:72]=data_reg_var[6]; \ + data_reg_128[71:64]=data_reg_var[7]; \ + data_reg_128[63:56]=data_reg_var[8]; \ + data_reg_128[55:48]=data_reg_var[9]; \ + data_reg_128[47:40]=data_reg_var[10]; \ + data_reg_128[39:32]=data_reg_var[11]; \ + data_reg_128[31:24]=data_reg_var[12]; \ + data_reg_128[23:16]=data_reg_var[13]; \ + data_reg_128[15:8]=data_reg_var[14]; \ + data_reg_128[7:0]=data_reg_var[15]; + +`define shift_array_to_128 \ + data_reg_128[127:120]=data_reg_var[0]; \ + data_reg_128[119:112]=data_reg_var[5]; \ + data_reg_128[111:104]=data_reg_var[10]; \ + data_reg_128[103:96]=data_reg_var[15]; \ + data_reg_128[95:88]=data_reg_var[4]; \ + data_reg_128[87:80]=data_reg_var[9]; \ + data_reg_128[79:72]=data_reg_var[14]; \ + data_reg_128[71:64]=data_reg_var[3]; \ + data_reg_128[63:56]=data_reg_var[8]; \ + data_reg_128[55:48]=data_reg_var[13]; \ + data_reg_128[47:40]=data_reg_var[2]; \ + data_reg_128[39:32]=data_reg_var[7]; \ + data_reg_128[31:24]=data_reg_var[12]; \ + data_reg_128[23:16]=data_reg_var[1]; \ + data_reg_128[15:8]=data_reg_var[6]; \ + data_reg_128[7:0]=data_reg_var[11]; + +`define invert_shift_array_to_128 \ + data_reg_128[127:120]=data_reg_var[0]; \ + data_reg_128[119:112]=data_reg_var[13]; \ + data_reg_128[111:104]=data_reg_var[10]; \ + data_reg_128[103:96]=data_reg_var[7]; \ + data_reg_128[95:88]=data_reg_var[4]; \ + data_reg_128[87:80]=data_reg_var[1]; \ + data_reg_128[79:72]=data_reg_var[14]; \ + data_reg_128[71:64]=data_reg_var[11]; \ + data_reg_128[63:56]=data_reg_var[8]; \ + data_reg_128[55:48]=data_reg_var[5]; \ + data_reg_128[47:40]=data_reg_var[2]; \ + data_reg_128[39:32]=data_reg_var[15]; \ + data_reg_128[31:24]=data_reg_var[12]; \ + data_reg_128[23:16]=data_reg_var[9]; \ + data_reg_128[15:8]=data_reg_var[6]; \ + data_reg_128[7:0]=data_reg_var[3]; + + +//registers: +always @(posedge clk or negedge reset) + +begin + +if(!reset) +begin + + data_reg = (0); + state = (0); + ready_o = (0); + +end +else +begin + + data_reg = (next_data_reg); + state = (next_state); + ready_o = (next_ready_o); + +end + + +end +//sub: +reg[127:0] data_i_var,data_reg_128; +reg[7:0] data_array[15:0],data_reg_var[15:0]; + +always @( decrypt_i or start_i or state or data_i or sbox_data_i or data_reg) + +begin + + + data_i_var=data_i; + + data_array[0]=data_i_var[127:120]; + data_array[1]=data_i_var[119:112]; + data_array[2]=data_i_var[111:104]; + data_array[3]=data_i_var[103:96]; + data_array[4]=data_i_var[95:88]; + data_array[5]=data_i_var[87:80]; + data_array[6]=data_i_var[79:72]; + data_array[7]=data_i_var[71:64]; + data_array[8]=data_i_var[63:56]; + data_array[9]=data_i_var[55:48]; + data_array[10]=data_i_var[47:40]; + data_array[11]=data_i_var[39:32]; + data_array[12]=data_i_var[31:24]; + data_array[13]=data_i_var[23:16]; + data_array[14]=data_i_var[15:8]; + data_array[15]=data_i_var[7:0]; + + data_reg_var[0]=data_reg[127:120]; + data_reg_var[1]=data_reg[119:112]; + data_reg_var[2]=data_reg[111:104]; + data_reg_var[3]=data_reg[103:96]; + data_reg_var[4]=data_reg[95:88]; + data_reg_var[5]=data_reg[87:80]; + data_reg_var[6]=data_reg[79:72]; + data_reg_var[7]=data_reg[71:64]; + data_reg_var[8]=data_reg[63:56]; + data_reg_var[9]=data_reg[55:48]; + data_reg_var[10]=data_reg[47:40]; + data_reg_var[11]=data_reg[39:32]; + data_reg_var[12]=data_reg[31:24]; + data_reg_var[13]=data_reg[23:16]; + data_reg_var[14]=data_reg[15:8]; + data_reg_var[15]=data_reg[7:0]; + + + sbox_decrypt_o = (decrypt_i); + sbox_data_o = (0); + next_state = (state); + next_data_reg = (data_reg); + + next_ready_o = (0); + data_o = (data_reg); + + case(state) + + 0: +begin + if(start_i) +begin + +sbox_data_o = (data_array[0]); + next_state = (1); + +end + + end + 16: +begin + data_reg_var[15]=sbox_data_i; + //Makeshiftrowsstage + case(decrypt_i) + 0: + begin + `shift_array_to_128 + end + 1: + begin + `invert_shift_array_to_128 + end + endcase + + next_data_reg = (data_reg_128); + next_ready_o = (1); + next_state = (0); + end + default: + begin + /* original version (causing troubles with synopsys formality): + sbox_data_o = (data_array[state]); + data_reg_var[state-1]=sbox_data_i; + improved version: */ + sbox_data_o = (data_array[state & 15]); + data_reg_var[(state-1) & 15]=sbox_data_i; + /* end of improved version */ + `assign_array_to_128 + next_data_reg = (data_reg_128); + next_state = (state+1); + end + +endcase + + +end + +endmodule diff --git a/tests/iwls2005/systemcaes/timescale.v b/tests/iwls2005/systemcaes/timescale.v new file mode 100644 index 00000000..ff9e265a --- /dev/null +++ b/tests/iwls2005/systemcaes/timescale.v @@ -0,0 +1 @@ +`timescale 1ns / 10ps diff --git a/tests/iwls2005/systemcaes/word_mixcolum.v b/tests/iwls2005/systemcaes/word_mixcolum.v new file mode 100644 index 00000000..9308ccc9 --- /dev/null +++ b/tests/iwls2005/systemcaes/word_mixcolum.v @@ -0,0 +1,124 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Mixcolumns for a 16 bit word module implementation //// +//// //// +//// This file is part of the SystemC AES //// +//// //// +//// Description: //// +//// Mixcolum for a 16 bit word //// +//// //// +//// Generated automatically using SystemC to Verilog translator //// +//// //// +//// To Do: //// +//// - done //// +//// //// +//// Author(s): //// +//// - Javier Castillo, jcastilo@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: word_mixcolum.v,v $ +// Revision 1.1.1.1 2004/07/05 09:46:23 jcastillo +// First import +// + +module word_mixcolum(in,outx,outy); +input [31:0] in; +output [31:0] outx; +output [31:0] outy; + +reg [31:0] outx; +reg [31:0] outy; + +reg [7:0] a; +reg [7:0] b; +reg [7:0] c; +reg [7:0] d; +wire [7:0] x1; + +wire [7:0] x2; + +wire [7:0] x3; + +wire [7:0] x4; + +wire [7:0] y1; + +wire [7:0] y2; + +wire [7:0] y3; + +wire [7:0] y4; + + +byte_mixcolum bm1 (.a(a), .b(b), .c(c), .d(d), .outx(x1), .outy(y1)); +byte_mixcolum bm2 (.a(b), .b(c), .c(d), .d(a), .outx(x2), .outy(y2)); +byte_mixcolum bm3 (.a(c), .b(d), .c(a), .d(b), .outx(x3), .outy(y3)); +byte_mixcolum bm4 (.a(d), .b(a), .c(b), .d(c), .outx(x4), .outy(y4)); + + + reg[31:0] in_var; + reg[31:0] outx_var,outy_var; +//split: +always @( in) + +begin + + + + in_var=in; + a = (in_var[31:24]); + b = (in_var[23:16]); + c = (in_var[15:8]); + d = (in_var[7:0]); + +end +//mix: +always @( x1 or x2 or x3 or x4 or y1 or y2 or y3 or y4) + +begin + + + + outx_var[31:24]=x1; + outx_var[23:16]=x2; + outx_var[15:8]=x3; + outx_var[7:0]=x4; + outy_var[31:24]=y1; + outy_var[23:16]=y2; + outy_var[15:8]=y3; + outy_var[7:0]=y4; + + outx = (outx_var); + outy = (outy_var); + +end + +endmodule diff --git a/tests/iwls2005/usb_phy/timescale.v b/tests/iwls2005/usb_phy/timescale.v new file mode 100644 index 00000000..ff9e265a --- /dev/null +++ b/tests/iwls2005/usb_phy/timescale.v @@ -0,0 +1 @@ +`timescale 1ns / 10ps diff --git a/tests/iwls2005/usb_phy/usb_phy.v b/tests/iwls2005/usb_phy/usb_phy.v new file mode 100644 index 00000000..4ee345ad --- /dev/null +++ b/tests/iwls2005/usb_phy/usb_phy.v @@ -0,0 +1,184 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB 1.1 PHY //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb_phy/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb_phy.v,v 1.4 2003/10/21 05:58:40 rudi Exp $ +// +// $Date: 2003/10/21 05:58:40 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usb_phy.v,v $ +// Revision 1.4 2003/10/21 05:58:40 rudi +// usb_rst is no longer or'ed with the incomming reset internally. +// Now usb_rst is simply an output, the application can decide how +// to utilize it. +// +// Revision 1.3 2003/10/19 17:40:13 rudi +// - Made core more robust against line noise +// - Added Error Checking and Reporting +// (See README.txt for more info) +// +// Revision 1.2 2002/09/16 16:06:37 rudi +// Changed top level name to be consistent ... +// +// Revision 1.1.1.1 2002/09/16 14:26:59 rudi +// Created Directory Structure +// +// +// +// +// +// +// +// + +`include "timescale.v" + +module usb_phy(clk, rst, phy_tx_mode, usb_rst, + + // Transciever Interface + txdp, txdn, txoe, + rxd, rxdp, rxdn, + + // UTMI Interface + DataOut_i, TxValid_i, TxReady_o, RxValid_o, + RxActive_o, RxError_o, DataIn_o, LineState_o + ); + +input clk; +input rst; +input phy_tx_mode; +output usb_rst; +output txdp, txdn, txoe; +input rxd, rxdp, rxdn; +input [7:0] DataOut_i; +input TxValid_i; +output TxReady_o; +output [7:0] DataIn_o; +output RxValid_o; +output RxActive_o; +output RxError_o; +output [1:0] LineState_o; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +reg [4:0] rst_cnt; +reg usb_rst; +wire fs_ce; +wire rst; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +/////////////////////////////////////////////////////////////////// +// +// TX Phy +// + +usb_tx_phy i_tx_phy( + .clk( clk ), + .rst( rst ), + .fs_ce( fs_ce ), + .phy_mode( phy_tx_mode ), + + // Transciever Interface + .txdp( txdp ), + .txdn( txdn ), + .txoe( txoe ), + + // UTMI Interface + .DataOut_i( DataOut_i ), + .TxValid_i( TxValid_i ), + .TxReady_o( TxReady_o ) + ); + +/////////////////////////////////////////////////////////////////// +// +// RX Phy and DPLL +// + +usb_rx_phy i_rx_phy( + .clk( clk ), + .rst( rst ), + .fs_ce( fs_ce ), + + // Transciever Interface + .rxd( rxd ), + .rxdp( rxdp ), + .rxdn( rxdn ), + + // UTMI Interface + .DataIn_o( DataIn_o ), + .RxValid_o( RxValid_o ), + .RxActive_o( RxActive_o ), + .RxError_o( RxError_o ), + .RxEn_i( txoe ), + .LineState( LineState_o ) + ); + +/////////////////////////////////////////////////////////////////// +// +// Generate an USB Reset is we see SE0 for at least 2.5uS +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) rst_cnt <= 5'h0; + else + if(LineState_o != 2'h0) rst_cnt <= 5'h0; + else + if(!usb_rst && fs_ce) rst_cnt <= rst_cnt + 5'h1; + +always @(posedge clk) + usb_rst <= (rst_cnt == 5'h1f); + +endmodule + diff --git a/tests/iwls2005/usb_phy/usb_rx_phy.v b/tests/iwls2005/usb_phy/usb_rx_phy.v new file mode 100644 index 00000000..c0568fb7 --- /dev/null +++ b/tests/iwls2005/usb_phy/usb_rx_phy.v @@ -0,0 +1,452 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB 1.1 PHY //// +//// RX & DPLL //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb_phy/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb_rx_phy.v,v 1.5 2004/10/19 09:29:07 rudi Exp $ +// +// $Date: 2004/10/19 09:29:07 $ +// $Revision: 1.5 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usb_rx_phy.v,v $ +// Revision 1.5 2004/10/19 09:29:07 rudi +// Fixed DPLL alignment in the rx_phy and bit stuffing errors in the tx_phy (if last bit bit was a stuff bit in a packet it was omitted). +// +// Revision 1.4 2003/12/02 04:56:00 rudi +// Fixed a bug reported by Karl C. Posch from Graz University of Technology. Thanks Karl ! +// +// Revision 1.3 2003/10/19 18:07:45 rudi +// - Fixed Sync Error to be only checked/generated during the sync phase +// +// Revision 1.2 2003/10/19 17:40:13 rudi +// - Made core more robust against line noise +// - Added Error Checking and Reporting +// (See README.txt for more info) +// +// Revision 1.1.1.1 2002/09/16 14:27:01 rudi +// Created Directory Structure +// +// +// +// +// +// +// +// + +`include "timescale.v" + +module usb_rx_phy( clk, rst, fs_ce, + + // Transciever Interface + rxd, rxdp, rxdn, + + // UTMI Interface + RxValid_o, RxActive_o, RxError_o, DataIn_o, + RxEn_i, LineState); + +input clk; +input rst; +output fs_ce; +input rxd, rxdp, rxdn; +output [7:0] DataIn_o; +output RxValid_o; +output RxActive_o; +output RxError_o; +input RxEn_i; +output [1:0] LineState; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +reg rxd_s0, rxd_s1, rxd_s; +reg rxdp_s0, rxdp_s1, rxdp_s, rxdp_s_r; +reg rxdn_s0, rxdn_s1, rxdn_s, rxdn_s_r; +reg synced_d; +wire k, j, se0; +reg rxd_r; +reg rx_en; +reg rx_active; +reg [2:0] bit_cnt; +reg rx_valid1, rx_valid; +reg shift_en; +reg sd_r; +reg sd_nrzi; +reg [7:0] hold_reg; +wire drop_bit; // Indicates a stuffed bit +reg [2:0] one_cnt; + +reg [1:0] dpll_state, dpll_next_state; +reg fs_ce_d; +reg fs_ce; +wire change; +wire lock_en; +reg [2:0] fs_state, fs_next_state; +reg rx_valid_r; +reg sync_err_d, sync_err; +reg bit_stuff_err; +reg se0_r, byte_err; +reg se0_s; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign RxActive_o = rx_active; +assign RxValid_o = rx_valid; +assign RxError_o = sync_err | bit_stuff_err | byte_err; +assign DataIn_o = hold_reg; +assign LineState = {rxdn_s1, rxdp_s1}; + +always @(posedge clk) rx_en <= RxEn_i; +always @(posedge clk) sync_err <= !rx_active & sync_err_d; + +/////////////////////////////////////////////////////////////////// +// +// Synchronize Inputs +// + +// First synchronize to the local system clock to +// avoid metastability outside the sync block (*_s0). +// Then make sure we see the signal for at least two +// clock cycles stable to avoid glitches and noise + +always @(posedge clk) rxd_s0 <= rxd; +always @(posedge clk) rxd_s1 <= rxd_s0; +always @(posedge clk) // Avoid detecting Line Glitches and noise + if(rxd_s0 && rxd_s1) rxd_s <= 1'b1; + else + if(!rxd_s0 && !rxd_s1) rxd_s <= 1'b0; + +always @(posedge clk) rxdp_s0 <= rxdp; +always @(posedge clk) rxdp_s1 <= rxdp_s0; +always @(posedge clk) rxdp_s_r <= rxdp_s0 & rxdp_s1; +always @(posedge clk) rxdp_s <= (rxdp_s0 & rxdp_s1) | rxdp_s_r; // Avoid detecting Line Glitches and noise + +always @(posedge clk) rxdn_s0 <= rxdn; +always @(posedge clk) rxdn_s1 <= rxdn_s0; +always @(posedge clk) rxdn_s_r <= rxdn_s0 & rxdn_s1; +always @(posedge clk) rxdn_s <= (rxdn_s0 & rxdn_s1) | rxdn_s_r; // Avoid detecting Line Glitches and noise + +assign k = !rxdp_s & rxdn_s; +assign j = rxdp_s & !rxdn_s; +assign se0 = !rxdp_s & !rxdn_s; + +always @(posedge clk) if(fs_ce) se0_s <= se0; + +/////////////////////////////////////////////////////////////////// +// +// DPLL +// + +// This design uses a clock enable to do 12Mhz timing and not a +// real 12Mhz clock. Everything always runs at 48Mhz. We want to +// make sure however, that the clock enable is always exactly in +// the middle between two virtual 12Mhz rising edges. +// We monitor rxdp and rxdn for any changes and do the appropiate +// adjustments. +// In addition to the locking done in the dpll FSM, we adjust the +// final latch enable to compensate for various sync registers ... + +// Allow lockinf only when we are receiving +assign lock_en = rx_en; + +always @(posedge clk) rxd_r <= rxd_s; + +// Edge detector +assign change = rxd_r != rxd_s; + +// DPLL FSM +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) dpll_state <= 2'h1; + else dpll_state <= dpll_next_state; + +always @(dpll_state or lock_en or change) + begin + fs_ce_d = 1'b0; + case(dpll_state) // synopsys full_case parallel_case + 2'h0: + if(lock_en && change) dpll_next_state = 2'h0; + else dpll_next_state = 2'h1; + 2'h1:begin + fs_ce_d = 1'b1; + if(lock_en && change) dpll_next_state = 2'h3; + else dpll_next_state = 2'h2; + end + 2'h2: + if(lock_en && change) dpll_next_state = 2'h0; + else dpll_next_state = 2'h3; + 2'h3: + if(lock_en && change) dpll_next_state = 2'h0; + else dpll_next_state = 2'h0; + endcase + end + +// Compensate for sync registers at the input - allign full speed +// clock enable to be in the middle between two bit changes ... +reg fs_ce_r1, fs_ce_r2; + +always @(posedge clk) fs_ce_r1 <= fs_ce_d; +always @(posedge clk) fs_ce_r2 <= fs_ce_r1; +always @(posedge clk) fs_ce <= fs_ce_r2; + + +/////////////////////////////////////////////////////////////////// +// +// Find Sync Pattern FSM +// + +parameter FS_IDLE = 3'h0, + K1 = 3'h1, + J1 = 3'h2, + K2 = 3'h3, + J2 = 3'h4, + K3 = 3'h5, + J3 = 3'h6, + K4 = 3'h7; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) fs_state <= FS_IDLE; + else fs_state <= fs_next_state; + +always @(fs_state or fs_ce or k or j or rx_en or rx_active or se0 or se0_s) + begin + synced_d = 1'b0; + sync_err_d = 1'b0; + fs_next_state = fs_state; + if(fs_ce && !rx_active && !se0 && !se0_s) + case(fs_state) // synopsys full_case parallel_case + FS_IDLE: + begin + if(k && rx_en) fs_next_state = K1; + end + K1: + begin + if(j && rx_en) fs_next_state = J1; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + J1: + begin + if(k && rx_en) fs_next_state = K2; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + K2: + begin + if(j && rx_en) fs_next_state = J2; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + J2: + begin + if(k && rx_en) fs_next_state = K3; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + K3: + begin + if(j && rx_en) fs_next_state = J3; + else + if(k && rx_en) + begin + fs_next_state = FS_IDLE; // Allow missing first K-J + synced_d = 1'b1; + end + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + J3: + begin + if(k && rx_en) fs_next_state = K4; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + K4: + begin + if(k) synced_d = 1'b1; + fs_next_state = FS_IDLE; + end + endcase + end + +/////////////////////////////////////////////////////////////////// +// +// Generate RxActive +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) rx_active <= 1'b0; + else + if(synced_d && rx_en) rx_active <= 1'b1; + else + if(se0 && rx_valid_r) rx_active <= 1'b0; + +always @(posedge clk) + if(rx_valid) rx_valid_r <= 1'b1; + else + if(fs_ce) rx_valid_r <= 1'b0; + +/////////////////////////////////////////////////////////////////// +// +// NRZI Decoder +// + +always @(posedge clk) + if(fs_ce) sd_r <= rxd_s; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) sd_nrzi <= 1'b0; + else + if(!rx_active) sd_nrzi <= 1'b1; + else + if(rx_active && fs_ce) sd_nrzi <= !(rxd_s ^ sd_r); + +/////////////////////////////////////////////////////////////////// +// +// Bit Stuff Detect +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) one_cnt <= 3'h0; + else + if(!shift_en) one_cnt <= 3'h0; + else + if(fs_ce) + begin + if(!sd_nrzi || drop_bit) one_cnt <= 3'h0; + else one_cnt <= one_cnt + 3'h1; + end + +assign drop_bit = (one_cnt==3'h6); + +always @(posedge clk) bit_stuff_err <= drop_bit & sd_nrzi & fs_ce & !se0 & rx_active; // Bit Stuff Error + +/////////////////////////////////////////////////////////////////// +// +// Serial => Parallel converter +// + +always @(posedge clk) + if(fs_ce) shift_en <= synced_d | rx_active; + +always @(posedge clk) + if(fs_ce && shift_en && !drop_bit) + hold_reg <= {sd_nrzi, hold_reg[7:1]}; + +/////////////////////////////////////////////////////////////////// +// +// Generate RxValid +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) bit_cnt <= 3'b0; + else + if(!shift_en) bit_cnt <= 3'h0; + else + if(fs_ce && !drop_bit) bit_cnt <= bit_cnt + 3'h1; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) rx_valid1 <= 1'b0; + else + if(fs_ce && !drop_bit && (bit_cnt==3'h7)) rx_valid1 <= 1'b1; + else + if(rx_valid1 && fs_ce && !drop_bit) rx_valid1 <= 1'b0; + +always @(posedge clk) rx_valid <= !drop_bit & rx_valid1 & fs_ce; + +always @(posedge clk) se0_r <= se0; + +always @(posedge clk) byte_err <= se0 & !se0_r & (|bit_cnt[2:1]) & rx_active; + +endmodule + diff --git a/tests/iwls2005/usb_phy/usb_tx_phy.v b/tests/iwls2005/usb_phy/usb_tx_phy.v new file mode 100644 index 00000000..7f61ffd3 --- /dev/null +++ b/tests/iwls2005/usb_phy/usb_tx_phy.v @@ -0,0 +1,465 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB 1.1 PHY //// +//// TX //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb_phy/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// 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. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb_tx_phy.v,v 1.4 2004/10/19 09:29:07 rudi Exp $ +// +// $Date: 2004/10/19 09:29:07 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: usb_tx_phy.v,v $ +// Revision 1.4 2004/10/19 09:29:07 rudi +// Fixed DPLL alignment in the rx_phy and bit stuffing errors in the tx_phy (if last bit bit was a stuff bit in a packet it was omitted). +// +// Revision 1.3 2003/10/21 05:58:41 rudi +// usb_rst is no longer or'ed with the incomming reset internally. +// Now usb_rst is simply an output, the application can decide how +// to utilize it. +// +// Revision 1.2 2003/10/19 17:40:13 rudi +// - Made core more robust against line noise +// - Added Error Checking and Reporting +// (See README.txt for more info) +// +// Revision 1.1.1.1 2002/09/16 14:27:02 rudi +// Created Directory Structure +// +// +// +// +// +// +// + +`include "timescale.v" + +module usb_tx_phy( + clk, rst, fs_ce, phy_mode, + + // Transciever Interface + txdp, txdn, txoe, + + // UTMI Interface + DataOut_i, TxValid_i, TxReady_o + ); + +input clk; +input rst; +input fs_ce; +input phy_mode; +output txdp, txdn, txoe; +input [7:0] DataOut_i; +input TxValid_i; +output TxReady_o; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +parameter IDLE = 3'd0, + SOP = 3'h1, + DATA = 3'h2, + EOP1 = 3'h3, + EOP2 = 3'h4, + WAIT = 3'h5; + +reg TxReady_o; +reg [2:0] state, next_state; +reg tx_ready_d; +reg ld_sop_d; +reg ld_data_d; +reg ld_eop_d; +reg tx_ip; +reg tx_ip_sync; +reg [2:0] bit_cnt; +reg [7:0] hold_reg; +reg [7:0] hold_reg_d; + +reg sd_raw_o; +wire hold; +reg data_done; +reg sft_done; +reg sft_done_r; +wire sft_done_e; +reg ld_data; +wire eop_done; +reg [2:0] one_cnt; +wire stuff; +reg sd_bs_o; +reg sd_nrzi_o; +reg append_eop; +reg append_eop_sync1; +reg append_eop_sync2; +reg append_eop_sync3; +reg append_eop_sync4; +reg txdp, txdn; +reg txoe_r1, txoe_r2; +reg txoe; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) TxReady_o <= 1'b0; + else TxReady_o <= tx_ready_d & TxValid_i; + +always @(posedge clk) ld_data <= ld_data_d; + +/////////////////////////////////////////////////////////////////// +// +// Transmit in progress indicator +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) tx_ip <= 1'b0; + else + if(ld_sop_d) tx_ip <= 1'b1; + else + if(eop_done) tx_ip <= 1'b0; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) tx_ip_sync <= 1'b0; + else + if(fs_ce) tx_ip_sync <= tx_ip; + +// data_done helps us to catch cases where TxValid drops due to +// packet end and then gets re-asserted as a new packet starts. +// We might not see this because we are still transmitting. +// data_done should solve those cases ... +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) data_done <= 1'b0; + else + if(TxValid_i && ! tx_ip) data_done <= 1'b1; + else + if(!TxValid_i) data_done <= 1'b0; + +/////////////////////////////////////////////////////////////////// +// +// Shift Register +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) bit_cnt <= 3'h0; + else + if(!tx_ip_sync) bit_cnt <= 3'h0; + else + if(fs_ce && !hold) bit_cnt <= bit_cnt + 3'h1; + +assign hold = stuff; + +always @(posedge clk) + if(!tx_ip_sync) sd_raw_o <= 1'b0; + else + case(bit_cnt) // synopsys full_case parallel_case + 3'h0: sd_raw_o <= hold_reg_d[0]; + 3'h1: sd_raw_o <= hold_reg_d[1]; + 3'h2: sd_raw_o <= hold_reg_d[2]; + 3'h3: sd_raw_o <= hold_reg_d[3]; + 3'h4: sd_raw_o <= hold_reg_d[4]; + 3'h5: sd_raw_o <= hold_reg_d[5]; + 3'h6: sd_raw_o <= hold_reg_d[6]; + 3'h7: sd_raw_o <= hold_reg_d[7]; + endcase + +always @(posedge clk) + sft_done <= !hold & (bit_cnt == 3'h7); + +always @(posedge clk) + sft_done_r <= sft_done; + +assign sft_done_e = sft_done & !sft_done_r; + +// Out Data Hold Register +always @(posedge clk) + if(ld_sop_d) hold_reg <= 8'h80; + else + if(ld_data) hold_reg <= DataOut_i; + +always @(posedge clk) hold_reg_d <= hold_reg; + +/////////////////////////////////////////////////////////////////// +// +// Bit Stuffer +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) one_cnt <= 3'h0; + else + if(!tx_ip_sync) one_cnt <= 3'h0; + else + if(fs_ce) + begin + if(!sd_raw_o || stuff) one_cnt <= 3'h0; + else one_cnt <= one_cnt + 3'h1; + end + +assign stuff = (one_cnt==3'h6); + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) sd_bs_o <= 1'h0; + else + if(fs_ce) sd_bs_o <= !tx_ip_sync ? 1'b0 : (stuff ? 1'b0 : sd_raw_o); + +/////////////////////////////////////////////////////////////////// +// +// NRZI Encoder +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) sd_nrzi_o <= 1'b1; + else + if(!tx_ip_sync || !txoe_r1) sd_nrzi_o <= 1'b1; + else + if(fs_ce) sd_nrzi_o <= sd_bs_o ? sd_nrzi_o : ~sd_nrzi_o; + +/////////////////////////////////////////////////////////////////// +// +// EOP append logic +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) append_eop <= 1'b0; + else + if(ld_eop_d) append_eop <= 1'b1; + else + if(append_eop_sync2) append_eop <= 1'b0; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) append_eop_sync1 <= 1'b0; + else + if(fs_ce) append_eop_sync1 <= append_eop; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) append_eop_sync2 <= 1'b0; + else + if(fs_ce) append_eop_sync2 <= append_eop_sync1; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) append_eop_sync3 <= 1'b0; + else + if(fs_ce) append_eop_sync3 <= append_eop_sync2 | + (append_eop_sync3 & !append_eop_sync4); // Make sure always 2 bit wide + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) append_eop_sync4 <= 1'b0; + else + if(fs_ce) append_eop_sync4 <= append_eop_sync3; + +assign eop_done = append_eop_sync3; + +/////////////////////////////////////////////////////////////////// +// +// Output Enable Logic +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) txoe_r1 <= 1'b0; + else + if(fs_ce) txoe_r1 <= tx_ip_sync; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) txoe_r2 <= 1'b0; + else + if(fs_ce) txoe_r2 <= txoe_r1; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) txoe <= 1'b1; + else + if(fs_ce) txoe <= !(txoe_r1 | txoe_r2); + +/////////////////////////////////////////////////////////////////// +// +// Output Registers +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) txdp <= 1'b1; + else + if(fs_ce) txdp <= phy_mode ? + (!append_eop_sync3 & sd_nrzi_o) : + sd_nrzi_o; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) txdn <= 1'b0; + else + if(fs_ce) txdn <= phy_mode ? + (!append_eop_sync3 & ~sd_nrzi_o) : + append_eop_sync3; + +/////////////////////////////////////////////////////////////////// +// +// Tx Statemashine +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rst) +`else +always @(posedge clk) +`endif + if(!rst) state <= IDLE; + else state <= next_state; + +always @(state or TxValid_i or data_done or sft_done_e or eop_done or fs_ce) + begin + next_state = state; + tx_ready_d = 1'b0; + + ld_sop_d = 1'b0; + ld_data_d = 1'b0; + ld_eop_d = 1'b0; + + case(state) // synopsys full_case parallel_case + IDLE: + if(TxValid_i) + begin + ld_sop_d = 1'b1; + next_state = SOP; + end + SOP: + if(sft_done_e) + begin + tx_ready_d = 1'b1; + ld_data_d = 1'b1; + next_state = DATA; + end + DATA: + begin + if(!data_done && sft_done_e) + begin + ld_eop_d = 1'b1; + next_state = EOP1; + end + + if(data_done && sft_done_e) + begin + tx_ready_d = 1'b1; + ld_data_d = 1'b1; + end + end + EOP1: + if(eop_done) next_state = EOP2; + EOP2: + if(!eop_done && fs_ce) next_state = WAIT; + WAIT: + if(fs_ce) next_state = IDLE; + endcase + end + +endmodule + -- cgit v1.2.3