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/asicworld/README | 1 + tests/asicworld/code_hdl_models_GrayCounter.v | 33 + tests/asicworld/code_hdl_models_arbiter.v | 123 +++ tests/asicworld/code_hdl_models_arbiter_tb.v | 62 ++ tests/asicworld/code_hdl_models_cam.v | 60 ++ tests/asicworld/code_hdl_models_clk_div.v | 27 + tests/asicworld/code_hdl_models_clk_div_45.v | 54 + tests/asicworld/code_hdl_models_d_ff_gates.v | 29 + tests/asicworld/code_hdl_models_d_latch_gates.v | 15 + .../asicworld/code_hdl_models_decoder_2to4_gates.v | 14 + .../code_hdl_models_decoder_using_assign.v | 20 + .../asicworld/code_hdl_models_decoder_using_case.v | 43 + tests/asicworld/code_hdl_models_dff_async_reset.v | 30 + tests/asicworld/code_hdl_models_dff_sync_reset.v | 30 + tests/asicworld/code_hdl_models_dlatch_reset.v | 30 + .../asicworld/code_hdl_models_encoder_4to2_gates.v | 8 + .../asicworld/code_hdl_models_encoder_using_case.v | 42 + tests/asicworld/code_hdl_models_encoder_using_if.v | 58 + tests/asicworld/code_hdl_models_full_adder_gates.v | 18 + .../code_hdl_models_full_subtracter_gates.v | 20 + tests/asicworld/code_hdl_models_gray_counter.v | 33 + tests/asicworld/code_hdl_models_half_adder_gates.v | 14 + tests/asicworld/code_hdl_models_lfsr.v | 35 + tests/asicworld/code_hdl_models_lfsr_updown.v | 35 + tests/asicworld/code_hdl_models_misc1.v | 22 + tests/asicworld/code_hdl_models_mux21_switch.v | 22 + tests/asicworld/code_hdl_models_mux_2to1_gates.v | 18 + tests/asicworld/code_hdl_models_mux_using_assign.v | 22 + tests/asicworld/code_hdl_models_mux_using_case.v | 28 + tests/asicworld/code_hdl_models_mux_using_if.v | 29 + tests/asicworld/code_hdl_models_nand_switch.v | 14 + tests/asicworld/code_hdl_models_one_hot_cnt.v | 31 + tests/asicworld/code_hdl_models_parallel_crc.v | 53 + .../code_hdl_models_parity_using_assign.v | 21 + .../code_hdl_models_parity_using_bitwise.v | 16 + .../code_hdl_models_parity_using_function.v | 29 + .../code_hdl_models_pri_encoder_using_assign.v | 36 + tests/asicworld/code_hdl_models_ram_sp_ar_sw.v | 58 + tests/asicworld/code_hdl_models_ram_sp_sr_sw.v | 62 ++ tests/asicworld/code_hdl_models_rom_using_case.v | 42 + tests/asicworld/code_hdl_models_serial_crc.v | 54 + tests/asicworld/code_hdl_models_t_gate_switch.v | 11 + tests/asicworld/code_hdl_models_tff_async_reset.v | 27 + tests/asicworld/code_hdl_models_tff_sync_reset.v | 27 + tests/asicworld/code_hdl_models_uart.v | 154 +++ tests/asicworld/code_hdl_models_up_counter.v | 29 + tests/asicworld/code_hdl_models_up_counter_load.v | 32 + tests/asicworld/code_hdl_models_up_down_counter.v | 29 + tests/asicworld/code_specman_switch_fabric.v | 82 ++ tests/asicworld/code_tidbits_asyn_reset.v | 18 + tests/asicworld/code_tidbits_blocking.v | 17 + tests/asicworld/code_tidbits_fsm_using_always.v | 91 ++ tests/asicworld/code_tidbits_fsm_using_function.v | 94 ++ .../code_tidbits_fsm_using_single_always.v | 63 ++ tests/asicworld/code_tidbits_nonblocking.v | 17 + tests/asicworld/code_tidbits_reg_combo_example.v | 13 + tests/asicworld/code_tidbits_reg_seq_example.v | 15 + tests/asicworld/code_tidbits_syn_reset.v | 19 + tests/asicworld/code_tidbits_wire_example.v | 9 + tests/asicworld/code_verilog_tutorial_addbit.v | 24 + .../code_verilog_tutorial_always_example.v | 11 + tests/asicworld/code_verilog_tutorial_bus_con.v | 8 + tests/asicworld/code_verilog_tutorial_comment.v | 25 + tests/asicworld/code_verilog_tutorial_counter.v | 19 + tests/asicworld/code_verilog_tutorial_counter_tb.v | 113 ++ tests/asicworld/code_verilog_tutorial_d_ff.v | 14 + tests/asicworld/code_verilog_tutorial_decoder.v | 14 + .../code_verilog_tutorial_decoder_always.v | 20 + tests/asicworld/code_verilog_tutorial_escape_id.v | 14 + tests/asicworld/code_verilog_tutorial_explicit.v | 35 + .../code_verilog_tutorial_first_counter.v | 47 + .../code_verilog_tutorial_first_counter_tb.v | 36 + tests/asicworld/code_verilog_tutorial_flip_flop.v | 15 + tests/asicworld/code_verilog_tutorial_fsm_full.v | 114 ++ .../asicworld/code_verilog_tutorial_fsm_full_tb.v | 48 + tests/asicworld/code_verilog_tutorial_good_code.v | 18 + tests/asicworld/code_verilog_tutorial_if_else.v | 13 + tests/asicworld/code_verilog_tutorial_multiply.v | 8 + tests/asicworld/code_verilog_tutorial_mux_21.v | 9 + .../code_verilog_tutorial_n_out_primitive.v | 13 + .../asicworld/code_verilog_tutorial_parallel_if.v | 21 + tests/asicworld/code_verilog_tutorial_parity.v | 41 + .../code_verilog_tutorial_simple_function.v | 10 + tests/asicworld/code_verilog_tutorial_simple_if.v | 11 + .../asicworld/code_verilog_tutorial_task_global.v | 12 + tests/asicworld/code_verilog_tutorial_tri_buf.v | 9 + tests/asicworld/code_verilog_tutorial_v2k_reg.v | 24 + .../asicworld/code_verilog_tutorial_which_clock.v | 12 + tests/asicworld/run-test.sh | 3 + tests/hana/README | 14 + tests/hana/hana_vlib.v | 1139 ++++++++++++++++++++ tests/hana/run-test.sh | 3 + tests/hana/test_intermout_always_comb_1_test.v | 13 + tests/hana/test_intermout_always_comb_3_test.v | 10 + tests/hana/test_intermout_always_comb_4_test.v | 9 + tests/hana/test_intermout_always_comb_5_test.v | 11 + tests/hana/test_intermout_always_ff_3_test.v | 15 + tests/hana/test_intermout_always_ff_4_test.v | 11 + tests/hana/test_intermout_always_ff_5_test.v | 13 + tests/hana/test_intermout_always_ff_6_test.v | 7 + tests/hana/test_intermout_always_ff_8_test.v | 11 + tests/hana/test_intermout_always_ff_9_test.v | 14 + tests/hana/test_intermout_always_latch_1_test.v | 9 + tests/hana/test_intermout_bufrm_1_test.v | 4 + tests/hana/test_intermout_bufrm_2_test.v | 7 + tests/hana/test_intermout_bufrm_6_test.v | 22 + tests/hana/test_intermout_bufrm_7_test.v | 33 + tests/hana/test_intermout_exprs_add_test.v | 10 + tests/hana/test_intermout_exprs_binlogic_test.v | 13 + tests/hana/test_intermout_exprs_bitwiseneg_test.v | 5 + tests/hana/test_intermout_exprs_buffer_test.v | 9 + .../hana/test_intermout_exprs_condexpr_mux_test.v | 11 + .../test_intermout_exprs_condexpr_tribuf_test.v | 9 + tests/hana/test_intermout_exprs_const_test.v | 7 + tests/hana/test_intermout_exprs_constshift_test.v | 12 + tests/hana/test_intermout_exprs_div_test.v | 10 + tests/hana/test_intermout_exprs_logicneg_test.v | 7 + tests/hana/test_intermout_exprs_mod_test.v | 10 + tests/hana/test_intermout_exprs_mul_test.v | 10 + tests/hana/test_intermout_exprs_redand_test.v | 5 + tests/hana/test_intermout_exprs_redop_test.v | 16 + tests/hana/test_intermout_exprs_sub_test.v | 10 + tests/hana/test_intermout_exprs_unaryminus_test.v | 5 + tests/hana/test_intermout_exprs_unaryplus_test.v | 4 + tests/hana/test_intermout_exprs_varshift_test.v | 10 + tests/hana/test_parse2synthtrans_behavopt_1_test.v | 22 + tests/hana/test_parse2synthtrans_case_1_test.v | 26 + .../hana/test_parse2synthtrans_contassign_1_test.v | 7 + .../test_parse2synthtrans_module_basic0_test.v | 2 + .../hana/test_parse2synthtrans_operators_1_test.v | 11 + tests/hana/test_parse2synthtrans_param_1_test.v | 7 + .../test_parse2synthtrans_port_scalar_1_test.v | 6 + .../test_parse2synthtrans_port_vector_1_test.v | 9 + ...arse2synthtrans_v2k_comb_logic_sens_list_test.v | 9 + .../test_parser_constructs_module_basic1_test.v | 2 + .../test_parser_constructs_param_basic0_test.v | 10 + .../hana/test_parser_constructs_port_basic0_test.v | 8 + .../test_parser_directives_define_simpledef_test.v | 9 + tests/hana/test_parser_misc_operators_test.v | 29 + .../test_parser_v2k_comb_port_data_type_test.v | 6 + .../test_parser_v2k_comma_sep_sens_list_test.v | 9 + tests/hana/test_simulation_always_15_test.v | 5 + tests/hana/test_simulation_always_17_test.v | 13 + tests/hana/test_simulation_always_18_test.v | 10 + tests/hana/test_simulation_always_19_test.v | 11 + tests/hana/test_simulation_always_1_test.v | 5 + tests/hana/test_simulation_always_20_test.v | 15 + tests/hana/test_simulation_always_21_test.v | 11 + tests/hana/test_simulation_always_22_test.v | 7 + tests/hana/test_simulation_always_23_test.v | 14 + tests/hana/test_simulation_always_27_test.v | 13 + tests/hana/test_simulation_always_29_test.v | 9 + tests/hana/test_simulation_always_31_tt.v | 50 + tests/hana/test_simulation_and_1_test.v | 3 + tests/hana/test_simulation_and_2_test.v | 3 + tests/hana/test_simulation_and_3_test.v | 3 + tests/hana/test_simulation_and_4_test.v | 3 + tests/hana/test_simulation_and_5_test.v | 3 + tests/hana/test_simulation_and_6_test.v | 3 + tests/hana/test_simulation_and_7_test.v | 3 + tests/hana/test_simulation_buffer_1_test.v | 3 + tests/hana/test_simulation_buffer_2_test.v | 4 + tests/hana/test_simulation_buffer_3_test.v | 4 + tests/hana/test_simulation_decoder_2_test.v | 14 + tests/hana/test_simulation_decoder_3_test.v | 14 + tests/hana/test_simulation_decoder_4_test.v | 14 + tests/hana/test_simulation_decoder_5_test.v | 17 + tests/hana/test_simulation_decoder_6_test.v | 27 + tests/hana/test_simulation_decoder_7_test.v | 43 + tests/hana/test_simulation_decoder_8_test.v | 76 ++ tests/hana/test_simulation_inc_16_test.v | 5 + tests/hana/test_simulation_inc_1_test.v | 5 + tests/hana/test_simulation_inc_2_test.v | 5 + tests/hana/test_simulation_inc_32_test.v | 5 + tests/hana/test_simulation_inc_4_test.v | 5 + tests/hana/test_simulation_inc_8_test.v | 5 + tests/hana/test_simulation_mod_1_xx.v | 13 + tests/hana/test_simulation_mux_16_test.v | 22 + tests/hana/test_simulation_mux_2_test.v | 8 + tests/hana/test_simulation_mux_32_test.v | 39 + tests/hana/test_simulation_mux_4_test.v | 10 + tests/hana/test_simulation_mux_64_test.v | 71 ++ tests/hana/test_simulation_mux_8_test.v | 14 + tests/hana/test_simulation_nand_1_test.v | 3 + tests/hana/test_simulation_nand_3_test.v | 3 + tests/hana/test_simulation_nand_4_test.v | 3 + tests/hana/test_simulation_nand_5_test.v | 3 + tests/hana/test_simulation_nand_6_test.v | 3 + tests/hana/test_simulation_nor_1_test.v | 3 + tests/hana/test_simulation_nor_2_test.v | 3 + tests/hana/test_simulation_nor_3_test.v | 3 + tests/hana/test_simulation_nor_4_test.v | 3 + ...st_simulation_opt_constprop_contassign_1_test.v | 3 + tests/hana/test_simulation_or_1_test.v | 3 + tests/hana/test_simulation_or_2_test.v | 3 + tests/hana/test_simulation_or_3_test.v | 3 + tests/hana/test_simulation_or_4_test.v | 3 + tests/hana/test_simulation_or_5_test.v | 3 + tests/hana/test_simulation_or_6_test.v | 3 + tests/hana/test_simulation_seq_ff_1_test.v | 4 + tests/hana/test_simulation_seq_ff_2_test.v | 4 + tests/hana/test_simulation_shifter_left_16_test.v | 4 + tests/hana/test_simulation_shifter_left_32_test.v | 4 + tests/hana/test_simulation_shifter_left_4_test.v | 4 + tests/hana/test_simulation_shifter_left_64_test.v | 4 + tests/hana/test_simulation_shifter_left_8_test.v | 4 + tests/hana/test_simulation_shifter_right_16_test.v | 4 + tests/hana/test_simulation_shifter_right_32_test.v | 4 + tests/hana/test_simulation_shifter_right_4_test.v | 4 + tests/hana/test_simulation_shifter_right_64_test.v | 4 + tests/hana/test_simulation_shifter_right_8_test.v | 4 + tests/hana/test_simulation_sop_basic_10_test.v | 8 + tests/hana/test_simulation_sop_basic_11_test.v | 10 + tests/hana/test_simulation_sop_basic_12_test.v | 14 + tests/hana/test_simulation_sop_basic_18_test.v | 5 + tests/hana/test_simulation_sop_basic_3_test.v | 3 + tests/hana/test_simulation_sop_basic_7_test.v | 3 + tests/hana/test_simulation_sop_basic_8_test.v | 3 + tests/hana/test_simulation_sop_basic_9_test.v | 3 + tests/hana/test_simulation_techmap_and_19_tech.v | 7 + tests/hana/test_simulation_techmap_and_5_tech.v | 3 + tests/hana/test_simulation_techmap_buf_test.v | 3 + tests/hana/test_simulation_techmap_inv_test.v | 3 + tests/hana/test_simulation_techmap_mux_0_test.v | 8 + tests/hana/test_simulation_techmap_mux_128_test.v | 134 +++ tests/hana/test_simulation_techmap_mux_8_test.v | 14 + tests/hana/test_simulation_techmap_nand_19_tech.v | 11 + tests/hana/test_simulation_techmap_nand_2_tech.v | 11 + tests/hana/test_simulation_techmap_nand_5_tech.v | 11 + tests/hana/test_simulation_techmap_nor_19_tech.v | 11 + tests/hana/test_simulation_techmap_nor_2_tech.v | 11 + tests/hana/test_simulation_techmap_nor_5_tech.v | 11 + tests/hana/test_simulation_techmap_or_19_tech.v | 7 + tests/hana/test_simulation_techmap_or_5_tech.v | 3 + tests/hana/test_simulation_techmap_xnor_2_tech.v | 6 + tests/hana/test_simulation_techmap_xnor_5_tech.v | 6 + tests/hana/test_simulation_techmap_xor_19_tech.v | 3 + tests/hana/test_simulation_techmap_xor_2_tech.v | 6 + tests/hana/test_simulation_techmap_xor_5_tech.v | 6 + tests/hana/test_simulation_tribuf_2_test.v | 3 + tests/hana/test_simulation_xnor_1_test.v | 3 + tests/hana/test_simulation_xnor_2_test.v | 3 + tests/hana/test_simulation_xnor_3_test.v | 3 + tests/hana/test_simulation_xnor_4_test.v | 3 + tests/hana/test_simulation_xor_1_test.v | 3 + tests/hana/test_simulation_xor_2_test.v | 3 + tests/hana/test_simulation_xor_3_test.v | 3 + tests/hana/test_simulation_xor_4_test.v | 3 + tests/i2c_bench/i2c_master_bit_ctrl.v | 576 ++++++++++ tests/i2c_bench/i2c_master_byte_ctrl.v | 344 ++++++ tests/i2c_bench/i2c_master_defines.v | 59 + tests/i2c_bench/i2c_master_top.v | 301 ++++++ tests/i2c_bench/i2c_slave_model.v | 361 +++++++ tests/i2c_bench/run-test.sh | 50 + tests/i2c_bench/spi_slave_model.v | 125 +++ tests/i2c_bench/timescale.v | 2 + tests/i2c_bench/tst_bench_top.v | 468 ++++++++ tests/i2c_bench/wb_master_model.v | 205 ++++ 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 ++++++++ tests/no-icarus/README | 2 + tests/no-icarus/autowire.v | 25 + tests/no-icarus/var_range.v | 45 + tests/openmsp430/rtl/omsp_alu.v | 258 +++++ tests/openmsp430/rtl/omsp_and_gate.v | 89 ++ tests/openmsp430/rtl/omsp_clock_gate.v | 86 ++ tests/openmsp430/rtl/omsp_clock_module.v | 1058 ++++++++++++++++++ tests/openmsp430/rtl/omsp_clock_mux.v | 192 ++++ tests/openmsp430/rtl/omsp_dbg.v | 827 ++++++++++++++ tests/openmsp430/rtl/omsp_dbg_hwbrk.v | 282 +++++ tests/openmsp430/rtl/omsp_dbg_uart.v | 298 +++++ tests/openmsp430/rtl/omsp_execution_unit.v | 420 ++++++++ tests/openmsp430/rtl/omsp_frontend.v | 966 +++++++++++++++++ tests/openmsp430/rtl/omsp_mem_backbone.v | 275 +++++ tests/openmsp430/rtl/omsp_multiplier.v | 420 ++++++++ tests/openmsp430/rtl/omsp_register_file.v | 618 +++++++++++ tests/openmsp430/rtl/omsp_scan_mux.v | 75 ++ tests/openmsp430/rtl/omsp_sfr.v | 353 ++++++ tests/openmsp430/rtl/omsp_sync_cell.v | 80 ++ tests/openmsp430/rtl/omsp_sync_reset.v | 78 ++ tests/openmsp430/rtl/omsp_wakeup_cell.v | 108 ++ tests/openmsp430/rtl/omsp_watchdog.v | 556 ++++++++++ tests/openmsp430/rtl/openMSP430.v | 584 ++++++++++ tests/openmsp430/rtl/openMSP430_defines.v | 843 +++++++++++++++ tests/openmsp430/rtl/openMSP430_undefines.v | 732 +++++++++++++ tests/openmsp430/run-fm.do | 37 + tests/openmsp430/run-fm.sh | 5 + tests/openmsp430/run-synth.sh | 3 + tests/openmsp430/run-synth.ys | 11 + tests/openmsp430/sim_mul.v | 29 + tests/or1200/config.patch | 46 + tests/or1200/run-checkout.sh | 4 + tests/or1200/run-fm-mods.sh | 24 + tests/or1200/run-fm.do | 53 + tests/or1200/run-fm.sh | 5 + tests/or1200/run-synth.sh | 2 + tests/or1200/run-synth.ys | 11 + tests/or1200/run-vg.sh | 4 + tests/simple/aes_kexp128.v | 24 + tests/simple/dff_different_styles.v | 52 + tests/simple/fiedler-cooley.v | 33 + tests/simple/fsm.v | 69 ++ tests/simple/generate.v | 67 ++ tests/simple/i2c_master_tests.v | 62 ++ tests/simple/loops.v | 79 ++ tests/simple/mem2reg.v | 17 + tests/simple/memory.v | 19 + tests/simple/muxtree.v | 50 + tests/simple/omsp_dbg_uart.v | 34 + tests/simple/operators.v | 97 ++ tests/simple/paramods.v | 37 + tests/simple/process.v | 65 ++ tests/simple/run-test.sh | 3 + tests/simple/subbytes.v | 82 ++ tests/simple/task_func.v | 35 + tests/simple/usb_phy_tetsts.v | 36 + tests/simple/values.v | 44 + tests/tools/autotest.sh | 164 +++ tests/tools/cmp_tbdata.c | 67 ++ tests/tools/profiler.pl | 55 + tests/tools/rtlview.sh | 63 ++ tests/tools/vcdcd.pl | 201 ++++ 367 files changed, 28611 insertions(+) create mode 100644 tests/asicworld/README create mode 100644 tests/asicworld/code_hdl_models_GrayCounter.v create mode 100644 tests/asicworld/code_hdl_models_arbiter.v create mode 100644 tests/asicworld/code_hdl_models_arbiter_tb.v create mode 100644 tests/asicworld/code_hdl_models_cam.v create mode 100644 tests/asicworld/code_hdl_models_clk_div.v create mode 100644 tests/asicworld/code_hdl_models_clk_div_45.v create mode 100644 tests/asicworld/code_hdl_models_d_ff_gates.v create mode 100644 tests/asicworld/code_hdl_models_d_latch_gates.v create mode 100644 tests/asicworld/code_hdl_models_decoder_2to4_gates.v create mode 100644 tests/asicworld/code_hdl_models_decoder_using_assign.v create mode 100644 tests/asicworld/code_hdl_models_decoder_using_case.v create mode 100644 tests/asicworld/code_hdl_models_dff_async_reset.v create mode 100644 tests/asicworld/code_hdl_models_dff_sync_reset.v create mode 100644 tests/asicworld/code_hdl_models_dlatch_reset.v create mode 100644 tests/asicworld/code_hdl_models_encoder_4to2_gates.v create mode 100644 tests/asicworld/code_hdl_models_encoder_using_case.v create mode 100644 tests/asicworld/code_hdl_models_encoder_using_if.v create mode 100644 tests/asicworld/code_hdl_models_full_adder_gates.v create mode 100644 tests/asicworld/code_hdl_models_full_subtracter_gates.v create mode 100644 tests/asicworld/code_hdl_models_gray_counter.v create mode 100644 tests/asicworld/code_hdl_models_half_adder_gates.v create mode 100644 tests/asicworld/code_hdl_models_lfsr.v create mode 100644 tests/asicworld/code_hdl_models_lfsr_updown.v create mode 100644 tests/asicworld/code_hdl_models_misc1.v create mode 100644 tests/asicworld/code_hdl_models_mux21_switch.v create mode 100644 tests/asicworld/code_hdl_models_mux_2to1_gates.v create mode 100644 tests/asicworld/code_hdl_models_mux_using_assign.v create mode 100644 tests/asicworld/code_hdl_models_mux_using_case.v create mode 100644 tests/asicworld/code_hdl_models_mux_using_if.v create mode 100644 tests/asicworld/code_hdl_models_nand_switch.v create mode 100644 tests/asicworld/code_hdl_models_one_hot_cnt.v create mode 100644 tests/asicworld/code_hdl_models_parallel_crc.v create mode 100644 tests/asicworld/code_hdl_models_parity_using_assign.v create mode 100644 tests/asicworld/code_hdl_models_parity_using_bitwise.v create mode 100644 tests/asicworld/code_hdl_models_parity_using_function.v create mode 100644 tests/asicworld/code_hdl_models_pri_encoder_using_assign.v create mode 100644 tests/asicworld/code_hdl_models_ram_sp_ar_sw.v create mode 100644 tests/asicworld/code_hdl_models_ram_sp_sr_sw.v create mode 100644 tests/asicworld/code_hdl_models_rom_using_case.v create mode 100644 tests/asicworld/code_hdl_models_serial_crc.v create mode 100644 tests/asicworld/code_hdl_models_t_gate_switch.v create mode 100644 tests/asicworld/code_hdl_models_tff_async_reset.v create mode 100644 tests/asicworld/code_hdl_models_tff_sync_reset.v create mode 100644 tests/asicworld/code_hdl_models_uart.v create mode 100644 tests/asicworld/code_hdl_models_up_counter.v create mode 100644 tests/asicworld/code_hdl_models_up_counter_load.v create mode 100644 tests/asicworld/code_hdl_models_up_down_counter.v create mode 100644 tests/asicworld/code_specman_switch_fabric.v create mode 100644 tests/asicworld/code_tidbits_asyn_reset.v create mode 100644 tests/asicworld/code_tidbits_blocking.v create mode 100644 tests/asicworld/code_tidbits_fsm_using_always.v create mode 100644 tests/asicworld/code_tidbits_fsm_using_function.v create mode 100644 tests/asicworld/code_tidbits_fsm_using_single_always.v create mode 100644 tests/asicworld/code_tidbits_nonblocking.v create mode 100644 tests/asicworld/code_tidbits_reg_combo_example.v create mode 100644 tests/asicworld/code_tidbits_reg_seq_example.v create mode 100644 tests/asicworld/code_tidbits_syn_reset.v create mode 100644 tests/asicworld/code_tidbits_wire_example.v create mode 100644 tests/asicworld/code_verilog_tutorial_addbit.v create mode 100644 tests/asicworld/code_verilog_tutorial_always_example.v create mode 100644 tests/asicworld/code_verilog_tutorial_bus_con.v create mode 100644 tests/asicworld/code_verilog_tutorial_comment.v create mode 100644 tests/asicworld/code_verilog_tutorial_counter.v create mode 100644 tests/asicworld/code_verilog_tutorial_counter_tb.v create mode 100644 tests/asicworld/code_verilog_tutorial_d_ff.v create mode 100644 tests/asicworld/code_verilog_tutorial_decoder.v create mode 100644 tests/asicworld/code_verilog_tutorial_decoder_always.v create mode 100644 tests/asicworld/code_verilog_tutorial_escape_id.v create mode 100644 tests/asicworld/code_verilog_tutorial_explicit.v create mode 100644 tests/asicworld/code_verilog_tutorial_first_counter.v create mode 100644 tests/asicworld/code_verilog_tutorial_first_counter_tb.v create mode 100644 tests/asicworld/code_verilog_tutorial_flip_flop.v create mode 100644 tests/asicworld/code_verilog_tutorial_fsm_full.v create mode 100644 tests/asicworld/code_verilog_tutorial_fsm_full_tb.v create mode 100644 tests/asicworld/code_verilog_tutorial_good_code.v create mode 100644 tests/asicworld/code_verilog_tutorial_if_else.v create mode 100644 tests/asicworld/code_verilog_tutorial_multiply.v create mode 100644 tests/asicworld/code_verilog_tutorial_mux_21.v create mode 100644 tests/asicworld/code_verilog_tutorial_n_out_primitive.v create mode 100644 tests/asicworld/code_verilog_tutorial_parallel_if.v create mode 100644 tests/asicworld/code_verilog_tutorial_parity.v create mode 100644 tests/asicworld/code_verilog_tutorial_simple_function.v create mode 100644 tests/asicworld/code_verilog_tutorial_simple_if.v create mode 100644 tests/asicworld/code_verilog_tutorial_task_global.v create mode 100644 tests/asicworld/code_verilog_tutorial_tri_buf.v create mode 100644 tests/asicworld/code_verilog_tutorial_v2k_reg.v create mode 100644 tests/asicworld/code_verilog_tutorial_which_clock.v create mode 100755 tests/asicworld/run-test.sh create mode 100644 tests/hana/README create mode 100644 tests/hana/hana_vlib.v create mode 100755 tests/hana/run-test.sh create mode 100644 tests/hana/test_intermout_always_comb_1_test.v create mode 100644 tests/hana/test_intermout_always_comb_3_test.v create mode 100644 tests/hana/test_intermout_always_comb_4_test.v create mode 100644 tests/hana/test_intermout_always_comb_5_test.v create mode 100644 tests/hana/test_intermout_always_ff_3_test.v create mode 100644 tests/hana/test_intermout_always_ff_4_test.v create mode 100644 tests/hana/test_intermout_always_ff_5_test.v create mode 100644 tests/hana/test_intermout_always_ff_6_test.v create mode 100644 tests/hana/test_intermout_always_ff_8_test.v create mode 100644 tests/hana/test_intermout_always_ff_9_test.v create mode 100644 tests/hana/test_intermout_always_latch_1_test.v create mode 100644 tests/hana/test_intermout_bufrm_1_test.v create mode 100644 tests/hana/test_intermout_bufrm_2_test.v create mode 100644 tests/hana/test_intermout_bufrm_6_test.v create mode 100644 tests/hana/test_intermout_bufrm_7_test.v create mode 100644 tests/hana/test_intermout_exprs_add_test.v create mode 100644 tests/hana/test_intermout_exprs_binlogic_test.v create mode 100644 tests/hana/test_intermout_exprs_bitwiseneg_test.v create mode 100644 tests/hana/test_intermout_exprs_buffer_test.v create mode 100644 tests/hana/test_intermout_exprs_condexpr_mux_test.v create mode 100644 tests/hana/test_intermout_exprs_condexpr_tribuf_test.v create mode 100644 tests/hana/test_intermout_exprs_const_test.v create mode 100644 tests/hana/test_intermout_exprs_constshift_test.v create mode 100644 tests/hana/test_intermout_exprs_div_test.v create mode 100644 tests/hana/test_intermout_exprs_logicneg_test.v create mode 100644 tests/hana/test_intermout_exprs_mod_test.v create mode 100644 tests/hana/test_intermout_exprs_mul_test.v create mode 100644 tests/hana/test_intermout_exprs_redand_test.v create mode 100644 tests/hana/test_intermout_exprs_redop_test.v create mode 100644 tests/hana/test_intermout_exprs_sub_test.v create mode 100644 tests/hana/test_intermout_exprs_unaryminus_test.v create mode 100644 tests/hana/test_intermout_exprs_unaryplus_test.v create mode 100644 tests/hana/test_intermout_exprs_varshift_test.v create mode 100644 tests/hana/test_parse2synthtrans_behavopt_1_test.v create mode 100644 tests/hana/test_parse2synthtrans_case_1_test.v create mode 100644 tests/hana/test_parse2synthtrans_contassign_1_test.v create mode 100644 tests/hana/test_parse2synthtrans_module_basic0_test.v create mode 100644 tests/hana/test_parse2synthtrans_operators_1_test.v create mode 100644 tests/hana/test_parse2synthtrans_param_1_test.v create mode 100644 tests/hana/test_parse2synthtrans_port_scalar_1_test.v create mode 100644 tests/hana/test_parse2synthtrans_port_vector_1_test.v create mode 100644 tests/hana/test_parse2synthtrans_v2k_comb_logic_sens_list_test.v create mode 100644 tests/hana/test_parser_constructs_module_basic1_test.v create mode 100644 tests/hana/test_parser_constructs_param_basic0_test.v create mode 100644 tests/hana/test_parser_constructs_port_basic0_test.v create mode 100644 tests/hana/test_parser_directives_define_simpledef_test.v create mode 100644 tests/hana/test_parser_misc_operators_test.v create mode 100644 tests/hana/test_parser_v2k_comb_port_data_type_test.v create mode 100644 tests/hana/test_parser_v2k_comma_sep_sens_list_test.v create mode 100644 tests/hana/test_simulation_always_15_test.v create mode 100644 tests/hana/test_simulation_always_17_test.v create mode 100644 tests/hana/test_simulation_always_18_test.v create mode 100644 tests/hana/test_simulation_always_19_test.v create mode 100644 tests/hana/test_simulation_always_1_test.v create mode 100644 tests/hana/test_simulation_always_20_test.v create mode 100644 tests/hana/test_simulation_always_21_test.v create mode 100644 tests/hana/test_simulation_always_22_test.v create mode 100644 tests/hana/test_simulation_always_23_test.v create mode 100644 tests/hana/test_simulation_always_27_test.v create mode 100644 tests/hana/test_simulation_always_29_test.v create mode 100644 tests/hana/test_simulation_always_31_tt.v create mode 100644 tests/hana/test_simulation_and_1_test.v create mode 100644 tests/hana/test_simulation_and_2_test.v create mode 100644 tests/hana/test_simulation_and_3_test.v create mode 100644 tests/hana/test_simulation_and_4_test.v create mode 100644 tests/hana/test_simulation_and_5_test.v create mode 100644 tests/hana/test_simulation_and_6_test.v create mode 100644 tests/hana/test_simulation_and_7_test.v create mode 100644 tests/hana/test_simulation_buffer_1_test.v create mode 100644 tests/hana/test_simulation_buffer_2_test.v create mode 100644 tests/hana/test_simulation_buffer_3_test.v create mode 100644 tests/hana/test_simulation_decoder_2_test.v create mode 100644 tests/hana/test_simulation_decoder_3_test.v create mode 100644 tests/hana/test_simulation_decoder_4_test.v create mode 100644 tests/hana/test_simulation_decoder_5_test.v create mode 100644 tests/hana/test_simulation_decoder_6_test.v create mode 100644 tests/hana/test_simulation_decoder_7_test.v create mode 100644 tests/hana/test_simulation_decoder_8_test.v create mode 100644 tests/hana/test_simulation_inc_16_test.v create mode 100644 tests/hana/test_simulation_inc_1_test.v create mode 100644 tests/hana/test_simulation_inc_2_test.v create mode 100644 tests/hana/test_simulation_inc_32_test.v create mode 100644 tests/hana/test_simulation_inc_4_test.v create mode 100644 tests/hana/test_simulation_inc_8_test.v create mode 100644 tests/hana/test_simulation_mod_1_xx.v create mode 100644 tests/hana/test_simulation_mux_16_test.v create mode 100644 tests/hana/test_simulation_mux_2_test.v create mode 100644 tests/hana/test_simulation_mux_32_test.v create mode 100644 tests/hana/test_simulation_mux_4_test.v create mode 100644 tests/hana/test_simulation_mux_64_test.v create mode 100644 tests/hana/test_simulation_mux_8_test.v create mode 100644 tests/hana/test_simulation_nand_1_test.v create mode 100644 tests/hana/test_simulation_nand_3_test.v create mode 100644 tests/hana/test_simulation_nand_4_test.v create mode 100644 tests/hana/test_simulation_nand_5_test.v create mode 100644 tests/hana/test_simulation_nand_6_test.v create mode 100644 tests/hana/test_simulation_nor_1_test.v create mode 100644 tests/hana/test_simulation_nor_2_test.v create mode 100644 tests/hana/test_simulation_nor_3_test.v create mode 100644 tests/hana/test_simulation_nor_4_test.v create mode 100644 tests/hana/test_simulation_opt_constprop_contassign_1_test.v create mode 100644 tests/hana/test_simulation_or_1_test.v create mode 100644 tests/hana/test_simulation_or_2_test.v create mode 100644 tests/hana/test_simulation_or_3_test.v create mode 100644 tests/hana/test_simulation_or_4_test.v create mode 100644 tests/hana/test_simulation_or_5_test.v create mode 100644 tests/hana/test_simulation_or_6_test.v create mode 100644 tests/hana/test_simulation_seq_ff_1_test.v create mode 100644 tests/hana/test_simulation_seq_ff_2_test.v create mode 100644 tests/hana/test_simulation_shifter_left_16_test.v create mode 100644 tests/hana/test_simulation_shifter_left_32_test.v create mode 100644 tests/hana/test_simulation_shifter_left_4_test.v create mode 100644 tests/hana/test_simulation_shifter_left_64_test.v create mode 100644 tests/hana/test_simulation_shifter_left_8_test.v create mode 100644 tests/hana/test_simulation_shifter_right_16_test.v create mode 100644 tests/hana/test_simulation_shifter_right_32_test.v create mode 100644 tests/hana/test_simulation_shifter_right_4_test.v create mode 100644 tests/hana/test_simulation_shifter_right_64_test.v create mode 100644 tests/hana/test_simulation_shifter_right_8_test.v create mode 100644 tests/hana/test_simulation_sop_basic_10_test.v create mode 100644 tests/hana/test_simulation_sop_basic_11_test.v create mode 100644 tests/hana/test_simulation_sop_basic_12_test.v create mode 100644 tests/hana/test_simulation_sop_basic_18_test.v create mode 100644 tests/hana/test_simulation_sop_basic_3_test.v create mode 100644 tests/hana/test_simulation_sop_basic_7_test.v create mode 100644 tests/hana/test_simulation_sop_basic_8_test.v create mode 100644 tests/hana/test_simulation_sop_basic_9_test.v create mode 100644 tests/hana/test_simulation_techmap_and_19_tech.v create mode 100644 tests/hana/test_simulation_techmap_and_5_tech.v create mode 100644 tests/hana/test_simulation_techmap_buf_test.v create mode 100644 tests/hana/test_simulation_techmap_inv_test.v create mode 100644 tests/hana/test_simulation_techmap_mux_0_test.v create mode 100644 tests/hana/test_simulation_techmap_mux_128_test.v create mode 100644 tests/hana/test_simulation_techmap_mux_8_test.v create mode 100644 tests/hana/test_simulation_techmap_nand_19_tech.v create mode 100644 tests/hana/test_simulation_techmap_nand_2_tech.v create mode 100644 tests/hana/test_simulation_techmap_nand_5_tech.v create mode 100644 tests/hana/test_simulation_techmap_nor_19_tech.v create mode 100644 tests/hana/test_simulation_techmap_nor_2_tech.v create mode 100644 tests/hana/test_simulation_techmap_nor_5_tech.v create mode 100644 tests/hana/test_simulation_techmap_or_19_tech.v create mode 100644 tests/hana/test_simulation_techmap_or_5_tech.v create mode 100644 tests/hana/test_simulation_techmap_xnor_2_tech.v create mode 100644 tests/hana/test_simulation_techmap_xnor_5_tech.v create mode 100644 tests/hana/test_simulation_techmap_xor_19_tech.v create mode 100644 tests/hana/test_simulation_techmap_xor_2_tech.v create mode 100644 tests/hana/test_simulation_techmap_xor_5_tech.v create mode 100644 tests/hana/test_simulation_tribuf_2_test.v create mode 100644 tests/hana/test_simulation_xnor_1_test.v create mode 100644 tests/hana/test_simulation_xnor_2_test.v create mode 100644 tests/hana/test_simulation_xnor_3_test.v create mode 100644 tests/hana/test_simulation_xnor_4_test.v create mode 100644 tests/hana/test_simulation_xor_1_test.v create mode 100644 tests/hana/test_simulation_xor_2_test.v create mode 100644 tests/hana/test_simulation_xor_3_test.v create mode 100644 tests/hana/test_simulation_xor_4_test.v create mode 100644 tests/i2c_bench/i2c_master_bit_ctrl.v create mode 100644 tests/i2c_bench/i2c_master_byte_ctrl.v create mode 100644 tests/i2c_bench/i2c_master_defines.v create mode 100644 tests/i2c_bench/i2c_master_top.v create mode 100644 tests/i2c_bench/i2c_slave_model.v create mode 100755 tests/i2c_bench/run-test.sh create mode 100644 tests/i2c_bench/spi_slave_model.v create mode 100644 tests/i2c_bench/timescale.v create mode 100644 tests/i2c_bench/tst_bench_top.v create mode 100644 tests/i2c_bench/wb_master_model.v 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 create mode 100644 tests/no-icarus/README create mode 100644 tests/no-icarus/autowire.v create mode 100644 tests/no-icarus/var_range.v create mode 100644 tests/openmsp430/rtl/omsp_alu.v create mode 100644 tests/openmsp430/rtl/omsp_and_gate.v create mode 100644 tests/openmsp430/rtl/omsp_clock_gate.v create mode 100644 tests/openmsp430/rtl/omsp_clock_module.v create mode 100644 tests/openmsp430/rtl/omsp_clock_mux.v create mode 100644 tests/openmsp430/rtl/omsp_dbg.v create mode 100644 tests/openmsp430/rtl/omsp_dbg_hwbrk.v create mode 100644 tests/openmsp430/rtl/omsp_dbg_uart.v create mode 100644 tests/openmsp430/rtl/omsp_execution_unit.v create mode 100644 tests/openmsp430/rtl/omsp_frontend.v create mode 100644 tests/openmsp430/rtl/omsp_mem_backbone.v create mode 100644 tests/openmsp430/rtl/omsp_multiplier.v create mode 100644 tests/openmsp430/rtl/omsp_register_file.v create mode 100644 tests/openmsp430/rtl/omsp_scan_mux.v create mode 100644 tests/openmsp430/rtl/omsp_sfr.v create mode 100644 tests/openmsp430/rtl/omsp_sync_cell.v create mode 100644 tests/openmsp430/rtl/omsp_sync_reset.v create mode 100644 tests/openmsp430/rtl/omsp_wakeup_cell.v create mode 100644 tests/openmsp430/rtl/omsp_watchdog.v create mode 100644 tests/openmsp430/rtl/openMSP430.v create mode 100644 tests/openmsp430/rtl/openMSP430_defines.v create mode 100644 tests/openmsp430/rtl/openMSP430_undefines.v create mode 100644 tests/openmsp430/run-fm.do create mode 100644 tests/openmsp430/run-fm.sh create mode 100644 tests/openmsp430/run-synth.sh create mode 100644 tests/openmsp430/run-synth.ys create mode 100644 tests/openmsp430/sim_mul.v create mode 100644 tests/or1200/config.patch create mode 100644 tests/or1200/run-checkout.sh create mode 100644 tests/or1200/run-fm-mods.sh create mode 100644 tests/or1200/run-fm.do create mode 100644 tests/or1200/run-fm.sh create mode 100644 tests/or1200/run-synth.sh create mode 100644 tests/or1200/run-synth.ys create mode 100644 tests/or1200/run-vg.sh create mode 100644 tests/simple/aes_kexp128.v create mode 100644 tests/simple/dff_different_styles.v create mode 100644 tests/simple/fiedler-cooley.v create mode 100644 tests/simple/fsm.v create mode 100644 tests/simple/generate.v create mode 100644 tests/simple/i2c_master_tests.v create mode 100644 tests/simple/loops.v create mode 100644 tests/simple/mem2reg.v create mode 100644 tests/simple/memory.v create mode 100644 tests/simple/muxtree.v create mode 100644 tests/simple/omsp_dbg_uart.v create mode 100644 tests/simple/operators.v create mode 100644 tests/simple/paramods.v create mode 100644 tests/simple/process.v create mode 100755 tests/simple/run-test.sh create mode 100644 tests/simple/subbytes.v create mode 100644 tests/simple/task_func.v create mode 100644 tests/simple/usb_phy_tetsts.v create mode 100644 tests/simple/values.v create mode 100755 tests/tools/autotest.sh create mode 100644 tests/tools/cmp_tbdata.c create mode 100755 tests/tools/profiler.pl create mode 100755 tests/tools/rtlview.sh create mode 100755 tests/tools/vcdcd.pl (limited to 'tests') diff --git a/tests/asicworld/README b/tests/asicworld/README new file mode 100644 index 00000000..0e96edb7 --- /dev/null +++ b/tests/asicworld/README @@ -0,0 +1 @@ +Borrowed verilog examples from http://www.asic-world.com/. diff --git a/tests/asicworld/code_hdl_models_GrayCounter.v b/tests/asicworld/code_hdl_models_GrayCounter.v new file mode 100644 index 00000000..23f0da04 --- /dev/null +++ b/tests/asicworld/code_hdl_models_GrayCounter.v @@ -0,0 +1,33 @@ +//========================================== +// Function : Code Gray counter. +// Coder : Alex Claros F. +// Date : 15/May/2005. +//======================================= + +module GrayCounter + #(parameter COUNTER_WIDTH = 4) + + (output reg [COUNTER_WIDTH-1:0] GrayCount_out, //'Gray' code count output. + + input wire Enable_in, //Count enable. + input wire Clear_in, //Count reset. + + input wire Clk); + + /////////Internal connections & variables/////// + reg [COUNTER_WIDTH-1:0] BinaryCount; + + /////////Code/////////////////////// + + always @ (posedge Clk) + if (Clear_in) begin + BinaryCount <= {COUNTER_WIDTH{1'b 0}} + 1; //Gray count begins @ '1' with + GrayCount_out <= {COUNTER_WIDTH{1'b 0}}; // first 'Enable_in'. + end + else if (Enable_in) begin + BinaryCount <= BinaryCount + 1; + GrayCount_out <= {BinaryCount[COUNTER_WIDTH-1], + BinaryCount[COUNTER_WIDTH-2:0] ^ BinaryCount[COUNTER_WIDTH-1:1]}; + end + +endmodule diff --git a/tests/asicworld/code_hdl_models_arbiter.v b/tests/asicworld/code_hdl_models_arbiter.v new file mode 100644 index 00000000..978e1987 --- /dev/null +++ b/tests/asicworld/code_hdl_models_arbiter.v @@ -0,0 +1,123 @@ +//---------------------------------------------------- +// A four level, round-robin arbiter. This was +// orginally coded by WD Peterson in VHDL. +//---------------------------------------------------- +module arbiter ( + clk, + rst, + req3, + req2, + req1, + req0, + gnt3, + gnt2, + gnt1, + gnt0 +); +// --------------Port Declaration----------------------- +input clk; +input rst; +input req3; +input req2; +input req1; +input req0; +output gnt3; +output gnt2; +output gnt1; +output gnt0; + +//--------------Internal Registers---------------------- +wire [1:0] gnt ; +wire comreq ; +wire beg ; +wire [1:0] lgnt ; +wire lcomreq ; +reg lgnt0 ; +reg lgnt1 ; +reg lgnt2 ; +reg lgnt3 ; +reg lasmask ; +reg lmask0 ; +reg lmask1 ; +reg ledge ; + +//--------------Code Starts Here----------------------- +always @ (posedge clk) +if (rst) begin + lgnt0 <= 0; + lgnt1 <= 0; + lgnt2 <= 0; + lgnt3 <= 0; +end else begin + lgnt0 <=(~lcomreq & ~lmask1 & ~lmask0 & ~req3 & ~req2 & ~req1 & req0) + | (~lcomreq & ~lmask1 & lmask0 & ~req3 & ~req2 & req0) + | (~lcomreq & lmask1 & ~lmask0 & ~req3 & req0) + | (~lcomreq & lmask1 & lmask0 & req0 ) + | ( lcomreq & lgnt0 ); + lgnt1 <=(~lcomreq & ~lmask1 & ~lmask0 & req1) + | (~lcomreq & ~lmask1 & lmask0 & ~req3 & ~req2 & req1 & ~req0) + | (~lcomreq & lmask1 & ~lmask0 & ~req3 & req1 & ~req0) + | (~lcomreq & lmask1 & lmask0 & req1 & ~req0) + | ( lcomreq & lgnt1); + lgnt2 <=(~lcomreq & ~lmask1 & ~lmask0 & req2 & ~req1) + | (~lcomreq & ~lmask1 & lmask0 & req2) + | (~lcomreq & lmask1 & ~lmask0 & ~req3 & req2 & ~req1 & ~req0) + | (~lcomreq & lmask1 & lmask0 & req2 & ~req1 & ~req0) + | ( lcomreq & lgnt2); + lgnt3 <=(~lcomreq & ~lmask1 & ~lmask0 & req3 & ~req2 & ~req1) + | (~lcomreq & ~lmask1 & lmask0 & req3 & ~req2) + | (~lcomreq & lmask1 & ~lmask0 & req3) + | (~lcomreq & lmask1 & lmask0 & req3 & ~req2 & ~req1 & ~req0) + | ( lcomreq & lgnt3); +end + +//---------------------------------------------------- +// lasmask state machine. +//---------------------------------------------------- +assign beg = (req3 | req2 | req1 | req0) & ~lcomreq; +always @ (posedge clk) +begin + lasmask <= (beg & ~ledge & ~lasmask); + ledge <= (beg & ~ledge & lasmask) + | (beg & ledge & ~lasmask); +end + +//---------------------------------------------------- +// comreq logic. +//---------------------------------------------------- +assign lcomreq = ( req3 & lgnt3 ) + | ( req2 & lgnt2 ) + | ( req1 & lgnt1 ) + | ( req0 & lgnt0 ); + +//---------------------------------------------------- +// Encoder logic. +//---------------------------------------------------- +assign lgnt = {(lgnt3 | lgnt2),(lgnt3 | lgnt1)}; + +//---------------------------------------------------- +// lmask register. +//---------------------------------------------------- +always @ (posedge clk ) +if( rst ) begin + lmask1 <= 0; + lmask0 <= 0; +end else if(lasmask) begin + lmask1 <= lgnt[1]; + lmask0 <= lgnt[0]; +end else begin + lmask1 <= lmask1; + lmask0 <= lmask0; +end + +assign comreq = lcomreq; +assign gnt = lgnt; +//---------------------------------------------------- +// Drive the outputs +//---------------------------------------------------- +assign gnt3 = lgnt3; +assign gnt2 = lgnt2; +assign gnt1 = lgnt1; +assign gnt0 = lgnt0; + +endmodule diff --git a/tests/asicworld/code_hdl_models_arbiter_tb.v b/tests/asicworld/code_hdl_models_arbiter_tb.v new file mode 100644 index 00000000..5e7bf46b --- /dev/null +++ b/tests/asicworld/code_hdl_models_arbiter_tb.v @@ -0,0 +1,62 @@ +module testbench (); + +reg clk; +reg rst; +reg req3; +reg req2; +reg req1; +reg req0; +wire gnt3; +wire gnt2; +wire gnt1; +wire gnt0; + +// Clock generator +always #1 clk = ~clk; + +initial begin + $dumpfile ("arbiter.vcd"); + $dumpvars(); + clk = 0; + rst = 1; + req0 = 0; + req1 = 0; + req2 = 0; + req3 = 0; + #10 rst = 0; + repeat (1) @ (posedge clk); + req0 <= 1; + repeat (1) @ (posedge clk); + req0 <= 0; + repeat (1) @ (posedge clk); + req0 <= 1; + req1 <= 1; + repeat (1) @ (posedge clk); + req2 <= 1; + req1 <= 0; + repeat (1) @ (posedge clk); + req3 <= 1; + req2 <= 0; + repeat (1) @ (posedge clk); + req3 <= 0; + repeat (1) @ (posedge clk); + req0 <= 0; + repeat (1) @ (posedge clk); + #10 $finish; +end + +// Connect the DUT +arbiter U ( + clk, + rst, + req3, + req2, + req1, + req0, + gnt3, + gnt2, + gnt1, + gnt0 +); + +endmodule diff --git a/tests/asicworld/code_hdl_models_cam.v b/tests/asicworld/code_hdl_models_cam.v new file mode 100644 index 00000000..0cebc07c --- /dev/null +++ b/tests/asicworld/code_hdl_models_cam.v @@ -0,0 +1,60 @@ +//----------------------------------------------------- +// Design Name : cam +// File Name : cam.v +// Function : CAM +// Coder : Deepak Kumar Tala +//----------------------------------------------------- +module cam ( +clk , // Cam clock +cam_enable , // Cam enable +cam_data_in , // Cam data to match +cam_hit_out , // Cam match has happened +cam_addr_out // Cam output address +); + +parameter ADDR_WIDTH = 8; +parameter DEPTH = 1 << ADDR_WIDTH; +//------------Input Ports-------------- +input clk; +input cam_enable; +input [DEPTH-1:0] cam_data_in; +//----------Output Ports-------------- +output cam_hit_out; +output [ADDR_WIDTH-1:0] cam_addr_out; +//------------Internal Variables-------- +reg [ADDR_WIDTH-1:0] cam_addr_out; +reg cam_hit_out; +reg [ADDR_WIDTH-1:0] cam_addr_combo; +reg cam_hit_combo; +reg found_match; +integer i; +//-------------Code Starts Here------- +always @(cam_data_in) begin + cam_addr_combo = {ADDR_WIDTH{1'b0}}; + found_match = 1'b0; + cam_hit_combo = 1'b0; + for (i=0; i 0 && rx_cnt < 9) begin + rx_reg[rx_cnt - 1] <= rx_d2; + end + if (rx_cnt == 9) begin + rx_busy <= 0; + // Check if End of frame received correctly + if (rx_d2 == 0) begin + rx_frame_err <= 1; + end else begin + rx_empty <= 0; + rx_frame_err <= 0; + // Check if last rx data was not unloaded, + rx_over_run <= (rx_empty) ? 0 : 1; + end + end + end + end + end + end + if (!rx_enable) begin + rx_busy <= 0; + end +end + +// UART TX Logic +always @ (posedge txclk or posedge reset) +if (reset) begin + tx_reg <= 0; + tx_empty <= 1; + tx_over_run <= 0; + tx_out <= 1; + tx_cnt <= 0; +end else begin + if (ld_tx_data) begin + if (!tx_empty) begin + tx_over_run <= 0; + end else begin + tx_reg <= tx_data; + tx_empty <= 0; + end + end + if (tx_enable && !tx_empty) begin + tx_cnt <= tx_cnt + 1; + if (tx_cnt == 0) begin + tx_out <= 0; + end + if (tx_cnt > 0 && tx_cnt < 9) begin + tx_out <= tx_reg[tx_cnt -1]; + end + if (tx_cnt == 9) begin + tx_out <= 1; + tx_cnt <= 0; + tx_empty <= 1; + end + end + if (!tx_enable) begin + tx_cnt <= 0; + end +end + +endmodule diff --git a/tests/asicworld/code_hdl_models_up_counter.v b/tests/asicworld/code_hdl_models_up_counter.v new file mode 100644 index 00000000..ffe67099 --- /dev/null +++ b/tests/asicworld/code_hdl_models_up_counter.v @@ -0,0 +1,29 @@ +//----------------------------------------------------- +// Design Name : up_counter +// File Name : up_counter.v +// Function : Up counter +// Coder  : Deepak +//----------------------------------------------------- +module up_counter ( +out , // Output of the counter +enable , // enable for counter +clk , // clock Input +reset // reset Input +); +//----------Output Ports-------------- + output [7:0] out; +//------------Input Ports-------------- + input enable, clk, reset; +//------------Internal Variables-------- + reg [7:0] out; +//-------------Code Starts Here------- +always @(posedge clk) +if (reset) begin + out <= 8'b0 ; +end else if (enable) begin + out <= out + 1; +end + + +endmodule + diff --git a/tests/asicworld/code_hdl_models_up_counter_load.v b/tests/asicworld/code_hdl_models_up_counter_load.v new file mode 100644 index 00000000..92ad895a --- /dev/null +++ b/tests/asicworld/code_hdl_models_up_counter_load.v @@ -0,0 +1,32 @@ +//----------------------------------------------------- +// Design Name : up_counter_load +// File Name : up_counter_load.v +// Function : Up counter with load +// Coder : Deepak Kumar Tala +//----------------------------------------------------- +module up_counter_load ( +out , // Output of the counter +data , // Parallel load for the counter +load , // Parallel load enable +enable , // Enable counting +clk , // clock input +reset // reset input +); +//----------Output Ports-------------- +output [7:0] out; +//------------Input Ports-------------- +input [7:0] data; +input load, enable, clk, reset; +//------------Internal Variables-------- +reg [7:0] out; +//-------------Code Starts Here------- +always @(posedge clk) +if (reset) begin + out <= 8'b0 ; +end else if (load) begin + out <= data; +end else if (enable) begin + out <= out + 1; +end + +endmodule diff --git a/tests/asicworld/code_hdl_models_up_down_counter.v b/tests/asicworld/code_hdl_models_up_down_counter.v new file mode 100644 index 00000000..fff2982a --- /dev/null +++ b/tests/asicworld/code_hdl_models_up_down_counter.v @@ -0,0 +1,29 @@ +//----------------------------------------------------- +// Design Name : up_down_counter +// File Name : up_down_counter.v +// Function : Up down counter +// Coder : Deepak Kumar Tala +//----------------------------------------------------- +module up_down_counter ( +out , // Output of the counter +up_down , // up_down control for counter +clk , // clock input +reset // reset input +); +//----------Output Ports-------------- +output [7:0] out; +//------------Input Ports-------------- +input up_down, clk, reset; +//------------Internal Variables-------- +reg [7:0] out; +//-------------Code Starts Here------- +always @(posedge clk) +if (reset) begin // active high reset + out <= 8'b0 ; +end else if (up_down) begin + out <= out + 1; +end else begin + out <= out - 1; +end + +endmodule diff --git a/tests/asicworld/code_specman_switch_fabric.v b/tests/asicworld/code_specman_switch_fabric.v new file mode 100644 index 00000000..1ac7ee70 --- /dev/null +++ b/tests/asicworld/code_specman_switch_fabric.v @@ -0,0 +1,82 @@ +module switch_fabric( + clk, reset, data_in0, data_in1, data_in2, + data_in3, data_in4, data_in5, data_in_valid0, + data_in_valid1, data_in_valid2, data_in_valid3, + data_in_valid4, data_in_valid5, data_out0, + data_out1, data_out2, data_out3, data_out4, + data_out5, data_out_ack0, data_out_ack1, + data_out_ack2, data_out_ack3, data_out_ack4, + data_out_ack5 +); + +input clk, reset; +input [7:0] data_in0, data_in1, data_in2, data_in3; +input [7:0] data_in4, data_in5; +input data_in_valid0, data_in_valid1, data_in_valid2; +input [7:0] data_in_valid3, data_in_valid4, data_in_valid5; +output [7:0] data_out0, data_out1, data_out2, data_out3; +output [7:0] data_out4, data_out5; +output data_out_ack0, data_out_ack1, data_out_ack2; +output [7:0] data_out_ack3, data_out_ack4, data_out_ack5; + +(* gentb_clock *) +wire clk; + +switch port_0 ( .clk(clk), .reset(reset), .data_in(data_in0), + .data_in_valid(data_in_valid0), .data_out(data_out0), + .data_out_ack(data_out_ack0)); + +switch port_1 ( .clk(clk), .reset(reset), .data_in(data_in1), + .data_in_valid(data_in_valid1), .data_out(data_out1), + .data_out_ack(data_out_ack1)); + +switch port_2 ( .clk(clk), .reset(reset), .data_in(data_in2), + .data_in_valid(data_in_valid2), .data_out(data_out2), . + data_out_ack(data_out_ack2)); + +switch port_3 ( .clk(clk), .reset(reset), .data_in(data_in3), + .data_in_valid(data_in_valid3), .data_out(data_out3), + .data_out_ack(data_out_ack3)); + +switch port_4 ( .clk(clk), .reset(reset), .data_in(data_in4), + .data_in_valid(data_in_valid4), .data_out(data_out4), + .data_out_ack(data_out_ack4)); + +switch port_5 ( .clk(clk), .reset(reset), .data_in(data_in5), + .data_in_valid(data_in_valid5), .data_out(data_out5), + .data_out_ack(data_out_ack5)); + +endmodule + +module switch ( + clk, + reset, + data_in, + data_in_valid, + data_out, + data_out_ack +); + +input clk; +input reset; +input [7:0] data_in; +input data_in_valid; +output [7:0] data_out; +output data_out_ack; + +reg [7:0] data_out; +reg data_out_ack; + +always @ (posedge clk) +if (reset) begin + data_out <= 0; + data_out_ack <= 0; +end else if (data_in_valid) begin + data_out <= data_in; + data_out_ack <= 1; +end else begin + data_out <= 0; + data_out_ack <= 0; +end + +endmodule diff --git a/tests/asicworld/code_tidbits_asyn_reset.v b/tests/asicworld/code_tidbits_asyn_reset.v new file mode 100644 index 00000000..58e47c56 --- /dev/null +++ b/tests/asicworld/code_tidbits_asyn_reset.v @@ -0,0 +1,18 @@ +module asyn_reset(clk,reset,a,c); + input clk; + input reset; + input a; + output c; + + wire clk; + wire reset; + wire a; + reg c; + +always @ (posedge clk or posedge reset) + if ( reset == 1'b1) begin + c <= 0; + end else begin + c <= a; + end +endmodule diff --git a/tests/asicworld/code_tidbits_blocking.v b/tests/asicworld/code_tidbits_blocking.v new file mode 100644 index 00000000..e13b72cc --- /dev/null +++ b/tests/asicworld/code_tidbits_blocking.v @@ -0,0 +1,17 @@ +module blocking (clk,a,c); +input clk; +input a; +output c; + +wire clk; +wire a; +reg c; +reg b; + +always @ (posedge clk ) +begin + b = a; + c = b; +end + +endmodule diff --git a/tests/asicworld/code_tidbits_fsm_using_always.v b/tests/asicworld/code_tidbits_fsm_using_always.v new file mode 100644 index 00000000..8a8775b9 --- /dev/null +++ b/tests/asicworld/code_tidbits_fsm_using_always.v @@ -0,0 +1,91 @@ +//----------------------------------------------------- +// This is FSM demo program using always block +// Design Name : fsm_using_always +// File Name : fsm_using_always.v +//----------------------------------------------------- +module fsm_using_always ( +clock , // clock +reset , // Active high, syn reset +req_0 , // Request 0 +req_1 , // Request 1 +gnt_0 , // Grant 0 +gnt_1 +); +//-------------Input Ports----------------------------- +input clock,reset,req_0,req_1; + //-------------Output Ports---------------------------- +output gnt_0,gnt_1; +//-------------Input ports Data Type------------------- +wire clock,reset,req_0,req_1; +//-------------Output Ports Data Type------------------ +reg gnt_0,gnt_1; +//-------------Internal Constants-------------------------- +parameter SIZE = 3 ; +parameter IDLE = 3'b001,GNT0 = 3'b010,GNT1 = 3'b100 ; +//-------------Internal Variables--------------------------- +reg [SIZE-1:0] state ;// Seq part of the FSM +reg [SIZE-1:0] next_state ;// combo part of FSM +//----------Code startes Here------------------------ +always @ (state or req_0 or req_1) +begin : FSM_COMBO + next_state = 3'b000; + case(state) + IDLE : if (req_0 == 1'b1) begin + next_state = GNT0; + end else if (req_1 == 1'b1) begin + next_state= GNT1; + end else begin + next_state = IDLE; + end + GNT0 : if (req_0 == 1'b1) begin + next_state = GNT0; + end else begin + next_state = IDLE; + end + GNT1 : if (req_1 == 1'b1) begin + next_state = GNT1; + end else begin + next_state = IDLE; + end + default : next_state = IDLE; + endcase +end +//----------Seq Logic----------------------------- +always @ (posedge clock) +begin : FSM_SEQ + if (reset == 1'b1) begin + state <= #1 IDLE; + end else begin + state <= #1 next_state; + end +end +//----------Output Logic----------------------------- +always @ (posedge clock) +begin : OUTPUT_LOGIC +if (reset == 1'b1) begin + gnt_0 <= #1 1'b0; + gnt_1 <= #1 1'b0; +end +else begin + case(state) + IDLE : begin + gnt_0 <= #1 1'b0; + gnt_1 <= #1 1'b0; + end + GNT0 : begin + gnt_0 <= #1 1'b1; + gnt_1 <= #1 1'b0; + end + GNT1 : begin + gnt_0 <= #1 1'b0; + gnt_1 <= #1 1'b1; + end + default : begin + gnt_0 <= #1 1'b0; + gnt_1 <= #1 1'b0; + end + endcase +end +end // End Of Block OUTPUT_LOGIC + +endmodule // End of Module arbiter diff --git a/tests/asicworld/code_tidbits_fsm_using_function.v b/tests/asicworld/code_tidbits_fsm_using_function.v new file mode 100644 index 00000000..404498a0 --- /dev/null +++ b/tests/asicworld/code_tidbits_fsm_using_function.v @@ -0,0 +1,94 @@ +//----------------------------------------------------- +// This is FSM demo program using function +// Design Name : fsm_using_function +// File Name : fsm_using_function.v +//----------------------------------------------------- +module fsm_using_function ( +clock , // clock +reset , // Active high, syn reset +req_0 , // Request 0 +req_1 , // Request 1 +gnt_0 , // Grant 0 +gnt_1 +); +//-------------Input Ports----------------------------- +input clock,reset,req_0,req_1; + //-------------Output Ports---------------------------- +output gnt_0,gnt_1; +//-------------Input ports Data Type------------------- +wire clock,reset,req_0,req_1; +//-------------Output Ports Data Type------------------ +reg gnt_0,gnt_1; +//-------------Internal Constants-------------------------- +parameter SIZE = 3 ; +parameter IDLE = 3'b001,GNT0 = 3'b010,GNT1 = 3'b100 ; +//-------------Internal Variables--------------------------- +reg [SIZE-1:0] state ;// Seq part of the FSM +wire [SIZE-1:0] next_state ;// combo part of FSM +//----------Code startes Here------------------------ +assign next_state = fsm_function(state, req_0, req_1); +//----------Function for Combo Logic----------------- +function [SIZE-1:0] fsm_function; + input [SIZE-1:0] state ; + input req_0 ; + input req_1 ; + case(state) + IDLE : if (req_0 == 1'b1) begin + fsm_function = GNT0; + end else if (req_1 == 1'b1) begin + fsm_function= GNT1; + end else begin + fsm_function = IDLE; + end + GNT0 : if (req_0 == 1'b1) begin + fsm_function = GNT0; + end else begin + fsm_function = IDLE; + end + GNT1 : if (req_1 == 1'b1) begin + fsm_function = GNT1; + end else begin + fsm_function = IDLE; + end + default : fsm_function = IDLE; + endcase +endfunction +//----------Seq Logic----------------------------- +always @ (posedge clock) +begin : FSM_SEQ + if (reset == 1'b1) begin + state <= #1 IDLE; + end else begin + state <= #1 next_state; + end +end +//----------Output Logic----------------------------- +always @ (posedge clock) +begin : OUTPUT_LOGIC +if (reset == 1'b1) begin + gnt_0 <= #1 1'b0; + gnt_1 <= #1 1'b0; +end +else begin + case(state) + IDLE : begin + gnt_0 <= #1 1'b0; + gnt_1 <= #1 1'b0; + end + GNT0 : begin + gnt_0 <= #1 1'b1; + gnt_1 <= #1 1'b0; + end + GNT1 : begin + gnt_0 <= #1 1'b0; + gnt_1 <= #1 1'b1; + end + default : begin + gnt_0 <= #1 1'b0; + gnt_1 <= #1 1'b0; + end + endcase +end +end // End Of Block OUTPUT_LOGIC + +endmodule // End of Module arbiter diff --git a/tests/asicworld/code_tidbits_fsm_using_single_always.v b/tests/asicworld/code_tidbits_fsm_using_single_always.v new file mode 100644 index 00000000..67cc0884 --- /dev/null +++ b/tests/asicworld/code_tidbits_fsm_using_single_always.v @@ -0,0 +1,63 @@ +//==================================================== +// This is FSM demo program using single always +// for both seq and combo logic +// Design Name : fsm_using_single_always +// File Name : fsm_using_single_always.v +//===================================================== +module fsm_using_single_always ( +clock , // clock +reset , // Active high, syn reset +req_0 , // Request 0 +req_1 , // Request 1 +gnt_0 , // Grant 0 +gnt_1 +); +//=============Input Ports============================= +input clock,reset,req_0,req_1; + //=============Output Ports=========================== +output gnt_0,gnt_1; +//=============Input ports Data Type=================== +wire clock,reset,req_0,req_1; +//=============Output Ports Data Type================== +reg gnt_0,gnt_1; +//=============Internal Constants====================== +parameter SIZE = 3 ; +parameter IDLE = 3'b001,GNT0 = 3'b010,GNT1 = 3'b100 ; +//=============Internal Variables====================== +reg [SIZE-1:0] state ;// Seq part of the FSM +reg [SIZE-1:0] next_state ;// combo part of FSM +//==========Code startes Here========================== +always @ (posedge clock) +begin : FSM +if (reset == 1'b1) begin + state <= #1 IDLE; + gnt_0 <= 0; + gnt_1 <= 0; +end else + case(state) + IDLE : if (req_0 == 1'b1) begin + state <= #1 GNT0; + gnt_0 <= 1; + end else if (req_1 == 1'b1) begin + gnt_1 <= 1; + state <= #1 GNT1; + end else begin + state <= #1 IDLE; + end + GNT0 : if (req_0 == 1'b1) begin + state <= #1 GNT0; + end else begin + gnt_0 <= 0; + state <= #1 IDLE; + end + GNT1 : if (req_1 == 1'b1) begin + state <= #1 GNT1; + end else begin + gnt_1 <= 0; + state <= #1 IDLE; + end + default : state <= #1 IDLE; +endcase +end + +endmodule // End of Module arbiter diff --git a/tests/asicworld/code_tidbits_nonblocking.v b/tests/asicworld/code_tidbits_nonblocking.v new file mode 100644 index 00000000..4a0d365e --- /dev/null +++ b/tests/asicworld/code_tidbits_nonblocking.v @@ -0,0 +1,17 @@ +module nonblocking (clk,a,c); +input clk; +input a; +output c; + +wire clk; +wire a; +reg c; +reg b; + +always @ (posedge clk ) +begin + b <= a; + c <= b; +end + +endmodule diff --git a/tests/asicworld/code_tidbits_reg_combo_example.v b/tests/asicworld/code_tidbits_reg_combo_example.v new file mode 100644 index 00000000..9689788c --- /dev/null +++ b/tests/asicworld/code_tidbits_reg_combo_example.v @@ -0,0 +1,13 @@ +module reg_combo_example( a, b, y); +input a, b; +output y; + +reg y; +wire a, b; + +always @ ( a or b) +begin + y = a & b; +end + +endmodule diff --git a/tests/asicworld/code_tidbits_reg_seq_example.v b/tests/asicworld/code_tidbits_reg_seq_example.v new file mode 100644 index 00000000..458c8792 --- /dev/null +++ b/tests/asicworld/code_tidbits_reg_seq_example.v @@ -0,0 +1,15 @@ +module reg_seq_example( clk, reset, d, q); +input clk, reset, d; +output q; + +reg q; +wire clk, reset, d; + +always @ (posedge clk or posedge reset) +if (reset) begin + q <= 1'b0; +end else begin + q <= d; +end + +endmodule diff --git a/tests/asicworld/code_tidbits_syn_reset.v b/tests/asicworld/code_tidbits_syn_reset.v new file mode 100644 index 00000000..994771b1 --- /dev/null +++ b/tests/asicworld/code_tidbits_syn_reset.v @@ -0,0 +1,19 @@ +module syn_reset (clk,reset,a,c); + input clk; + input reset; + input a; + output c; + + wire clk; + wire reset; + wire a; + reg c; + +always @ (posedge clk ) + if ( reset == 1'b1) begin + c <= 0; + end else begin + c <= a; + end + +endmodule diff --git a/tests/asicworld/code_tidbits_wire_example.v b/tests/asicworld/code_tidbits_wire_example.v new file mode 100644 index 00000000..577a535d --- /dev/null +++ b/tests/asicworld/code_tidbits_wire_example.v @@ -0,0 +1,9 @@ +module wire_example( a, b, y); + input a, b; + output y; + + wire a, b, y; + + assign y = a & b; + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_addbit.v b/tests/asicworld/code_verilog_tutorial_addbit.v new file mode 100644 index 00000000..22063b05 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_addbit.v @@ -0,0 +1,24 @@ +module addbit ( +a , // first input +b , // Second input +ci , // Carry input +sum , // sum output +co // carry output +); +//Input declaration +input a; +input b; +input ci; +//Ouput declaration +output sum; +output co; +//Port Data types +wire a; +wire b; +wire ci; +wire sum; +wire co; +//Code starts here +assign {co,sum} = a + b + ci; + +endmodule // End of Module addbit diff --git a/tests/asicworld/code_verilog_tutorial_always_example.v b/tests/asicworld/code_verilog_tutorial_always_example.v new file mode 100644 index 00000000..8b0fc206 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_always_example.v @@ -0,0 +1,11 @@ +module always_example(); +reg clk,reset,enable,q_in,data; + +always @ (posedge clk) +if (reset) begin + data <= 0; +end else if (enable) begin + data <= q_in; +end + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_bus_con.v b/tests/asicworld/code_verilog_tutorial_bus_con.v new file mode 100644 index 00000000..b100c813 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_bus_con.v @@ -0,0 +1,8 @@ +module bus_con (a,b, y); + input [3:0] a, b; + output [7:0] y; + wire [7:0] y; + + assign y = {a,b}; + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_comment.v b/tests/asicworld/code_verilog_tutorial_comment.v new file mode 100644 index 00000000..1cc0eb42 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_comment.v @@ -0,0 +1,25 @@ +/* This is a + Multi line comment + example */ +module addbit ( +a, +b, +ci, +sum, +co); + +// Input Ports Single line comment +input a; +input b; +input ci; +// Output ports +output sum; +output co; +// Data Types +wire a; +wire b; +wire ci; +wire sum; +wire co; + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_counter.v b/tests/asicworld/code_verilog_tutorial_counter.v new file mode 100644 index 00000000..53451974 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_counter.v @@ -0,0 +1,19 @@ +//----------------------------------------------------- +// Design Name : counter +// File Name : counter.v +// Function : 4 bit up counter +// Coder : Deepak +//----------------------------------------------------- +module counter (clk, reset, enable, count); +input clk, reset, enable; +output [3:0] count; +reg [3:0] count; + +always @ (posedge clk) +if (reset == 1'b1) begin + count <= 0; +end else if ( enable == 1'b1) begin + count <= count + 1; +end + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_counter_tb.v b/tests/asicworld/code_verilog_tutorial_counter_tb.v new file mode 100644 index 00000000..10477938 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_counter_tb.v @@ -0,0 +1,113 @@ +/////////////////////////////////////////////////////////////////////////// +// MODULE : counter_tb // +// TOP MODULE : -- // +// // +// PURPOSE : 4-bit up counter test bench // +// // +// DESIGNER : Deepak Kumar Tala // +// // +// Revision History // +// // +// DEVELOPMENT HISTORY : // +// Rev0.0 : Jan 03, 2003 // +// Initial Revision // +// // +/////////////////////////////////////////////////////////////////////////// +module testbench; + +reg clk, reset, enable; +wire [3:0] count; +reg dut_error; + +counter U0 ( +.clk (clk), +.reset (reset), +.enable (enable), +.count (count) +); + +event reset_enable; +event terminate_sim; + +initial +begin + $display ("###################################################"); + clk = 0; + reset = 0; + enable = 0; + dut_error = 0; +end + +always + #5 clk = !clk; + +initial +begin + $dumpfile ("counter.vcd"); + $dumpvars; +end + + +initial +@ (terminate_sim) begin + $display ("Terminating simulation"); + if (dut_error == 0) begin + $display ("Simulation Result : PASSED"); + end + else begin + $display ("Simulation Result : FAILED"); + end + $display ("###################################################"); + #1 $finish; +end + + + +event reset_done; + +initial +forever begin + @ (reset_enable); + @ (negedge clk) + $display ("Applying reset"); + reset = 1; + @ (negedge clk) + reset = 0; + $display ("Came out of Reset"); + -> reset_done; +end + +initial begin + #10 -> reset_enable; + @ (reset_done); + @ (negedge clk); + enable = 1; + repeat (5) + begin + @ (negedge clk); + end + enable = 0; + #5 -> terminate_sim; +end + + +reg [3:0] count_compare; + +always @ (posedge clk) +if (reset == 1'b1) + count_compare <= 0; +else if ( enable == 1'b1) + count_compare <= count_compare + 1; + + + +always @ (negedge clk) +if (count_compare != count) begin + $display ("DUT ERROR AT TIME%d",$time); + $display ("Expected value %d, Got Value %d", count_compare, count); + dut_error = 1; + #5 -> terminate_sim; +end + +endmodule + diff --git a/tests/asicworld/code_verilog_tutorial_d_ff.v b/tests/asicworld/code_verilog_tutorial_d_ff.v new file mode 100644 index 00000000..7a408360 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_d_ff.v @@ -0,0 +1,14 @@ +// D flip-flop Code +module d_ff ( d, clk, q, q_bar); +input d ,clk; +output q, q_bar; +wire d ,clk; +reg q, q_bar; + +always @ (posedge clk) +begin + q <= d; + q_bar <= !d; +end + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_decoder.v b/tests/asicworld/code_verilog_tutorial_decoder.v new file mode 100644 index 00000000..5efdbd7e --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_decoder.v @@ -0,0 +1,14 @@ +module decoder (in,out); +input [2:0] in; +output [7:0] out; +wire [7:0] out; +assign out = (in == 3'b000 ) ? 8'b0000_0001 : +(in == 3'b001 ) ? 8'b0000_0010 : +(in == 3'b010 ) ? 8'b0000_0100 : +(in == 3'b011 ) ? 8'b0000_1000 : +(in == 3'b100 ) ? 8'b0001_0000 : +(in == 3'b101 ) ? 8'b0010_0000 : +(in == 3'b110 ) ? 8'b0100_0000 : +(in == 3'b111 ) ? 8'b1000_0000 : 8'h00; + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_decoder_always.v b/tests/asicworld/code_verilog_tutorial_decoder_always.v new file mode 100644 index 00000000..4418ec70 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_decoder_always.v @@ -0,0 +1,20 @@ +module decoder_always (in,out); +input [2:0] in; +output [7:0] out; +reg [7:0] out; + +always @ (in) +begin + out = 0; + case (in) + 3'b001 : out = 8'b0000_0001; + 3'b010 : out = 8'b0000_0010; + 3'b011 : out = 8'b0000_0100; + 3'b100 : out = 8'b0000_1000; + 3'b101 : out = 8'b0001_0000; + 3'b110 : out = 8'b0100_0000; + 3'b111 : out = 8'b1000_0000; + endcase +end + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_escape_id.v b/tests/asicworld/code_verilog_tutorial_escape_id.v new file mode 100644 index 00000000..6c33da17 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_escape_id.v @@ -0,0 +1,14 @@ +// There must be white space after the +// string which uses escape character +module \1dff ( +q, // Q output +\q~ , // Q_out output +d, // D input +cl$k, // CLOCK input +\reset* // Reset input +); + +input d, cl$k, \reset* ; +output q, \q~ ; + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_explicit.v b/tests/asicworld/code_verilog_tutorial_explicit.v new file mode 100644 index 00000000..88427ff0 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_explicit.v @@ -0,0 +1,35 @@ +module explicit(); +reg clk,d,rst,pre; +wire q; + +// Here q_bar is not connected +// We can connect ports in any order +dff u0 ( +.q (q), +.d (d), +.clk (clk), +.q_bar (), +.rst (rst), +.pre (pre) +); + +endmodule + +// D fli-flop +module dff (q, q_bar, clk, d, rst, pre); +input clk, d, rst, pre; +output q, q_bar; +reg q; + +assign q_bar = ~q; + +always @ (posedge clk) +if (rst == 1'b1) begin + q <= 0; +end else if (pre == 1'b1) begin + q <= 1; +end else begin + q <= d; +end + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_first_counter.v b/tests/asicworld/code_verilog_tutorial_first_counter.v new file mode 100644 index 00000000..d35d4aac --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_first_counter.v @@ -0,0 +1,47 @@ +//----------------------------------------------------- +// This is my second Verilog Design +// Design Name : first_counter +// File Name : first_counter.v +// Function : This is a 4 bit up-counter with +// Synchronous active high reset and +// with active high enable signal +//----------------------------------------------------- +module first_counter ( +clock , // Clock input of the design +reset , // active high, synchronous Reset input +enable , // Active high enable signal for counter +counter_out // 4 bit vector output of the counter +); // End of port list +//-------------Input Ports----------------------------- +input clock ; +input reset ; +input enable ; +//-------------Output Ports---------------------------- +output [3:0] counter_out ; +//-------------Input ports Data Type------------------- +// By rule all the input ports should be wires +wire clock ; +wire reset ; +wire enable ; +//-------------Output Ports Data Type------------------ +// Output port can be a storage element (reg) or a wire +reg [3:0] counter_out ; + +//------------Code Starts Here------------------------- +// Since this counter is a positive edge trigged one, +// We trigger the below block with respect to positive +// edge of the clock. +always @ (posedge clock) +begin : COUNTER // Block Name + // At every rising edge of clock we check if reset is active + // If active, we load the counter output with 4'b0000 + if (reset == 1'b1) begin + counter_out <= 4'b0000; + end + // If enable is active, then we increment the counter + else if (enable == 1'b1) begin + counter_out <= counter_out + 1; + end +end // End of Block COUNTER + +endmodule // End of Module counter diff --git a/tests/asicworld/code_verilog_tutorial_first_counter_tb.v b/tests/asicworld/code_verilog_tutorial_first_counter_tb.v new file mode 100644 index 00000000..f065732b --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_first_counter_tb.v @@ -0,0 +1,36 @@ +module testbench(); +// Declare inputs as regs and outputs as wires +reg clock, reset, enable; +wire [3:0] counter_out; + +// Initialize all variables +initial begin + $display ("time\t clk reset enable counter"); + $monitor ("%g\t %b %b %b %b", + $time, clock, reset, enable, counter_out); + clock = 1; // initial value of clock + reset = 0; // initial value of reset + enable = 0; // initial value of enable + #5 reset = 1; // Assert the reset + #10 reset = 0; // De-assert the reset + #10 enable = 1; // Assert enable + #100 enable = 0; // De-assert enable + #5 $finish; // Terminate simulation +end + +// Clock generator +initial begin + #1; + forever + #5 clock = ~clock; // Toggle clock every 5 ticks +end + +// Connect DUT to test bench +first_counter U_counter ( +clock, +reset, +enable, +counter_out +); + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_flip_flop.v b/tests/asicworld/code_verilog_tutorial_flip_flop.v new file mode 100644 index 00000000..ed2e88c2 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_flip_flop.v @@ -0,0 +1,15 @@ +module flif_flop (clk,reset, q, d); +input clk, reset, d; +output q; +reg q; + +always @ (posedge clk ) +begin + if (reset == 1) begin + q <= 0; + end else begin + q <= d; + end +end + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_fsm_full.v b/tests/asicworld/code_verilog_tutorial_fsm_full.v new file mode 100644 index 00000000..fd2d559b --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_fsm_full.v @@ -0,0 +1,114 @@ +module fsm_full( +clock , // Clock +reset , // Active high reset +req_0 , // Active high request from agent 0 +req_1 , // Active high request from agent 1 +req_2 , // Active high request from agent 2 +req_3 , // Active high request from agent 3 +gnt_0 , // Active high grant to agent 0 +gnt_1 , // Active high grant to agent 1 +gnt_2 , // Active high grant to agent 2 +gnt_3 // Active high grant to agent 3 +); +// Port declaration here +input clock ; // Clock +input reset ; // Active high reset +input req_0 ; // Active high request from agent 0 +input req_1 ; // Active high request from agent 1 +input req_2 ; // Active high request from agent 2 +input req_3 ; // Active high request from agent 3 +output gnt_0 ; // Active high grant to agent 0 +output gnt_1 ; // Active high grant to agent 1 +output gnt_2 ; // Active high grant to agent 2 +output gnt_3 ; // Active high grant to agent + +// Internal Variables +reg gnt_0 ; // Active high grant to agent 0 +reg gnt_1 ; // Active high grant to agent 1 +reg gnt_2 ; // Active high grant to agent 2 +reg gnt_3 ; // Active high grant to agent + +parameter [2:0] IDLE = 3'b000; +parameter [2:0] GNT0 = 3'b001; +parameter [2:0] GNT1 = 3'b010; +parameter [2:0] GNT2 = 3'b011; +parameter [2:0] GNT3 = 3'b100; + +reg [2:0] state, next_state; + +always @ (state or req_0 or req_1 or req_2 or req_3) +begin + next_state = 0; + case(state) + IDLE : if (req_0 == 1'b1) begin + next_state = GNT0; + end else if (req_1 == 1'b1) begin + next_state= GNT1; + end else if (req_2 == 1'b1) begin + next_state= GNT2; + end else if (req_3 == 1'b1) begin + next_state= GNT3; + end else begin + next_state = IDLE; + end + GNT0 : if (req_0 == 1'b0) begin + next_state = IDLE; + end else begin + next_state = GNT0; + end + GNT1 : if (req_1 == 1'b0) begin + next_state = IDLE; + end else begin + next_state = GNT1; + end + GNT2 : if (req_2 == 1'b0) begin + next_state = IDLE; + end else begin + next_state = GNT2; + end + GNT3 : if (req_3 == 1'b0) begin + next_state = IDLE; + end else begin + next_state = GNT3; + end + default : next_state = IDLE; + endcase +end + +always @ (posedge clock) +begin : OUTPUT_LOGIC + if (reset) begin + gnt_0 <= 1'b0; + gnt_1 <= 1'b0; + gnt_2 <= 1'b0; + gnt_3 <= 1'b0; + state <= IDLE; + end else begin + state <= next_state; + case(state) + IDLE : begin + gnt_0 <= 1'b0; + gnt_1 <= 1'b0; + gnt_2 <= 1'b0; + gnt_3 <= 1'b0; + end + GNT0 : begin + gnt_0 <= 1'b1; + end + GNT1 : begin + gnt_1 <= 1'b1; + end + GNT2 : begin + gnt_2 <= 1'b1; + end + GNT3 : begin + gnt_3 <= 1'b1; + end + default : begin + state <= IDLE; + end + endcase + end +end + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_fsm_full_tb.v b/tests/asicworld/code_verilog_tutorial_fsm_full_tb.v new file mode 100644 index 00000000..0097b1c9 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_fsm_full_tb.v @@ -0,0 +1,48 @@ +module testbench(); +reg clock , reset ; +reg req_0 , req_1 , req_2 , req_3; +wire gnt_0 , gnt_1 , gnt_2 , gnt_3 ; + +initial begin + $display("Time\t R0 R1 R2 R3 G0 G1 G2 G3"); + $monitor("%g\t %b %b %b %b %b %b %b %b", + $time, req_0, req_1, req_2, req_3, gnt_0, gnt_1, gnt_2, gnt_3); + clock = 0; + reset = 0; + req_0 = 0; + req_1 = 0; + req_2 = 0; + req_3 = 0; + #10 reset = 1; + #10 reset = 0; + #10 req_0 = 1; + #20 req_0 = 0; + #10 req_1 = 1; + #20 req_1 = 0; + #10 req_2 = 1; + #20 req_2 = 0; + #10 req_3 = 1; + #20 req_3 = 0; + #10 $finish; +end + +initial begin + #1; + forever + #2 clock = ~clock; +end + +fsm_full U_fsm_full( +clock , // Clock +reset , // Active high reset +req_0 , // Active high request from agent 0 +req_1 , // Active high request from agent 1 +req_2 , // Active high request from agent 2 +req_3 , // Active high request from agent 3 +gnt_0 , // Active high grant to agent 0 +gnt_1 , // Active high grant to agent 1 +gnt_2 , // Active high grant to agent 2 +gnt_3 // Active high grant to agent 3 +); + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_good_code.v b/tests/asicworld/code_verilog_tutorial_good_code.v new file mode 100644 index 00000000..6ba77644 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_good_code.v @@ -0,0 +1,18 @@ + module addbit ( + a, + b, + ci, + sum, + co); + input a; + input b; + input ci; + output sum; + output co; + wire a; + wire b; + wire ci; + wire sum; + wire co; + + endmodule diff --git a/tests/asicworld/code_verilog_tutorial_if_else.v b/tests/asicworld/code_verilog_tutorial_if_else.v new file mode 100644 index 00000000..19b91d3f --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_if_else.v @@ -0,0 +1,13 @@ +module if_else(); + +reg dff; +wire clk,din,reset; + +always @ (posedge clk) +if (reset) begin + dff <= 0; +end else begin + dff <= din; +end + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_multiply.v b/tests/asicworld/code_verilog_tutorial_multiply.v new file mode 100644 index 00000000..1912e1e2 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_multiply.v @@ -0,0 +1,8 @@ +module muliply (a,product); + input [3:0] a; + output [4:0] product; + wire [4:0] product; + + assign product = a << 1; + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_mux_21.v b/tests/asicworld/code_verilog_tutorial_mux_21.v new file mode 100644 index 00000000..a6a0d35e --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_mux_21.v @@ -0,0 +1,9 @@ +module mux_21 (a,b,sel,y); + input a, b; + output y; + input sel; + wire y; + + assign y = (sel) ? b : a; + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_n_out_primitive.v b/tests/asicworld/code_verilog_tutorial_n_out_primitive.v new file mode 100644 index 00000000..814385a4 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_n_out_primitive.v @@ -0,0 +1,13 @@ +module n_out_primitive(); + +wire out,out_0,out_1,out_2,out_3,out_a,out_b,out_c; +wire in; + +// one output Buffer gate +buf u_buf0 (out,in); +// four output Buffer gate +buf u_buf1 (out_0, out_1, out_2, out_3, in); +// three output Invertor gate +not u_not0 (out_a, out_b, out_c, in); + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_parallel_if.v b/tests/asicworld/code_verilog_tutorial_parallel_if.v new file mode 100644 index 00000000..1dbe737e --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_parallel_if.v @@ -0,0 +1,21 @@ +module parallel_if(); + +reg [3:0] counter; +wire clk,reset,enable, up_en, down_en; + +always @ (posedge clk) +// If reset is asserted +if (reset == 1'b0) begin + counter <= 4'b0000; +end else begin + // If counter is enable and up count is mode + if (enable == 1'b1 && up_en == 1'b1) begin + counter <= counter + 1'b1; + end + // If counter is enable and down count is mode + if (enable == 1'b1 && down_en == 1'b1) begin + counter <= counter - 1'b1; + end +end + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_parity.v b/tests/asicworld/code_verilog_tutorial_parity.v new file mode 100644 index 00000000..764396c2 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_parity.v @@ -0,0 +1,41 @@ +//----------------------------------------------------- +// This is simple parity Program +// Design Name : parity +// File Name : parity.v +// Function : This program shows how a verilog +// primitive/module port connection are done +// Coder : Deepak +//----------------------------------------------------- +module parity ( +a , // First input +b , // Second input +c , // Third Input +d , // Fourth Input +y // Parity output +); + +// Input Declaration +input a ; +input b ; +input c ; +input d ; +// Ouput Declaration +output y ; +// port data types +wire a ; +wire b ; +wire c ; +wire d ; +wire y ; +// Internal variables +wire out_0 ; +wire out_1 ; + +// Code starts Here +xor u0 (out_0,a,b); + +xor u1 (out_1,c,d); + +xor u2 (y,out_0,out_1); + +endmodule // End Of Module parity diff --git a/tests/asicworld/code_verilog_tutorial_simple_function.v b/tests/asicworld/code_verilog_tutorial_simple_function.v new file mode 100644 index 00000000..5818a1d4 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_simple_function.v @@ -0,0 +1,10 @@ +module simple_function(); + +function myfunction; +input a, b, c, d; +begin + myfunction = ((a+b) + (c-d)); +end +endfunction + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_simple_if.v b/tests/asicworld/code_verilog_tutorial_simple_if.v new file mode 100644 index 00000000..a68cc4a8 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_simple_if.v @@ -0,0 +1,11 @@ +module simple_if(); + +reg latch; +wire enable,din; + +always @ (enable or din) +if (enable) begin + latch <= din; +end + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_task_global.v b/tests/asicworld/code_verilog_tutorial_task_global.v new file mode 100644 index 00000000..3ae86279 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_task_global.v @@ -0,0 +1,12 @@ +module task_global(); + +reg [7:0] temp_out; +reg [7:0] temp_in; + +task convert; +begin + temp_out = (9/5) *( temp_in + 32); +end +endtask + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_tri_buf.v b/tests/asicworld/code_verilog_tutorial_tri_buf.v new file mode 100644 index 00000000..a55b29ca --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_tri_buf.v @@ -0,0 +1,9 @@ +module tri_buf (a,b,enable); + input a; + output b; + input enable; + wire b; + +assign b = (enable) ? a : 1'bz; + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_v2k_reg.v b/tests/asicworld/code_verilog_tutorial_v2k_reg.v new file mode 100644 index 00000000..537a9e85 --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_v2k_reg.v @@ -0,0 +1,24 @@ +module v2k_reg(); + +// v2k allows to init variables +reg a = 0; +// Here only last variable is set to 0, i.e d = 0 +// Rest b, c are set to x +reg b, c, d = 0; +// reg data type can be signed in v2k +// We can assign with signed constants +reg signed [7:0] data = 8'shF0; + +// Function can return signed values +// Its ports can contain signed ports +function signed [7:0] adder; + input a_in; + input b_in; + input c_in; + input signed [7:0] data_in; + begin + adder = a_in + b_in + c_in + data_in; + end +endfunction + +endmodule diff --git a/tests/asicworld/code_verilog_tutorial_which_clock.v b/tests/asicworld/code_verilog_tutorial_which_clock.v new file mode 100644 index 00000000..418a2cfa --- /dev/null +++ b/tests/asicworld/code_verilog_tutorial_which_clock.v @@ -0,0 +1,12 @@ +module which_clock (x,y,q,d); +input x,y,d; +output q; +reg q; + +always @ (posedge x or posedge y) + if (x) + q <= 1'b0; + else + q <= d; + +endmodule diff --git a/tests/asicworld/run-test.sh b/tests/asicworld/run-test.sh new file mode 100755 index 00000000..bf27d15f --- /dev/null +++ b/tests/asicworld/run-test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +make -C ../.. || exit 1 +exec bash ../tools/autotest.sh *.v diff --git a/tests/hana/README b/tests/hana/README new file mode 100644 index 00000000..37049405 --- /dev/null +++ b/tests/hana/README @@ -0,0 +1,14 @@ + +This test cases are copied from the hana project: +https://sourceforge.net/projects/sim-sim/ + +** Copy tests from hana: ** +while read fn; do cp -v $fn ALL_TESTS/${fn//\//_}; done < <(find test -name '*.v' ! -name '*_gold.v') + +** Eliminate test's we can't parse atm: ** +rm -f test_synthesizability*.v +rm -f test_parse2synthtrans_latch_1_test.v +rm -f test_parse2synthtrans_always_1_test.v +rm -f test_parse2synthtrans_always_2_test.v +for x in test_*.v; do ../../yosys -b "" $x || rm $x; done + diff --git a/tests/hana/hana_vlib.v b/tests/hana/hana_vlib.v new file mode 100644 index 00000000..fc82f138 --- /dev/null +++ b/tests/hana/hana_vlib.v @@ -0,0 +1,1139 @@ +/* +Copyright (C) 2009-2010 Parvez Ahmad +Written by Parvez Ahmad . + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . */ + + +module BUF (input in, output out); + +assign out = in; + +endmodule + +module TRIBUF(input in, enable, output out); + +assign out = enable ? in : 1'bz; + +endmodule + +module INV(input in, output out); + +assign out = ~in; + +endmodule + +module AND2 #(parameter SIZE = 2) (input [SIZE-1:0] in, output out); + +assign out = ∈ + +endmodule + +module AND3 #(parameter SIZE = 3) (input [SIZE-1:0] in, output out); + +assign out = ∈ + +endmodule + +module AND4 #(parameter SIZE = 4) (input [SIZE-1:0] in, output out); + +assign out = ∈ + +endmodule + +module OR2 #(parameter SIZE = 2) (input [SIZE-1:0] in, output out); + +assign out = |in; + +endmodule + +module OR3 #(parameter SIZE = 3) (input [SIZE-1:0] in, output out); + +assign out = |in; + +endmodule + +module OR4 #(parameter SIZE = 4) (input [SIZE-1:0] in, output out); + +assign out = |in; + +endmodule + + +module NAND2 #(parameter SIZE = 2) (input [SIZE-1:0] in, output out); + +assign out = ~∈ + +endmodule + +module NAND3 #(parameter SIZE = 3) (input [SIZE-1:0] in, output out); + +assign out = ~∈ + +endmodule + +module NAND4 #(parameter SIZE = 4) (input [SIZE-1:0] in, output out); + +assign out = ~∈ + +endmodule + +module NOR2 #(parameter SIZE = 2) (input [SIZE-1:0] in, output out); + +assign out = ~|in; + +endmodule + +module NOR3 #(parameter SIZE = 3) (input [SIZE-1:0] in, output out); + +assign out = ~|in; + +endmodule + +module NOR4 #(parameter SIZE = 4) (input [SIZE-1:0] in, output out); + +assign out = ~|in; + +endmodule + + +module XOR2 #(parameter SIZE = 2) (input [SIZE-1:0] in, output out); + +assign out = ^in; + +endmodule + +module XOR3 #(parameter SIZE = 3) (input [SIZE-1:0] in, output out); + +assign out = ^in; + +endmodule + +module XOR4 #(parameter SIZE = 4) (input [SIZE-1:0] in, output out); + +assign out = ^in; + +endmodule + + +module XNOR2 #(parameter SIZE = 2) (input [SIZE-1:0] in, output out); + +assign out = ~^in; + +endmodule + +module XNOR3 #(parameter SIZE = 3) (input [SIZE-1:0] in, output out); + +assign out = ~^in; + +endmodule + +module XNOR4 #(parameter SIZE = 4) (input [SIZE-1:0] in, output out); + +assign out = ~^in; + +endmodule + +module DEC1 (input in, enable, output reg [1:0] out); + +always @(in or enable) + if(!enable) + out = 2'b00; + else begin + case (in) + 1'b0 : out = 2'b01; + 1'b1 : out = 2'b10; + endcase + end +endmodule + +module DEC2 (input [1:0] in, input enable, output reg [3:0] out); + +always @(in or enable) + if(!enable) + out = 4'b0000; + else begin + case (in) + 2'b00 : out = 4'b0001; + 2'b01 : out = 4'b0010; + 2'b10 : out = 4'b0100; + 2'b11 : out = 4'b1000; + endcase + end +endmodule + +module DEC3 (input [2:0] in, input enable, output reg [7:0] out); + +always @(in or enable) + if(!enable) + out = 8'b00000000; + else begin + case (in) + 3'b000 : out = 8'b00000001; + 3'b001 : out = 8'b00000010; + 3'b010 : out = 8'b00000100; + 3'b011 : out = 8'b00001000; + 3'b100 : out = 8'b00010000; + 3'b101 : out = 8'b00100000; + 3'b110 : out = 8'b01000000; + 3'b111 : out = 8'b10000000; + endcase + end +endmodule + +module DEC4 (input [3:0] in, input enable, output reg [15:0] out); + +always @(in or enable) + if(!enable) + out = 16'b0000000000000000; + else begin + case (in) + 4'b0000 : out = 16'b0000000000000001; + 4'b0001 : out = 16'b0000000000000010; + 4'b0010 : out = 16'b0000000000000100; + 4'b0011 : out = 16'b0000000000001000; + 4'b0100 : out = 16'b0000000000010000; + 4'b0101 : out = 16'b0000000000100000; + 4'b0110 : out = 16'b0000000001000000; + 4'b0111 : out = 16'b0000000010000000; + 4'b1000 : out = 16'b0000000100000000; + 4'b1001 : out = 16'b0000001000000000; + 4'b1010 : out = 16'b0000010000000000; + 4'b1011 : out = 16'b0000100000000000; + 4'b1100 : out = 16'b0001000000000000; + 4'b1101 : out = 16'b0010000000000000; + 4'b1110 : out = 16'b0100000000000000; + 4'b1111 : out = 16'b1000000000000000; + endcase + end +endmodule +module DEC5 (input [4:0] in, input enable, output reg [31:0] out); + +always @(in or enable) + if(!enable) + out = 32'b00000000000000000000000000000000; + else begin + case (in) + 5'b00000 : out = 32'b00000000000000000000000000000001; + 5'b00001 : out = 32'b00000000000000000000000000000010; + 5'b00010 : out = 32'b00000000000000000000000000000100; + 5'b00011 : out = 32'b00000000000000000000000000001000; + 5'b00100 : out = 32'b00000000000000000000000000010000; + 5'b00101 : out = 32'b00000000000000000000000000100000; + 5'b00110 : out = 32'b00000000000000000000000001000000; + 5'b00111 : out = 32'b00000000000000000000000010000000; + 5'b01000 : out = 32'b00000000000000000000000100000000; + 5'b01001 : out = 32'b00000000000000000000001000000000; + 5'b01010 : out = 32'b00000000000000000000010000000000; + 5'b01011 : out = 32'b00000000000000000000100000000000; + 5'b01100 : out = 32'b00000000000000000001000000000000; + 5'b01101 : out = 32'b00000000000000000010000000000000; + 5'b01110 : out = 32'b00000000000000000100000000000000; + 5'b01111 : out = 32'b00000000000000001000000000000000; + 5'b10000 : out = 32'b00000000000000010000000000000000; + 5'b10001 : out = 32'b00000000000000100000000000000000; + 5'b10010 : out = 32'b00000000000001000000000000000000; + 5'b10011 : out = 32'b00000000000010000000000000000000; + 5'b10100 : out = 32'b00000000000100000000000000000000; + 5'b10101 : out = 32'b00000000001000000000000000000000; + 5'b10110 : out = 32'b00000000010000000000000000000000; + 5'b10111 : out = 32'b00000000100000000000000000000000; + 5'b11000 : out = 32'b00000001000000000000000000000000; + 5'b11001 : out = 32'b00000010000000000000000000000000; + 5'b11010 : out = 32'b00000100000000000000000000000000; + 5'b11011 : out = 32'b00001000000000000000000000000000; + 5'b11100 : out = 32'b00010000000000000000000000000000; + 5'b11101 : out = 32'b00100000000000000000000000000000; + 5'b11110 : out = 32'b01000000000000000000000000000000; + 5'b11111 : out = 32'b10000000000000000000000000000000; + endcase + end +endmodule + +module DEC6 (input [5:0] in, input enable, output reg [63:0] out); + +always @(in or enable) + if(!enable) + out = 64'b0000000000000000000000000000000000000000000000000000000000000000; + else begin + case (in) + 6'b000000 : out = 64'b0000000000000000000000000000000000000000000000000000000000000001; + 6'b000001 : out = 64'b0000000000000000000000000000000000000000000000000000000000000010; + 6'b000010 : out = 64'b0000000000000000000000000000000000000000000000000000000000000100; + 6'b000011 : out = 64'b0000000000000000000000000000000000000000000000000000000000001000; + 6'b000100 : out = 64'b0000000000000000000000000000000000000000000000000000000000010000; + 6'b000101 : out = 64'b0000000000000000000000000000000000000000000000000000000000100000; + 6'b000110 : out = 64'b0000000000000000000000000000000000000000000000000000000001000000; + 6'b000111 : out = 64'b0000000000000000000000000000000000000000000000000000000010000000; + 6'b001000 : out = 64'b0000000000000000000000000000000000000000000000000000000100000000; + 6'b001001 : out = 64'b0000000000000000000000000000000000000000000000000000001000000000; + 6'b001010 : out = 64'b0000000000000000000000000000000000000000000000000000010000000000; + 6'b001011 : out = 64'b0000000000000000000000000000000000000000000000000000100000000000; + 6'b001100 : out = 64'b0000000000000000000000000000000000000000000000000001000000000000; + 6'b001101 : out = 64'b0000000000000000000000000000000000000000000000000010000000000000; + 6'b001110 : out = 64'b0000000000000000000000000000000000000000000000000100000000000000; + 6'b001111 : out = 64'b0000000000000000000000000000000000000000000000001000000000000000; + 6'b010000 : out = 64'b0000000000000000000000000000000000000000000000010000000000000000; + 6'b010001 : out = 64'b0000000000000000000000000000000000000000000000100000000000000000; + 6'b010010 : out = 64'b0000000000000000000000000000000000000000000001000000000000000000; + 6'b010011 : out = 64'b0000000000000000000000000000000000000000000010000000000000000000; + 6'b010100 : out = 64'b0000000000000000000000000000000000000000000100000000000000000000; + 6'b010101 : out = 64'b0000000000000000000000000000000000000000001000000000000000000000; + 6'b010110 : out = 64'b0000000000000000000000000000000000000000010000000000000000000000; + 6'b010111 : out = 64'b0000000000000000000000000000000000000000100000000000000000000000; + 6'b011000 : out = 64'b0000000000000000000000000000000000000001000000000000000000000000; + 6'b011001 : out = 64'b0000000000000000000000000000000000000010000000000000000000000000; + 6'b011010 : out = 64'b0000000000000000000000000000000000000100000000000000000000000000; + 6'b011011 : out = 64'b0000000000000000000000000000000000001000000000000000000000000000; + 6'b011100 : out = 64'b0000000000000000000000000000000000010000000000000000000000000000; + 6'b011101 : out = 64'b0000000000000000000000000000000000100000000000000000000000000000; + 6'b011110 : out = 64'b0000000000000000000000000000000001000000000000000000000000000000; + 6'b011111 : out = 64'b0000000000000000000000000000000010000000000000000000000000000000; + + 6'b100000 : out = 64'b0000000000000000000000000000000100000000000000000000000000000000; + 6'b100001 : out = 64'b0000000000000000000000000000001000000000000000000000000000000000; + 6'b100010 : out = 64'b0000000000000000000000000000010000000000000000000000000000000000; + 6'b100011 : out = 64'b0000000000000000000000000000100000000000000000000000000000000000; + 6'b100100 : out = 64'b0000000000000000000000000001000000000000000000000000000000000000; + 6'b100101 : out = 64'b0000000000000000000000000010000000000000000000000000000000000000; + 6'b100110 : out = 64'b0000000000000000000000000100000000000000000000000000000000000000; + 6'b100111 : out = 64'b0000000000000000000000001000000000000000000000000000000000000000; + 6'b101000 : out = 64'b0000000000000000000000010000000000000000000000000000000000000000; + 6'b101001 : out = 64'b0000000000000000000000100000000000000000000000000000000000000000; + 6'b101010 : out = 64'b0000000000000000000001000000000000000000000000000000000000000000; + 6'b101011 : out = 64'b0000000000000000000010000000000000000000000000000000000000000000; + 6'b101100 : out = 64'b0000000000000000000100000000000000000000000000000000000000000000; + 6'b101101 : out = 64'b0000000000000000001000000000000000000000000000000000000000000000; + 6'b101110 : out = 64'b0000000000000000010000000000000000000000000000000000000000000000; + 6'b101111 : out = 64'b0000000000000000100000000000000000000000000000000000000000000000; + 6'b110000 : out = 64'b0000000000000001000000000000000000000000000000000000000000000000; + 6'b110001 : out = 64'b0000000000000010000000000000000000000000000000000000000000000000; + 6'b110010 : out = 64'b0000000000000100000000000000000000000000000000000000000000000000; + 6'b110011 : out = 64'b0000000000001000000000000000000000000000000000000000000000000000; + 6'b110100 : out = 64'b0000000000010000000000000000000000000000000000000000000000000000; + 6'b110101 : out = 64'b0000000000100000000000000000000000000000000000000000000000000000; + 6'b110110 : out = 64'b0000000001000000000000000000000000000000000000000000000000000000; + 6'b110111 : out = 64'b0000000010000000000000000000000000000000000000000000000000000000; + 6'b111000 : out = 64'b0000000100000000000000000000000000000000000000000000000000000000; + 6'b111001 : out = 64'b0000001000000000000000000000000000000000000000000000000000000000; + 6'b111010 : out = 64'b0000010000000000000000000000000000000000000000000000000000000000; + 6'b111011 : out = 64'b0000100000000000000000000000000000000000000000000000000000000000; + 6'b111100 : out = 64'b0001000000000000000000000000000000000000000000000000000000000000; + 6'b111101 : out = 64'b0010000000000000000000000000000000000000000000000000000000000000; + 6'b111110 : out = 64'b0100000000000000000000000000000000000000000000000000000000000000; + 6'b111111 : out = 64'b1000000000000000000000000000000000000000000000000000000000000000; + endcase + end +endmodule + + +module MUX2(input [1:0] in, input select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + endcase +endmodule + + +module MUX4(input [3:0] in, input [1:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + endcase +endmodule + + +module MUX8(input [7:0] in, input [2:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + 4: out = in[4]; + 5: out = in[5]; + 6: out = in[6]; + 7: out = in[7]; + endcase +endmodule + +module MUX16(input [15:0] in, input [3:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + 4: out = in[4]; + 5: out = in[5]; + 6: out = in[6]; + 7: out = in[7]; + 8: out = in[8]; + 9: out = in[9]; + 10: out = in[10]; + 11: out = in[11]; + 12: out = in[12]; + 13: out = in[13]; + 14: out = in[14]; + 15: out = in[15]; + endcase +endmodule + +module MUX32(input [31:0] in, input [4:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + 4: out = in[4]; + 5: out = in[5]; + 6: out = in[6]; + 7: out = in[7]; + 8: out = in[8]; + 9: out = in[9]; + 10: out = in[10]; + 11: out = in[11]; + 12: out = in[12]; + 13: out = in[13]; + 14: out = in[14]; + 15: out = in[15]; + 16: out = in[16]; + 17: out = in[17]; + 18: out = in[18]; + 19: out = in[19]; + 20: out = in[20]; + 21: out = in[21]; + 22: out = in[22]; + 23: out = in[23]; + 24: out = in[24]; + 25: out = in[25]; + 26: out = in[26]; + 27: out = in[27]; + 28: out = in[28]; + 29: out = in[29]; + 30: out = in[30]; + 31: out = in[31]; + endcase +endmodule + +module MUX64(input [63:0] in, input [5:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + 4: out = in[4]; + 5: out = in[5]; + 6: out = in[6]; + 7: out = in[7]; + 8: out = in[8]; + 9: out = in[9]; + 10: out = in[10]; + 11: out = in[11]; + 12: out = in[12]; + 13: out = in[13]; + 14: out = in[14]; + 15: out = in[15]; + 16: out = in[16]; + 17: out = in[17]; + 18: out = in[18]; + 19: out = in[19]; + 20: out = in[20]; + 21: out = in[21]; + 22: out = in[22]; + 23: out = in[23]; + 24: out = in[24]; + 25: out = in[25]; + 26: out = in[26]; + 27: out = in[27]; + 28: out = in[28]; + 29: out = in[29]; + 30: out = in[30]; + 31: out = in[31]; + 32: out = in[32]; + 33: out = in[33]; + 34: out = in[34]; + 35: out = in[35]; + 36: out = in[36]; + 37: out = in[37]; + 38: out = in[38]; + 39: out = in[39]; + 40: out = in[40]; + 41: out = in[41]; + 42: out = in[42]; + 43: out = in[43]; + 44: out = in[44]; + 45: out = in[45]; + 46: out = in[46]; + 47: out = in[47]; + 48: out = in[48]; + 49: out = in[49]; + 50: out = in[50]; + 51: out = in[51]; + 52: out = in[52]; + 53: out = in[53]; + 54: out = in[54]; + 55: out = in[55]; + 56: out = in[56]; + 57: out = in[57]; + 58: out = in[58]; + 59: out = in[59]; + 60: out = in[60]; + 61: out = in[61]; + 62: out = in[62]; + 63: out = in[63]; + endcase +endmodule + +module ADD1(input in1, in2, cin, output out, cout); + +assign {cout, out} = in1 + in2 + cin; + +endmodule + +module ADD2 #(parameter SIZE = 2)(input [SIZE-1:0] in1, in2, + input cin, output [SIZE-1:0] out, output cout); + +assign {cout, out} = in1 + in2 + cin; + +endmodule + +module ADD4 #(parameter SIZE = 4)(input [SIZE-1:0] in1, in2, + input cin, output [SIZE-1:0] out, output cout); + +assign {cout, out} = in1 + in2 + cin; + +endmodule + +module ADD8 #(parameter SIZE = 8)(input [SIZE-1:0] in1, in2, + input cin, output [SIZE-1:0] out, output cout); + +assign {cout, out} = in1 + in2 + cin; + +endmodule + +module ADD16 #(parameter SIZE = 16)(input [SIZE-1:0] in1, in2, + input cin, output [SIZE-1:0] out, output cout); + +assign {cout, out} = in1 + in2 + cin; + +endmodule + +module ADD32 #(parameter SIZE = 32)(input [SIZE-1:0] in1, in2, + input cin, output [SIZE-1:0] out, output cout); + +assign {cout, out} = in1 + in2 + cin; + +endmodule +module ADD64 #(parameter SIZE = 64)(input [SIZE-1:0] in1, in2, + input cin, output [SIZE-1:0] out, output cout); + +assign {cout, out} = in1 + in2 + cin; + +endmodule + +module SUB1(input in1, in2, cin, output out, cout); + +assign {cout, out} = in1 - in2 - cin; + +endmodule + +module SUB2 #(parameter SIZE = 2)(input [SIZE-1:0] in1, in2, + input cin, output [SIZE-1:0] out, output cout); + +assign {cout, out} = in1 - in2 - cin; + +endmodule + +module SUB4 #(parameter SIZE = 4)(input [SIZE-1:0] in1, in2, + input cin, output [SIZE-1:0] out, output cout); + +assign {cout, out} = in1 - in2 - cin; + +endmodule + +module SUB8 #(parameter SIZE = 8)(input [SIZE-1:0] in1, in2, + input cin, output [SIZE-1:0] out, output cout); + +assign {cout, out} = in1 - in2 - cin; + +endmodule + +module SUB16 #(parameter SIZE = 16)(input [SIZE-1:0] in1, in2, + input cin, output [SIZE-1:0] out, output cout); + +assign {cout, out} = in1 - in2 - cin; + +endmodule + +module SUB32 #(parameter SIZE = 32)(input [SIZE-1:0] in1, in2, + input cin, output [SIZE-1:0] out, output cout); + +assign {cout, out} = in1 - in2 - cin; + +endmodule +module SUB64 #(parameter SIZE = 64)(input [SIZE-1:0] in1, in2, + input cin, output [SIZE-1:0] out, output cout); + +assign {cout, out} = in1 - in2 - cin; + +endmodule + +module MUL1 #(parameter SIZE = 1)(input in1, in2, output [2*SIZE-1:0] out); + +assign out = in1*in2; + +endmodule + +module MUL2 #(parameter SIZE = 2)(input [SIZE-1:0] in1, in2, output [2*SIZE-1:0] out); + +assign out = in1*in2; + +endmodule + +module MUL4 #(parameter SIZE = 4)(input [SIZE-1:0] in1, in2, output [2*SIZE-1:0] out); + +assign out = in1*in2; + +endmodule + +module MUL8 #(parameter SIZE = 8)(input [SIZE-1:0] in1, in2, output [2*SIZE-1:0] out); + +assign out = in1*in2; + +endmodule + +module MUL16 #(parameter SIZE = 16)(input [SIZE-1:0] in1, in2, output [2*SIZE-1:0] out); + +assign out = in1*in2; + +endmodule + +module MUL32 #(parameter SIZE = 32)(input [SIZE-1:0] in1, in2, output [2*SIZE-1:0] out); + +assign out = in1*in2; + +endmodule + +module MUL64 #(parameter SIZE = 64)(input [SIZE-1:0] in1, in2, output [2*SIZE-1:0] out); + +assign out = in1*in2; + +endmodule + +module DIV1 #(parameter SIZE = 1)(input in1, in2, output out, rem); + +assign out = in1/in2; +assign rem = in1%in2; + +endmodule + +module DIV2 #(parameter SIZE = 2)(input [SIZE-1:0] in1, in2, + output [SIZE-1:0] out, rem); + +assign out = in1/in2; +assign rem = in1%in2; + +endmodule + +module DIV4 #(parameter SIZE = 4)(input [SIZE-1:0] in1, in2, + output [SIZE-1:0] out, rem); + +assign out = in1/in2; +assign rem = in1%in2; + +endmodule + +module DIV8 #(parameter SIZE = 8)(input [SIZE-1:0] in1, in2, + output [SIZE-1:0] out, rem); + +assign out = in1/in2; +assign rem = in1%in2; + +endmodule + +module DIV16 #(parameter SIZE = 16)(input [SIZE-1:0] in1, in2, + output [SIZE-1:0] out, rem); + +assign out = in1/in2; +assign rem = in1%in2; + +endmodule + +module DIV32 #(parameter SIZE = 32)(input [SIZE-1:0] in1, in2, + output [SIZE-1:0] out, rem); + +assign out = in1/in2; +assign rem = in1%in2; + +endmodule + +module DIV64 #(parameter SIZE = 64)(input [SIZE-1:0] in1, in2, + output [SIZE-1:0] out, rem); + +assign out = in1/in2; +assign rem = in1%in2; + +endmodule + +module FF (input d, clk, output reg q); +always @( posedge clk) + q <= d; +endmodule + + +module RFF(input d, clk, reset, output reg q); +always @(posedge clk or posedge reset) + if(reset) + q <= 0; + else + q <= d; +endmodule + +module SFF(input d, clk, set, output reg q); +always @(posedge clk or posedge set) + if(set) + q <= 1; + else + q <= d; +endmodule + +module RSFF(input d, clk, set, reset, output reg q); +always @(posedge clk or posedge reset or posedge set) + if(reset) + q <= 0; + else if(set) + q <= 1; + else + q <= d; +endmodule + +module SRFF(input d, clk, set, reset, output reg q); +always @(posedge clk or posedge set or posedge reset) + if(set) + q <= 1; + else if(reset) + q <= 0; + else + q <= d; +endmodule + +module LATCH(input d, enable, output reg q); +always @( d or enable) + if(enable) + q <= d; +endmodule + +module RLATCH(input d, reset, enable, output reg q); +always @( d or enable or reset) + if(enable) + if(reset) + q <= 0; + else + q <= d; +endmodule + +module LSHIFT1 #(parameter SIZE = 1)(input in, shift, val, output reg out); + +always @ (in, shift, val) begin + if(shift) + out = val; + else + out = in; +end + +endmodule + + +module LSHIFT2 #(parameter SIZE = 2)(input [SIZE-1:0] in, + input [SIZE-1:0] shift, input val, + output reg [SIZE-1:0] out); + +always @(in or shift or val) begin + out = in << shift; + if(val) + out = out | ({SIZE-1 {1'b1} } >> (SIZE-1-shift)); +end +endmodule + +module LSHIFT4 #(parameter SIZE = 4)(input [SIZE-1:0] in, + input [2:0] shift, input val, output reg [SIZE-1:0] out); + +always @(in or shift or val) begin + out = in << shift; + if(val) + out = out | ({SIZE-1 {1'b1} } >> (SIZE-1-shift)); +end +endmodule + + +module LSHIFT8 #(parameter SIZE = 8)(input [SIZE-1:0] in, + input [3:0] shift, input val, output reg [SIZE-1:0] out); + +always @(in or shift or val) begin + out = in << shift; + if(val) + out = out | ({SIZE-1 {1'b1} } >> (SIZE-1-shift)); +end +endmodule + +module LSHIFT16 #(parameter SIZE = 16)(input [SIZE-1:0] in, + input [4:0] shift, input val, output reg [SIZE-1:0] out); + +always @(in or shift or val) begin + out = in << shift; + if(val) + out = out | ({SIZE-1 {1'b1} } >> (SIZE-1-shift)); +end +endmodule + +module LSHIFT32 #(parameter SIZE = 32)(input [SIZE-1:0] in, + input [5:0] shift, input val, output reg [SIZE-1:0] out); + +always @(in or shift or val) begin + out = in << shift; + if(val) + out = out | ({SIZE-1 {1'b1} } >> (SIZE-1-shift)); +end +endmodule + +module LSHIFT64 #(parameter SIZE = 64)(input [SIZE-1:0] in, + input [6:0] shift, input val, output reg [SIZE-1:0] out); + +always @(in or shift or val) begin + out = in << shift; + if(val) + out = out | ({SIZE-1 {1'b1} } >> (SIZE-1-shift)); +end +endmodule + +module RSHIFT1 #(parameter SIZE = 1)(input in, shift, val, output reg out); + +always @ (in, shift, val) begin + if(shift) + out = val; + else + out = in; +end + +endmodule + +module RSHIFT2 #(parameter SIZE = 2)(input [SIZE-1:0] in, + input [SIZE-1:0] shift, input val, + output reg [SIZE-1:0] out); + +always @(in or shift or val) begin + out = in >> shift; + if(val) + out = out | ({SIZE-1 {1'b1} } << (SIZE-1-shift)); +end + +endmodule + + +module RSHIFT4 #(parameter SIZE = 4)(input [SIZE-1:0] in, + input [2:0] shift, input val, + output reg [SIZE-1:0] out); + +always @(in or shift or val) begin + out = in >> shift; + if(val) + out = out | ({SIZE-1 {1'b1} } << (SIZE-1-shift)); +end +endmodule + +module RSHIFT8 #(parameter SIZE = 8)(input [SIZE-1:0] in, + input [3:0] shift, input val, + output reg [SIZE-1:0] out); + +always @(in or shift or val) begin + out = in >> shift; + if(val) + out = out | ({SIZE-1 {1'b1} } << (SIZE-1-shift)); +end + +endmodule + +module RSHIFT16 #(parameter SIZE = 16)(input [SIZE-1:0] in, + input [4:0] shift, input val, + output reg [SIZE-1:0] out); + +always @(in or shift or val) begin + out = in >> shift; + if(val) + out = out | ({SIZE-1 {1'b1} } << (SIZE-1-shift)); +end +endmodule + + +module RSHIFT32 #(parameter SIZE = 32)(input [SIZE-1:0] in, + input [5:0] shift, input val, + output reg [SIZE-1:0] out); + +always @(in or shift or val) begin + out = in >> shift; + if(val) + out = out | ({SIZE-1 {1'b1} } << (SIZE-1-shift)); +end +endmodule + +module RSHIFT64 #(parameter SIZE = 64)(input [SIZE-1:0] in, + input [6:0] shift, input val, + output reg [SIZE-1:0] out); + +always @(in or shift or val) begin + out = in >> shift; + if(val) + out = out | ({SIZE-1 {1'b1} } << (SIZE-1-shift)); +end +endmodule + +module CMP1 #(parameter SIZE = 1) (input in1, in2, + output reg equal, unequal, greater, lesser); + +always @ (in1 or in2) begin + if(in1 == in2) begin + equal = 1; + unequal = 0; + greater = 0; + lesser = 0; + end + else begin + equal = 0; + unequal = 1; + + if(in1 < in2) begin + greater = 0; + lesser = 1; + end + else begin + greater = 1; + lesser = 0; + end + end +end +endmodule + + +module CMP2 #(parameter SIZE = 2) (input [SIZE-1:0] in1, in2, + output reg equal, unequal, greater, lesser); + +always @ (in1 or in2) begin + if(in1 == in2) begin + equal = 1; + unequal = 0; + greater = 0; + lesser = 0; + end + else begin + equal = 0; + unequal = 1; + + if(in1 < in2) begin + greater = 0; + lesser = 1; + end + else begin + greater = 1; + lesser = 0; + end + end +end +endmodule + +module CMP4 #(parameter SIZE = 4) (input [SIZE-1:0] in1, in2, + output reg equal, unequal, greater, lesser); + +always @ (in1 or in2) begin + if(in1 == in2) begin + equal = 1; + unequal = 0; + greater = 0; + lesser = 0; + end + else begin + equal = 0; + unequal = 1; + + if(in1 < in2) begin + greater = 0; + lesser = 1; + end + else begin + greater = 1; + lesser = 0; + end + end +end +endmodule + +module CMP8 #(parameter SIZE = 8) (input [SIZE-1:0] in1, in2, + output reg equal, unequal, greater, lesser); + +always @ (in1 or in2) begin + if(in1 == in2) begin + equal = 1; + unequal = 0; + greater = 0; + lesser = 0; + end + else begin + equal = 0; + unequal = 1; + + if(in1 < in2) begin + greater = 0; + lesser = 1; + end + else begin + greater = 1; + lesser = 0; + end + end +end +endmodule + +module CMP16 #(parameter SIZE = 16) (input [SIZE-1:0] in1, in2, + output reg equal, unequal, greater, lesser); + +always @ (in1 or in2) begin + if(in1 == in2) begin + equal = 1; + unequal = 0; + greater = 0; + lesser = 0; + end + else begin + equal = 0; + unequal = 1; + + if(in1 < in2) begin + greater = 0; + lesser = 1; + end + else begin + greater = 1; + lesser = 0; + end + end +end +endmodule + +module CMP32 #(parameter SIZE = 32) (input [SIZE-1:0] in1, in2, + output reg equal, unequal, greater, lesser); + +always @ (in1 or in2) begin + if(in1 == in2) begin + equal = 1; + unequal = 0; + greater = 0; + lesser = 0; + end + else begin + equal = 0; + unequal = 1; + + if(in1 < in2) begin + greater = 0; + lesser = 1; + end + else begin + greater = 1; + lesser = 0; + end + end +end +endmodule + +module CMP64 #(parameter SIZE = 64) (input [SIZE-1:0] in1, in2, + output reg equal, unequal, greater, lesser); + +always @ (in1 or in2) begin + if(in1 == in2) begin + equal = 1; + unequal = 0; + greater = 0; + lesser = 0; + end + else begin + equal = 0; + unequal = 1; + + if(in1 < in2) begin + greater = 0; + lesser = 1; + end + else begin + greater = 1; + lesser = 0; + end + end +end +endmodule + +module VCC (output supply1 out); +endmodule + +module GND (output supply0 out); +endmodule + + +module INC1 #(parameter SIZE = 1) (input in, output [SIZE:0] out); + +assign out = in + 1; + +endmodule + +module INC2 #(parameter SIZE = 2) (input [SIZE-1:0] in, output [SIZE:0] out); + +assign out = in + 1; + +endmodule + +module INC4 #(parameter SIZE = 4) (input [SIZE-1:0] in, output [SIZE:0] out); +assign out = in + 1; + +endmodule + +module INC8 #(parameter SIZE = 8) (input [SIZE-1:0] in, output [SIZE:0] out); +assign out = in + 1; + +endmodule + +module INC16 #(parameter SIZE = 16) (input [SIZE-1:0] in, output [SIZE:0] out); +assign out = in + 1; + +endmodule + +module INC32 #(parameter SIZE = 32) (input [SIZE-1:0] in, output [SIZE:0] out); +assign out = in + 1; + +endmodule +module INC64 #(parameter SIZE = 64) (input [SIZE-1:0] in, output [SIZE:0] out); +assign out = in + 1; + +endmodule + diff --git a/tests/hana/run-test.sh b/tests/hana/run-test.sh new file mode 100755 index 00000000..b8e7231c --- /dev/null +++ b/tests/hana/run-test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +make -C ../.. || exit 1 +exec bash ../tools/autotest.sh -l hana_vlib.v test_*.v diff --git a/tests/hana/test_intermout_always_comb_1_test.v b/tests/hana/test_intermout_always_comb_1_test.v new file mode 100644 index 00000000..2d5abc4a --- /dev/null +++ b/tests/hana/test_intermout_always_comb_1_test.v @@ -0,0 +1,13 @@ +module test(a, b, c, d, z); +input a, b, c, d; +output z; +reg z, temp1, temp2; + +always @(a or b or c or d) +begin + temp1 = a ^ b; + temp2 = c ^ d; + z = temp1 ^ temp2; +end + +endmodule diff --git a/tests/hana/test_intermout_always_comb_3_test.v b/tests/hana/test_intermout_always_comb_3_test.v new file mode 100644 index 00000000..234407ef --- /dev/null +++ b/tests/hana/test_intermout_always_comb_3_test.v @@ -0,0 +1,10 @@ +module test (in1, in2, out); +input in1, in2; +output reg out; + +always @ ( in1 or in2) + if(in1 > in2) + out = in1; + else + out = in2; +endmodule diff --git a/tests/hana/test_intermout_always_comb_4_test.v b/tests/hana/test_intermout_always_comb_4_test.v new file mode 100644 index 00000000..b0a94f29 --- /dev/null +++ b/tests/hana/test_intermout_always_comb_4_test.v @@ -0,0 +1,9 @@ +module test(a, b, c); +input b, c; +output reg a; + +always @(b or c) begin +a = b; +a = c; +end +endmodule diff --git a/tests/hana/test_intermout_always_comb_5_test.v b/tests/hana/test_intermout_always_comb_5_test.v new file mode 100644 index 00000000..5152781d --- /dev/null +++ b/tests/hana/test_intermout_always_comb_5_test.v @@ -0,0 +1,11 @@ +module test(ctrl, in1, in2, out); +input ctrl; +input in1, in2; +output reg out; + +always @ (ctrl or in1 or in2) + if(ctrl) + out = in1 & in2; + else + out = in1 | in2; +endmodule diff --git a/tests/hana/test_intermout_always_ff_3_test.v b/tests/hana/test_intermout_always_ff_3_test.v new file mode 100644 index 00000000..ed8630c3 --- /dev/null +++ b/tests/hana/test_intermout_always_ff_3_test.v @@ -0,0 +1,15 @@ +module NonBlockingEx(clk, merge, er, xmit, fddi, claim); +input clk, merge, er, xmit, fddi; +output reg claim; +reg fcr; + +always @(posedge clk) +begin + fcr = er | xmit; + + if(merge) + claim = fcr & fddi; + else + claim = fddi; +end +endmodule diff --git a/tests/hana/test_intermout_always_ff_4_test.v b/tests/hana/test_intermout_always_ff_4_test.v new file mode 100644 index 00000000..cac420a4 --- /dev/null +++ b/tests/hana/test_intermout_always_ff_4_test.v @@ -0,0 +1,11 @@ +module FlipFlop(clk, cs, ns); +input clk; +input [31:0] cs; +output [31:0] ns; +integer is; + +always @(posedge clk) + is <= cs; + +assign ns = is; +endmodule diff --git a/tests/hana/test_intermout_always_ff_5_test.v b/tests/hana/test_intermout_always_ff_5_test.v new file mode 100644 index 00000000..669b2a5f --- /dev/null +++ b/tests/hana/test_intermout_always_ff_5_test.v @@ -0,0 +1,13 @@ +module FlipFlop(clock, cs, ns); +input clock; +input [3:0] cs; +output reg [3:0] ns; +reg [3:0] temp; + +always @(posedge clock) +begin + temp = cs; + ns = temp; +end + +endmodule diff --git a/tests/hana/test_intermout_always_ff_6_test.v b/tests/hana/test_intermout_always_ff_6_test.v new file mode 100644 index 00000000..ad0a0df6 --- /dev/null +++ b/tests/hana/test_intermout_always_ff_6_test.v @@ -0,0 +1,7 @@ +module inc(clock, counter); + +input clock; +output reg [3:0] counter; +always @(posedge clock) + counter <= counter + 1; +endmodule diff --git a/tests/hana/test_intermout_always_ff_8_test.v b/tests/hana/test_intermout_always_ff_8_test.v new file mode 100644 index 00000000..0f29ea0a --- /dev/null +++ b/tests/hana/test_intermout_always_ff_8_test.v @@ -0,0 +1,11 @@ +module NegEdgeClock(q, d, clk, reset); +input d, clk, reset; +output reg q; + +always @(negedge clk or negedge reset) + if(!reset) + q <= 1'b0; + else + q <= d; + +endmodule diff --git a/tests/hana/test_intermout_always_ff_9_test.v b/tests/hana/test_intermout_always_ff_9_test.v new file mode 100644 index 00000000..f1f13bbe --- /dev/null +++ b/tests/hana/test_intermout_always_ff_9_test.v @@ -0,0 +1,14 @@ +module MyCounter (clock, preset, updown, presetdata, counter); +input clock, preset, updown; +input [1: 0] presetdata; +output reg [1:0] counter; + +always @(posedge clock) + if(preset) + counter <= presetdata; + else + if(updown) + counter <= counter + 1; + else + counter <= counter - 1; +endmodule diff --git a/tests/hana/test_intermout_always_latch_1_test.v b/tests/hana/test_intermout_always_latch_1_test.v new file mode 100644 index 00000000..a83be20d --- /dev/null +++ b/tests/hana/test_intermout_always_latch_1_test.v @@ -0,0 +1,9 @@ +module test(en, in, out); +input en; +input [1:0] in; +output reg [2:0] out; + +always @ (en or in) + if(en) + out = in + 1; +endmodule diff --git a/tests/hana/test_intermout_bufrm_1_test.v b/tests/hana/test_intermout_bufrm_1_test.v new file mode 100644 index 00000000..8e3d4222 --- /dev/null +++ b/tests/hana/test_intermout_bufrm_1_test.v @@ -0,0 +1,4 @@ +module test(input in, output out); +//no buffer removal +assign out = in; +endmodule diff --git a/tests/hana/test_intermout_bufrm_2_test.v b/tests/hana/test_intermout_bufrm_2_test.v new file mode 100644 index 00000000..853f1dc9 --- /dev/null +++ b/tests/hana/test_intermout_bufrm_2_test.v @@ -0,0 +1,7 @@ +module test(input in, output out); +//intermediate buffers should be removed +wire w1, w2; +assign w1 = in; +assign w2 = w1; +assign out = w2; +endmodule diff --git a/tests/hana/test_intermout_bufrm_6_test.v b/tests/hana/test_intermout_bufrm_6_test.v new file mode 100644 index 00000000..d4f3878d --- /dev/null +++ b/tests/hana/test_intermout_bufrm_6_test.v @@ -0,0 +1,22 @@ +module test(in, out); +input in; +output out; + +wire w1, w2, w3, w4; +assign w1 = in; +assign w2 = w1; +assign w4 = w3; +assign out = w4; +mybuf _mybuf(w2, w3); +endmodule + +module mybuf(in, out); +input in; +output out; +wire w1, w2, w3, w4; + +assign w1 = in; +assign w2 = w1; +assign out = w2; +endmodule + diff --git a/tests/hana/test_intermout_bufrm_7_test.v b/tests/hana/test_intermout_bufrm_7_test.v new file mode 100644 index 00000000..7b651302 --- /dev/null +++ b/tests/hana/test_intermout_bufrm_7_test.v @@ -0,0 +1,33 @@ +module test(in1, in2, out); +input in1, in2; +output out; +// Y with cluster of mybuf instances at the junction + +wire w1, w2, w3, w4, w5, w6, w7, w8, w9, w10; +assign w1 = in1; +assign w2 = w1; +assign w5 = in2; +assign w6 = w5; +assign w10 = w9; +assign out = w10; + +mybuf _mybuf0(w2, w3); +mybuf _mybuf1(w3, w4); + +mybuf _mybuf2(w6, w7); +mybuf _mybuf3(w7, w4); + +mybuf _mybuf4(w4, w8); +mybuf _mybuf5(w8, w9); +endmodule + +module mybuf(in, out); +input in; +output out; +wire w1, w2, w3, w4; + +assign w1 = in; +assign w2 = w1; +assign out = w2; +endmodule + diff --git a/tests/hana/test_intermout_exprs_add_test.v b/tests/hana/test_intermout_exprs_add_test.v new file mode 100644 index 00000000..ec70f347 --- /dev/null +++ b/tests/hana/test_intermout_exprs_add_test.v @@ -0,0 +1,10 @@ +module test(out, in1, in2, vin1, vin2, vout1); +output out; +input in1, in2; +input [1:0] vin1; +input [2:0] vin2; +output [3:0] vout1; + +assign out = in1 + in2; +assign vout1 = vin1 + vin2; +endmodule diff --git a/tests/hana/test_intermout_exprs_binlogic_test.v b/tests/hana/test_intermout_exprs_binlogic_test.v new file mode 100644 index 00000000..eec8c4b1 --- /dev/null +++ b/tests/hana/test_intermout_exprs_binlogic_test.v @@ -0,0 +1,13 @@ +module test(in1, in2, vin1, vin2, out, vout, vin3, vin4, vout1 ); +input in1, in2; +input [1:0] vin1; +input [3:0] vin2; +input [1:0] vin3; +input [3:0] vin4; +output vout, vout1; +output out; + +assign out = in1 && in2; +assign vout = vin1 && vin2; +assign vout1 = vin3 || vin4; +endmodule diff --git a/tests/hana/test_intermout_exprs_bitwiseneg_test.v b/tests/hana/test_intermout_exprs_bitwiseneg_test.v new file mode 100644 index 00000000..5b62bef0 --- /dev/null +++ b/tests/hana/test_intermout_exprs_bitwiseneg_test.v @@ -0,0 +1,5 @@ +module test(output out, input in, output [1:0] vout, input [1:0] vin); + +assign out = ~in; +assign vout = ~vin; +endmodule diff --git a/tests/hana/test_intermout_exprs_buffer_test.v b/tests/hana/test_intermout_exprs_buffer_test.v new file mode 100644 index 00000000..2b4cbc3e --- /dev/null +++ b/tests/hana/test_intermout_exprs_buffer_test.v @@ -0,0 +1,9 @@ +module buffer(in, out, vin, vout); +input in; +output out; +input [1:0] vin; +output [1:0] vout; + +assign out = in; +assign vout = vin; +endmodule diff --git a/tests/hana/test_intermout_exprs_condexpr_mux_test.v b/tests/hana/test_intermout_exprs_condexpr_mux_test.v new file mode 100644 index 00000000..11006e8b --- /dev/null +++ b/tests/hana/test_intermout_exprs_condexpr_mux_test.v @@ -0,0 +1,11 @@ +module test(in1, in2, out, vin1, vin2, vin3, vin4, vout1, vout2, en1, ven1, ven2); +input in1, in2, en1, ven1; +input [1:0] ven2; +output out; +input [1:0] vin1, vin2, vin3, vin4; +output [1:0] vout1, vout2; + +assign out = en1 ? in1 : in2; +assign vout1 = ven1 ? vin1 : vin2; +assign vout2 = ven2 ? vin3 : vin4; +endmodule diff --git a/tests/hana/test_intermout_exprs_condexpr_tribuf_test.v b/tests/hana/test_intermout_exprs_condexpr_tribuf_test.v new file mode 100644 index 00000000..5b778fe9 --- /dev/null +++ b/tests/hana/test_intermout_exprs_condexpr_tribuf_test.v @@ -0,0 +1,9 @@ +module test(in, out, en, vin1, vout1, en1); +input in, en, en1; +output out; +input [1:0] vin1; +output [1:0] vout1; + +assign out = en ? in : 1'bz; +assign vout1 = en1 ? vin1 : 2'bzz; +endmodule diff --git a/tests/hana/test_intermout_exprs_const_test.v b/tests/hana/test_intermout_exprs_const_test.v new file mode 100644 index 00000000..484d8103 --- /dev/null +++ b/tests/hana/test_intermout_exprs_const_test.v @@ -0,0 +1,7 @@ +module test (out, vout); +output out; +output [7:0] vout; + +assign out = 1'b1; +assign vout = 9; +endmodule diff --git a/tests/hana/test_intermout_exprs_constshift_test.v b/tests/hana/test_intermout_exprs_constshift_test.v new file mode 100644 index 00000000..eb21315d --- /dev/null +++ b/tests/hana/test_intermout_exprs_constshift_test.v @@ -0,0 +1,12 @@ +module test(in, out, vin, vout, vin1, vout1, vin2, vout2); + +input in; +input [3:0] vin, vin1, vin2; +output [3:0] vout, vout1, vout2; +output out; + +assign out = in << 1; +assign vout = vin << 2; +assign vout1 = vin1 >> 2; +assign vout2 = vin2 >>> 2; +endmodule diff --git a/tests/hana/test_intermout_exprs_div_test.v b/tests/hana/test_intermout_exprs_div_test.v new file mode 100644 index 00000000..21765fcd --- /dev/null +++ b/tests/hana/test_intermout_exprs_div_test.v @@ -0,0 +1,10 @@ +module test(out, in1, in2, vin1, vin2, vout1); +output out; +input in1, in2; +input [1:0] vin1; +input [2:0] vin2; +output [3:0] vout1; + +assign out = in1 / in2; +assign vout1 = vin1 / vin2; +endmodule diff --git a/tests/hana/test_intermout_exprs_logicneg_test.v b/tests/hana/test_intermout_exprs_logicneg_test.v new file mode 100644 index 00000000..b45b32b9 --- /dev/null +++ b/tests/hana/test_intermout_exprs_logicneg_test.v @@ -0,0 +1,7 @@ +module test(out, vout, in, vin); +output out, vout; +input in; +input [3:0] vin; +assign out = !in; +assign vout = !vin; +endmodule diff --git a/tests/hana/test_intermout_exprs_mod_test.v b/tests/hana/test_intermout_exprs_mod_test.v new file mode 100644 index 00000000..cea6b02d --- /dev/null +++ b/tests/hana/test_intermout_exprs_mod_test.v @@ -0,0 +1,10 @@ +module test(out, in1, in2, vin1, vin2, vout1); +output out; +input in1, in2; +input [1:0] vin1; +input [2:0] vin2; +output [3:0] vout1; + +assign out = in1 % in2; +assign vout1 = vin1 % vin2; +endmodule diff --git a/tests/hana/test_intermout_exprs_mul_test.v b/tests/hana/test_intermout_exprs_mul_test.v new file mode 100644 index 00000000..f9973dad --- /dev/null +++ b/tests/hana/test_intermout_exprs_mul_test.v @@ -0,0 +1,10 @@ +module test(out, in1, in2, vin1, vin2, vout1); +output out; +input in1, in2; +input [1:0] vin1; +input [2:0] vin2; +output [3:0] vout1; + +assign out = in1 * in2; +assign vout1 = vin1 * vin2; +endmodule diff --git a/tests/hana/test_intermout_exprs_redand_test.v b/tests/hana/test_intermout_exprs_redand_test.v new file mode 100644 index 00000000..35fdf73a --- /dev/null +++ b/tests/hana/test_intermout_exprs_redand_test.v @@ -0,0 +1,5 @@ +module test(output out, input [1:0] vin, output out1, input [3:0] vin1); + +assign out = &vin; +assign out1 = &vin1; +endmodule diff --git a/tests/hana/test_intermout_exprs_redop_test.v b/tests/hana/test_intermout_exprs_redop_test.v new file mode 100644 index 00000000..93fdb2e5 --- /dev/null +++ b/tests/hana/test_intermout_exprs_redop_test.v @@ -0,0 +1,16 @@ +module Reduction (A1, A2, A3, A4, A5, A6, Y1, Y2, Y3, Y4, Y5, Y6); +input [1:0] A1; +input [1:0] A2; +input [1:0] A3; +input [1:0] A4; +input [1:0] A5; +input [1:0] A6; +output Y1, Y2, Y3, Y4, Y5, Y6; +//reg Y1, Y2, Y3, Y4, Y5, Y6; +assign Y1=&A1; //reduction AND +assign Y2=|A2; //reduction OR +assign Y3=~&A3; //reduction NAND +assign Y4=~|A4; //reduction NOR +assign Y5=^A5; //reduction XOR +assign Y6=~^A6; //reduction XNOR +endmodule diff --git a/tests/hana/test_intermout_exprs_sub_test.v b/tests/hana/test_intermout_exprs_sub_test.v new file mode 100644 index 00000000..06e3a814 --- /dev/null +++ b/tests/hana/test_intermout_exprs_sub_test.v @@ -0,0 +1,10 @@ +module test(out, in1, in2, vin1, vin2, vout1); +output out; +input in1, in2; +input [1:0] vin1; +input [2:0] vin2; +output [3:0] vout1; + +assign out = in1 - in2; +assign vout1 = vin1 - vin2; +endmodule diff --git a/tests/hana/test_intermout_exprs_unaryminus_test.v b/tests/hana/test_intermout_exprs_unaryminus_test.v new file mode 100644 index 00000000..ee3f229a --- /dev/null +++ b/tests/hana/test_intermout_exprs_unaryminus_test.v @@ -0,0 +1,5 @@ +module test(output out, input in, output [31:0] vout, input [31:0] vin); + +assign out = -in; +assign vout = -vin; +endmodule diff --git a/tests/hana/test_intermout_exprs_unaryplus_test.v b/tests/hana/test_intermout_exprs_unaryplus_test.v new file mode 100644 index 00000000..07be5b24 --- /dev/null +++ b/tests/hana/test_intermout_exprs_unaryplus_test.v @@ -0,0 +1,4 @@ +module test(output out, input in); + +assign out = +in; +endmodule diff --git a/tests/hana/test_intermout_exprs_varshift_test.v b/tests/hana/test_intermout_exprs_varshift_test.v new file mode 100644 index 00000000..2ca35c09 --- /dev/null +++ b/tests/hana/test_intermout_exprs_varshift_test.v @@ -0,0 +1,10 @@ +module test(vin0, vout0); +input [2:0] vin0; +output reg [7:0] vout0; + +wire [7:0] myreg0, myreg1, myreg2; +integer i; +assign myreg0 = vout0 << vin0; + +assign myreg1 = myreg2 >> i; +endmodule diff --git a/tests/hana/test_parse2synthtrans_behavopt_1_test.v b/tests/hana/test_parse2synthtrans_behavopt_1_test.v new file mode 100644 index 00000000..c825739c --- /dev/null +++ b/tests/hana/test_parse2synthtrans_behavopt_1_test.v @@ -0,0 +1,22 @@ +module test(in, out, clk, reset); +input in, reset; +output reg out; +input clk; +reg signed [3:0] a; +reg signed [3:0] b; +reg signed [3:0] c; +reg [5:0] d; +reg [5:0] e; + +always @(clk or reset) begin + a = -4; + b = 2; + c = a + b; + d = a + b + c; + d = d*d; + if(b) + e = d*d; + else + e = d + d; +end +endmodule diff --git a/tests/hana/test_parse2synthtrans_case_1_test.v b/tests/hana/test_parse2synthtrans_case_1_test.v new file mode 100644 index 00000000..348c566a --- /dev/null +++ b/tests/hana/test_parse2synthtrans_case_1_test.v @@ -0,0 +1,26 @@ +module demultiplexer1_to_4 (out0, out1, out2, out3, in, s1, s0); +output out0, out1, out2, out3; +reg out0, out1, out2, out3; +input in; +input s1, s0; +reg [3:0] encoding; +reg [1:0] state; + always @(encoding) begin + case (encoding) + 4'bxx11: state = 1; + 4'bx0xx: state = 3; + 4'b11xx: state = 4; + 4'bx1xx: state = 2; + 4'bxx1x: state = 1; + 4'bxxx1: state = 0; + default: state = 0; + endcase + end + + always @(encoding) begin + case (encoding) + 4'b0000: state = 1; + default: state = 0; + endcase + end +endmodule diff --git a/tests/hana/test_parse2synthtrans_contassign_1_test.v b/tests/hana/test_parse2synthtrans_contassign_1_test.v new file mode 100644 index 00000000..78bf0077 --- /dev/null +++ b/tests/hana/test_parse2synthtrans_contassign_1_test.v @@ -0,0 +1,7 @@ +module test(in, out); + +input wire in; +output out; +assign out = (in+in); +assign out = 74; +endmodule diff --git a/tests/hana/test_parse2synthtrans_module_basic0_test.v b/tests/hana/test_parse2synthtrans_module_basic0_test.v new file mode 100644 index 00000000..67a272df --- /dev/null +++ b/tests/hana/test_parse2synthtrans_module_basic0_test.v @@ -0,0 +1,2 @@ +module test; +endmodule diff --git a/tests/hana/test_parse2synthtrans_operators_1_test.v b/tests/hana/test_parse2synthtrans_operators_1_test.v new file mode 100644 index 00000000..93b5691f --- /dev/null +++ b/tests/hana/test_parse2synthtrans_operators_1_test.v @@ -0,0 +1,11 @@ +module test(in, out); +input in; +output out; +parameter p1 = 10; +parameter p2 = 5; + +assign out = +p1; +assign out = -p2; +assign out = p1 + p2; +assign out = p1 - p2; +endmodule diff --git a/tests/hana/test_parse2synthtrans_param_1_test.v b/tests/hana/test_parse2synthtrans_param_1_test.v new file mode 100644 index 00000000..146eedf4 --- /dev/null +++ b/tests/hana/test_parse2synthtrans_param_1_test.v @@ -0,0 +1,7 @@ +module test(in, out); +input in; +output out; +parameter p = 10; + +assign out = p; +endmodule diff --git a/tests/hana/test_parse2synthtrans_port_scalar_1_test.v b/tests/hana/test_parse2synthtrans_port_scalar_1_test.v new file mode 100644 index 00000000..8cdf495a --- /dev/null +++ b/tests/hana/test_parse2synthtrans_port_scalar_1_test.v @@ -0,0 +1,6 @@ +module test(in, out, io); +inout io; +output out; +input in; + +endmodule diff --git a/tests/hana/test_parse2synthtrans_port_vector_1_test.v b/tests/hana/test_parse2synthtrans_port_vector_1_test.v new file mode 100644 index 00000000..a740282b --- /dev/null +++ b/tests/hana/test_parse2synthtrans_port_vector_1_test.v @@ -0,0 +1,9 @@ +module test(in1, in2, out1, out2, io1, io2); +inout [1:0] io1; +inout [0:1] io2; +output [1:0] out1; +output [0:1] out2; +input [1:0] in1; +input [0:1] in2; + +endmodule diff --git a/tests/hana/test_parse2synthtrans_v2k_comb_logic_sens_list_test.v b/tests/hana/test_parse2synthtrans_v2k_comb_logic_sens_list_test.v new file mode 100644 index 00000000..50f1d353 --- /dev/null +++ b/tests/hana/test_parse2synthtrans_v2k_comb_logic_sens_list_test.v @@ -0,0 +1,9 @@ +module test(q, d, clk, reset); +output reg q; +input d, clk, reset; + +always @ (posedge clk, negedge reset) + if(!reset) q <= 0; + else q <= d; + +endmodule diff --git a/tests/hana/test_parser_constructs_module_basic1_test.v b/tests/hana/test_parser_constructs_module_basic1_test.v new file mode 100644 index 00000000..67a272df --- /dev/null +++ b/tests/hana/test_parser_constructs_module_basic1_test.v @@ -0,0 +1,2 @@ +module test; +endmodule diff --git a/tests/hana/test_parser_constructs_param_basic0_test.v b/tests/hana/test_parser_constructs_param_basic0_test.v new file mode 100644 index 00000000..fd679230 --- /dev/null +++ b/tests/hana/test_parser_constructs_param_basic0_test.v @@ -0,0 +1,10 @@ +module test #( parameter v2kparam = 5) +(in, out, io, vin, vout, vio); +input in; +output out; +inout io; +input [3:0] vin; +output [v2kparam:0] vout; +inout [0:3] vio; +parameter myparam = 10; +endmodule diff --git a/tests/hana/test_parser_constructs_port_basic0_test.v b/tests/hana/test_parser_constructs_port_basic0_test.v new file mode 100644 index 00000000..8478e31d --- /dev/null +++ b/tests/hana/test_parser_constructs_port_basic0_test.v @@ -0,0 +1,8 @@ +module test(in, out, io, vin, vout, vio); +input in; +output out; +inout io; +input [3:0] vin; +output [3:0] vout; +inout [0:3] vio; +endmodule diff --git a/tests/hana/test_parser_directives_define_simpledef_test.v b/tests/hana/test_parser_directives_define_simpledef_test.v new file mode 100644 index 00000000..4a5d2345 --- /dev/null +++ b/tests/hana/test_parser_directives_define_simpledef_test.v @@ -0,0 +1,9 @@ +`define parvez ahmad +`define WIRE wire +`define TEN 10 + +module `parvez(); +parameter param = `TEN; +`WIRE w; +assign w = `TEN; +endmodule diff --git a/tests/hana/test_parser_misc_operators_test.v b/tests/hana/test_parser_misc_operators_test.v new file mode 100644 index 00000000..8fe8e7ba --- /dev/null +++ b/tests/hana/test_parser_misc_operators_test.v @@ -0,0 +1,29 @@ +module test(out, i0, i1, i2, i3, s1, s0); +output out; +input i0, i1, i2, i3; +input s1, s0; + +assign out = (~s1 & s0 & i0) | + (~s1 & s0 & i1) | + (s1 & ~s0 & i2) | + (s1 & s0 & i3); + +endmodule + +module ternaryop(out, i0, i1, i2, i3, s1, s0); +output out; +input i0, i1, i2, i3; +input s1, s0; + +assign out = s1 ? (s0 ? i3 : i2) : (s0 ? i1 : i0); + +endmodule + +module fulladd4(sum, c_out, a, b, c_in); +output [3:0] sum; +output c_out; +input [3:0] a, b; +input c_in; + +assign {c_out, sum} = a + b + c_in; +endmodule diff --git a/tests/hana/test_parser_v2k_comb_port_data_type_test.v b/tests/hana/test_parser_v2k_comb_port_data_type_test.v new file mode 100644 index 00000000..099585b5 --- /dev/null +++ b/tests/hana/test_parser_v2k_comb_port_data_type_test.v @@ -0,0 +1,6 @@ +module adder(sum , co, a, b, ci); +output reg [31:0] sum; +output reg co; +input wire [31:0] a, b; +input wire ci; +endmodule diff --git a/tests/hana/test_parser_v2k_comma_sep_sens_list_test.v b/tests/hana/test_parser_v2k_comma_sep_sens_list_test.v new file mode 100644 index 00000000..50f1d353 --- /dev/null +++ b/tests/hana/test_parser_v2k_comma_sep_sens_list_test.v @@ -0,0 +1,9 @@ +module test(q, d, clk, reset); +output reg q; +input d, clk, reset; + +always @ (posedge clk, negedge reset) + if(!reset) q <= 0; + else q <= d; + +endmodule diff --git a/tests/hana/test_simulation_always_15_test.v b/tests/hana/test_simulation_always_15_test.v new file mode 100644 index 00000000..5c5fed5b --- /dev/null +++ b/tests/hana/test_simulation_always_15_test.v @@ -0,0 +1,5 @@ +module test(input [1:0] in, output reg [1:0] out); + +always @(in) + out = in; +endmodule diff --git a/tests/hana/test_simulation_always_17_test.v b/tests/hana/test_simulation_always_17_test.v new file mode 100644 index 00000000..2d5abc4a --- /dev/null +++ b/tests/hana/test_simulation_always_17_test.v @@ -0,0 +1,13 @@ +module test(a, b, c, d, z); +input a, b, c, d; +output z; +reg z, temp1, temp2; + +always @(a or b or c or d) +begin + temp1 = a ^ b; + temp2 = c ^ d; + z = temp1 ^ temp2; +end + +endmodule diff --git a/tests/hana/test_simulation_always_18_test.v b/tests/hana/test_simulation_always_18_test.v new file mode 100644 index 00000000..234407ef --- /dev/null +++ b/tests/hana/test_simulation_always_18_test.v @@ -0,0 +1,10 @@ +module test (in1, in2, out); +input in1, in2; +output reg out; + +always @ ( in1 or in2) + if(in1 > in2) + out = in1; + else + out = in2; +endmodule diff --git a/tests/hana/test_simulation_always_19_test.v b/tests/hana/test_simulation_always_19_test.v new file mode 100644 index 00000000..5152781d --- /dev/null +++ b/tests/hana/test_simulation_always_19_test.v @@ -0,0 +1,11 @@ +module test(ctrl, in1, in2, out); +input ctrl; +input in1, in2; +output reg out; + +always @ (ctrl or in1 or in2) + if(ctrl) + out = in1 & in2; + else + out = in1 | in2; +endmodule diff --git a/tests/hana/test_simulation_always_1_test.v b/tests/hana/test_simulation_always_1_test.v new file mode 100644 index 00000000..211369cb --- /dev/null +++ b/tests/hana/test_simulation_always_1_test.v @@ -0,0 +1,5 @@ +module test(input in, output reg out); + +always @(in) + out = in; +endmodule diff --git a/tests/hana/test_simulation_always_20_test.v b/tests/hana/test_simulation_always_20_test.v new file mode 100644 index 00000000..6b3e861d --- /dev/null +++ b/tests/hana/test_simulation_always_20_test.v @@ -0,0 +1,15 @@ +module NonBlockingEx(clk, merge, er, xmit, fddi, claim); +input clk, merge, er, xmit, fddi; +output reg claim; +reg fcr; + +always @(posedge clk) +begin + fcr <= er | xmit; + + if(merge) + claim <= fcr & fddi; + else + claim <= fddi; +end +endmodule diff --git a/tests/hana/test_simulation_always_21_test.v b/tests/hana/test_simulation_always_21_test.v new file mode 100644 index 00000000..6c47b4bd --- /dev/null +++ b/tests/hana/test_simulation_always_21_test.v @@ -0,0 +1,11 @@ +module FlipFlop(clk, cs, ns); +input clk; +input [7:0] cs; +output [7:0] ns; +integer is; + +always @(posedge clk) + is <= cs; + +assign ns = is; +endmodule diff --git a/tests/hana/test_simulation_always_22_test.v b/tests/hana/test_simulation_always_22_test.v new file mode 100644 index 00000000..8d91f815 --- /dev/null +++ b/tests/hana/test_simulation_always_22_test.v @@ -0,0 +1,7 @@ +module inc(clock, counter); + +input clock; +output reg [7:0] counter; +always @(posedge clock) + counter <= counter + 1; +endmodule diff --git a/tests/hana/test_simulation_always_23_test.v b/tests/hana/test_simulation_always_23_test.v new file mode 100644 index 00000000..f1f13bbe --- /dev/null +++ b/tests/hana/test_simulation_always_23_test.v @@ -0,0 +1,14 @@ +module MyCounter (clock, preset, updown, presetdata, counter); +input clock, preset, updown; +input [1: 0] presetdata; +output reg [1:0] counter; + +always @(posedge clock) + if(preset) + counter <= presetdata; + else + if(updown) + counter <= counter + 1; + else + counter <= counter - 1; +endmodule diff --git a/tests/hana/test_simulation_always_27_test.v b/tests/hana/test_simulation_always_27_test.v new file mode 100644 index 00000000..577378fd --- /dev/null +++ b/tests/hana/test_simulation_always_27_test.v @@ -0,0 +1,13 @@ +module FlipFlop(clock, cs, ns); +input clock; +input cs; +output reg ns; +reg temp; + +always @(posedge clock) +begin + temp <= cs; + ns <= temp; +end + +endmodule diff --git a/tests/hana/test_simulation_always_29_test.v b/tests/hana/test_simulation_always_29_test.v new file mode 100644 index 00000000..55606832 --- /dev/null +++ b/tests/hana/test_simulation_always_29_test.v @@ -0,0 +1,9 @@ +module test(input in, output reg [1:0] out); + + always @(in) + begin + out = in; + out = out + in; + end + +endmodule diff --git a/tests/hana/test_simulation_always_31_tt.v b/tests/hana/test_simulation_always_31_tt.v new file mode 100644 index 00000000..299c0ca4 --- /dev/null +++ b/tests/hana/test_simulation_always_31_tt.v @@ -0,0 +1,50 @@ +module test(clk, cond, data); +input cond; +input clk; +output data; + +wire synth_net; +wire synth_net_0; +wire synth_net_1; +wire synth_net_2; + +wire synth_net_3; +wire synth_net_4; +wire synth_net_5; +wire synth_net_6; + +wire synth_net_7; +wire synth_net_8; +wire synth_net_9; +wire synth_net_10; + +wire synth_net_11; +wire tmp; +AND2 synth_AND(.in({synth_net_0, synth_net_1}), . + out(synth_net_2)); +AND2 synth_AND_0(.in({synth_net_3, synth_net_4}), .out( + synth_net_5)); +AND2 synth_AND_1(.in({synth_net_6, synth_net_7}), .out( + synth_net_8)); +AND2 synth_AND_2(.in({synth_net_9, synth_net_10}), .out( + synth_net_11)); +BUF synth_BUF(.in(synth_net), .out(synth_net_0)); +BUF + synth_BUF_0(.in(data), .out(synth_net_3)); +BUF synth_BUF_1(.in(synth_net_8) + , .out(tmp)); +BUF synth_BUF_2(.in(tmp), .out(synth_net_9)); +MUX2 synth_MUX(. + in({synth_net_2, synth_net_5}), .select(cond), .out(synth_net_6)); +MUX2 + synth_MUX_0(.in({synth_net_1, synth_net_4}), .select(cond), .out(synth_net_7 + )); +FF synth_FF(.d(synth_net_11), .clk(clk), .q(data)); +VCC synth_VCC(.out( + synth_net)); +VCC synth_VCC_0(.out(synth_net_1)); +VCC synth_VCC_1(.out( + synth_net_4)); +VCC synth_VCC_2(.out(synth_net_10)); +endmodule + diff --git a/tests/hana/test_simulation_and_1_test.v b/tests/hana/test_simulation_and_1_test.v new file mode 100644 index 00000000..fba639ca --- /dev/null +++ b/tests/hana/test_simulation_and_1_test.v @@ -0,0 +1,3 @@ +module test(input [1:0] in, output out); +assign out = in[0] & in[1]; +endmodule diff --git a/tests/hana/test_simulation_and_2_test.v b/tests/hana/test_simulation_and_2_test.v new file mode 100644 index 00000000..715bc7ca --- /dev/null +++ b/tests/hana/test_simulation_and_2_test.v @@ -0,0 +1,3 @@ +module test(input [1:0] in, output out); +assign out = in[0] && in[1]; +endmodule diff --git a/tests/hana/test_simulation_and_3_test.v b/tests/hana/test_simulation_and_3_test.v new file mode 100644 index 00000000..74dccabf --- /dev/null +++ b/tests/hana/test_simulation_and_3_test.v @@ -0,0 +1,3 @@ +module test(input [2:0] in, output out); +assign out = in[0] & in[1] & in[2]; +endmodule diff --git a/tests/hana/test_simulation_and_4_test.v b/tests/hana/test_simulation_and_4_test.v new file mode 100644 index 00000000..48ed9102 --- /dev/null +++ b/tests/hana/test_simulation_and_4_test.v @@ -0,0 +1,3 @@ +module test(input [2:0] in, output out); +assign out = in[0] && in[1] && in[2]; +endmodule diff --git a/tests/hana/test_simulation_and_5_test.v b/tests/hana/test_simulation_and_5_test.v new file mode 100644 index 00000000..29a35578 --- /dev/null +++ b/tests/hana/test_simulation_and_5_test.v @@ -0,0 +1,3 @@ +module test(input [3:0] in, output out); +assign out = in[0] & in[1] & in[2] & in[3]; +endmodule diff --git a/tests/hana/test_simulation_and_6_test.v b/tests/hana/test_simulation_and_6_test.v new file mode 100644 index 00000000..ebce4eeb --- /dev/null +++ b/tests/hana/test_simulation_and_6_test.v @@ -0,0 +1,3 @@ +module test(input [3:0] in, output out); +assign out = in[0] && in[1] && in[2] && in[3]; +endmodule diff --git a/tests/hana/test_simulation_and_7_test.v b/tests/hana/test_simulation_and_7_test.v new file mode 100644 index 00000000..d394adad --- /dev/null +++ b/tests/hana/test_simulation_and_7_test.v @@ -0,0 +1,3 @@ +module test(input [3:0] in, output out); +and myand(out, in[0], in[1], in[2], in[3]); +endmodule diff --git a/tests/hana/test_simulation_buffer_1_test.v b/tests/hana/test_simulation_buffer_1_test.v new file mode 100644 index 00000000..e9bb7f61 --- /dev/null +++ b/tests/hana/test_simulation_buffer_1_test.v @@ -0,0 +1,3 @@ +module test(input in, output out); +assign out = in; +endmodule diff --git a/tests/hana/test_simulation_buffer_2_test.v b/tests/hana/test_simulation_buffer_2_test.v new file mode 100644 index 00000000..9a3f5aa3 --- /dev/null +++ b/tests/hana/test_simulation_buffer_2_test.v @@ -0,0 +1,4 @@ +module test(input [1:0] in, output [1:0] out); +assign out[0] = in[0]; +assign out[1] = in[1]; +endmodule diff --git a/tests/hana/test_simulation_buffer_3_test.v b/tests/hana/test_simulation_buffer_3_test.v new file mode 100644 index 00000000..9bca426d --- /dev/null +++ b/tests/hana/test_simulation_buffer_3_test.v @@ -0,0 +1,4 @@ +module test(input in, output [1:0] out); +assign out[0] = in; +assign out[1] = in; +endmodule diff --git a/tests/hana/test_simulation_decoder_2_test.v b/tests/hana/test_simulation_decoder_2_test.v new file mode 100644 index 00000000..5bdf1971 --- /dev/null +++ b/tests/hana/test_simulation_decoder_2_test.v @@ -0,0 +1,14 @@ +module test (input [1:0] in, input enable, output reg out); + +always @(in or enable) + if(!enable) + out = 4'b0000; + else begin + case (in) + 2'b00 : out = 0 ; + 2'b01 : out = 1; + 2'b10 : out = 0; + 2'b11 : out = 1; + endcase + end +endmodule diff --git a/tests/hana/test_simulation_decoder_3_test.v b/tests/hana/test_simulation_decoder_3_test.v new file mode 100644 index 00000000..44f5de12 --- /dev/null +++ b/tests/hana/test_simulation_decoder_3_test.v @@ -0,0 +1,14 @@ +module test (input [1:0] in, input enable, output reg [2:0] out); + +always @(in or enable) + if(!enable) + out = 3'b000; + else begin + case (in) + 2'b00 : out = 3'b001 ; + 2'b01 : out = 3'b010; + 2'b10 : out = 3'b010; + 2'b11 : out = 3'b100; + endcase + end +endmodule diff --git a/tests/hana/test_simulation_decoder_4_test.v b/tests/hana/test_simulation_decoder_4_test.v new file mode 100644 index 00000000..871a5bbf --- /dev/null +++ b/tests/hana/test_simulation_decoder_4_test.v @@ -0,0 +1,14 @@ +module test (input [2:0] in, output reg [7:0] out); + +always @(in ) + case (in) + 3'b000 : out = 8'b00000001; + 3'b001 : out = 8'b00000010; + 3'b010 : out = 8'b00000100; + 3'b011 : out = 8'b00001000; + 3'b100 : out = 8'b00010000; + 3'b101 : out = 8'b00100000; + 3'b110 : out = 8'b01000000; + 3'b111 : out = 8'b10000000; + endcase +endmodule diff --git a/tests/hana/test_simulation_decoder_5_test.v b/tests/hana/test_simulation_decoder_5_test.v new file mode 100644 index 00000000..497fa4bf --- /dev/null +++ b/tests/hana/test_simulation_decoder_5_test.v @@ -0,0 +1,17 @@ +module test (input [2:0] in, input enable, output reg [7:0] out); + +always @(in or enable ) + if(!enable) + out = 8'b00000000; + else + case (in) + 3'b000 : out = 8'b00000001; + 3'b001 : out = 8'b00000010; + 3'b010 : out = 8'b00000100; + 3'b011 : out = 8'b00001000; + 3'b100 : out = 8'b00010000; + 3'b101 : out = 8'b00100000; + 3'b110 : out = 8'b01000000; + 3'b111 : out = 8'b10000000; + endcase +endmodule diff --git a/tests/hana/test_simulation_decoder_6_test.v b/tests/hana/test_simulation_decoder_6_test.v new file mode 100644 index 00000000..fd19ad60 --- /dev/null +++ b/tests/hana/test_simulation_decoder_6_test.v @@ -0,0 +1,27 @@ +module test (input [3:0] in, input enable, output reg [15:0] out); + +always @(in or enable) + if(!enable) + out = 16'b0000000000000000; + else begin + case (in) + 4'b0000 : out = 16'b0000000000000001; + 4'b0001 : out = 16'b0000000000000010; + 4'b0010 : out = 16'b0000000000000100; + 4'b0011 : out = 16'b0000000000001000; + 4'b0100 : out = 16'b0000000000010000; + 4'b0101 : out = 16'b0000000000100000; + 4'b0110 : out = 16'b0000000001000000; + 4'b0111 : out = 16'b0000000010000000; + 4'b1000 : out = 16'b0000000100000000; + 4'b1001 : out = 16'b0000001000000000; + 4'b1010 : out = 16'b0000010000000000; + 4'b1011 : out = 16'b0000100000000000; + 4'b1100 : out = 16'b0001000000000000; + 4'b1101 : out = 16'b0010000000000000; + 4'b1110 : out = 16'b0100000000000000; + 4'b1111 : out = 16'b1000000000000000; + endcase + end +endmodule + diff --git a/tests/hana/test_simulation_decoder_7_test.v b/tests/hana/test_simulation_decoder_7_test.v new file mode 100644 index 00000000..462e9419 --- /dev/null +++ b/tests/hana/test_simulation_decoder_7_test.v @@ -0,0 +1,43 @@ +module test (input [4:0] in, input enable, output reg [31:0] out); + +always @(in or enable) + if(!enable) + out = 32'b00000000000000000000000000000000; + else begin + case (in) + 5'b00000 : out = 32'b00000000000000000000000000000001; + 5'b00001 : out = 32'b00000000000000000000000000000010; + 5'b00010 : out = 32'b00000000000000000000000000000100; + 5'b00011 : out = 32'b00000000000000000000000000001000; + 5'b00100 : out = 32'b00000000000000000000000000010000; + 5'b00101 : out = 32'b00000000000000000000000000100000; + 5'b00110 : out = 32'b00000000000000000000000001000000; + 5'b00111 : out = 32'b00000000000000000000000010000000; + 5'b01000 : out = 32'b00000000000000000000000100000000; + 5'b01001 : out = 32'b00000000000000000000001000000000; + 5'b01010 : out = 32'b00000000000000000000010000000000; + 5'b01011 : out = 32'b00000000000000000000100000000000; + 5'b01100 : out = 32'b00000000000000000001000000000000; + 5'b01101 : out = 32'b00000000000000000010000000000000; + 5'b01110 : out = 32'b00000000000000000100000000000000; + 5'b01111 : out = 32'b00000000000000001000000000000000; + 5'b10000 : out = 32'b00000000000000010000000000000000; + 5'b10001 : out = 32'b00000000000000100000000000000000; + 5'b10010 : out = 32'b00000000000001000000000000000000; + 5'b10011 : out = 32'b00000000000010000000000000000000; + 5'b10100 : out = 32'b00000000000100000000000000000000; + 5'b10101 : out = 32'b00000000001000000000000000000000; + 5'b10110 : out = 32'b00000000010000000000000000000000; + 5'b10111 : out = 32'b00000000100000000000000000000000; + 5'b11000 : out = 32'b00000001000000000000000000000000; + 5'b11001 : out = 32'b00000010000000000000000000000000; + 5'b11010 : out = 32'b00000100000000000000000000000000; + 5'b11011 : out = 32'b00001000000000000000000000000000; + 5'b11100 : out = 32'b00010000000000000000000000000000; + 5'b11101 : out = 32'b00100000000000000000000000000000; + 5'b11110 : out = 32'b01000000000000000000000000000000; + 5'b11111 : out = 32'b10000000000000000000000000000000; + endcase + end +endmodule + diff --git a/tests/hana/test_simulation_decoder_8_test.v b/tests/hana/test_simulation_decoder_8_test.v new file mode 100644 index 00000000..751d60f6 --- /dev/null +++ b/tests/hana/test_simulation_decoder_8_test.v @@ -0,0 +1,76 @@ +module test (input [5:0] in, input enable, output reg [63:0] out); + +always @(in or enable) + if(!enable) + out = 64'b0000000000000000000000000000000000000000000000000000000000000000; + else begin + case (in) + 6'b000000 : out = 64'b0000000000000000000000000000000000000000000000000000000000000001; + 6'b000001 : out = 64'b0000000000000000000000000000000000000000000000000000000000000010; + 6'b000010 : out = 64'b0000000000000000000000000000000000000000000000000000000000000100; + 6'b000011 : out = 64'b0000000000000000000000000000000000000000000000000000000000001000; + 6'b000100 : out = 64'b0000000000000000000000000000000000000000000000000000000000010000; + 6'b000101 : out = 64'b0000000000000000000000000000000000000000000000000000000000100000; + 6'b000110 : out = 64'b0000000000000000000000000000000000000000000000000000000001000000; + 6'b000111 : out = 64'b0000000000000000000000000000000000000000000000000000000010000000; + 6'b001000 : out = 64'b0000000000000000000000000000000000000000000000000000000100000000; + 6'b001001 : out = 64'b0000000000000000000000000000000000000000000000000000001000000000; + 6'b001010 : out = 64'b0000000000000000000000000000000000000000000000000000010000000000; + 6'b001011 : out = 64'b0000000000000000000000000000000000000000000000000000100000000000; + 6'b001100 : out = 64'b0000000000000000000000000000000000000000000000000001000000000000; + 6'b001101 : out = 64'b0000000000000000000000000000000000000000000000000010000000000000; + 6'b001110 : out = 64'b0000000000000000000000000000000000000000000000000100000000000000; + 6'b001111 : out = 64'b0000000000000000000000000000000000000000000000001000000000000000; + 6'b010000 : out = 64'b0000000000000000000000000000000000000000000000010000000000000000; + 6'b010001 : out = 64'b0000000000000000000000000000000000000000000000100000000000000000; + 6'b010010 : out = 64'b0000000000000000000000000000000000000000000001000000000000000000; + 6'b010011 : out = 64'b0000000000000000000000000000000000000000000010000000000000000000; + 6'b010100 : out = 64'b0000000000000000000000000000000000000000000100000000000000000000; + 6'b010101 : out = 64'b0000000000000000000000000000000000000000001000000000000000000000; + 6'b010110 : out = 64'b0000000000000000000000000000000000000000010000000000000000000000; + 6'b010111 : out = 64'b0000000000000000000000000000000000000000100000000000000000000000; + 6'b011000 : out = 64'b0000000000000000000000000000000000000001000000000000000000000000; + 6'b011001 : out = 64'b0000000000000000000000000000000000000010000000000000000000000000; + 6'b011010 : out = 64'b0000000000000000000000000000000000000100000000000000000000000000; + 6'b011011 : out = 64'b0000000000000000000000000000000000001000000000000000000000000000; + 6'b011100 : out = 64'b0000000000000000000000000000000000010000000000000000000000000000; + 6'b011101 : out = 64'b0000000000000000000000000000000000100000000000000000000000000000; + 6'b011110 : out = 64'b0000000000000000000000000000000001000000000000000000000000000000; + 6'b011111 : out = 64'b0000000000000000000000000000000010000000000000000000000000000000; + + 6'b100000 : out = 64'b0000000000000000000000000000000100000000000000000000000000000000; + 6'b100001 : out = 64'b0000000000000000000000000000001000000000000000000000000000000000; + 6'b100010 : out = 64'b0000000000000000000000000000010000000000000000000000000000000000; + 6'b100011 : out = 64'b0000000000000000000000000000100000000000000000000000000000000000; + 6'b100100 : out = 64'b0000000000000000000000000001000000000000000000000000000000000000; + 6'b100101 : out = 64'b0000000000000000000000000010000000000000000000000000000000000000; + 6'b100110 : out = 64'b0000000000000000000000000100000000000000000000000000000000000000; + 6'b100111 : out = 64'b0000000000000000000000001000000000000000000000000000000000000000; + 6'b101000 : out = 64'b0000000000000000000000010000000000000000000000000000000000000000; + 6'b101001 : out = 64'b0000000000000000000000100000000000000000000000000000000000000000; + 6'b101010 : out = 64'b0000000000000000000001000000000000000000000000000000000000000000; + 6'b101011 : out = 64'b0000000000000000000010000000000000000000000000000000000000000000; + 6'b101100 : out = 64'b0000000000000000000100000000000000000000000000000000000000000000; + 6'b101101 : out = 64'b0000000000000000001000000000000000000000000000000000000000000000; + 6'b101110 : out = 64'b0000000000000000010000000000000000000000000000000000000000000000; + 6'b101111 : out = 64'b0000000000000000100000000000000000000000000000000000000000000000; + 6'b110000 : out = 64'b0000000000000001000000000000000000000000000000000000000000000000; + 6'b110001 : out = 64'b0000000000000010000000000000000000000000000000000000000000000000; + 6'b110010 : out = 64'b0000000000000100000000000000000000000000000000000000000000000000; + 6'b110011 : out = 64'b0000000000001000000000000000000000000000000000000000000000000000; + 6'b110100 : out = 64'b0000000000010000000000000000000000000000000000000000000000000000; + 6'b110101 : out = 64'b0000000000100000000000000000000000000000000000000000000000000000; + 6'b110110 : out = 64'b0000000001000000000000000000000000000000000000000000000000000000; + 6'b110111 : out = 64'b0000000010000000000000000000000000000000000000000000000000000000; + 6'b111000 : out = 64'b0000000100000000000000000000000000000000000000000000000000000000; + 6'b111001 : out = 64'b0000001000000000000000000000000000000000000000000000000000000000; + 6'b111010 : out = 64'b0000010000000000000000000000000000000000000000000000000000000000; + 6'b111011 : out = 64'b0000100000000000000000000000000000000000000000000000000000000000; + 6'b111100 : out = 64'b0001000000000000000000000000000000000000000000000000000000000000; + 6'b111101 : out = 64'b0010000000000000000000000000000000000000000000000000000000000000; + 6'b111110 : out = 64'b0100000000000000000000000000000000000000000000000000000000000000; + 6'b111111 : out = 64'b1000000000000000000000000000000000000000000000000000000000000000; + endcase + end +endmodule + diff --git a/tests/hana/test_simulation_inc_16_test.v b/tests/hana/test_simulation_inc_16_test.v new file mode 100644 index 00000000..7ff42ff5 --- /dev/null +++ b/tests/hana/test_simulation_inc_16_test.v @@ -0,0 +1,5 @@ +module test(input [15:0] in, output [15:0] out); + +assign out = -in; + +endmodule diff --git a/tests/hana/test_simulation_inc_1_test.v b/tests/hana/test_simulation_inc_1_test.v new file mode 100644 index 00000000..02bec2c2 --- /dev/null +++ b/tests/hana/test_simulation_inc_1_test.v @@ -0,0 +1,5 @@ +module test(input in, output out); + +assign out = -in; + +endmodule diff --git a/tests/hana/test_simulation_inc_2_test.v b/tests/hana/test_simulation_inc_2_test.v new file mode 100644 index 00000000..b96e05a2 --- /dev/null +++ b/tests/hana/test_simulation_inc_2_test.v @@ -0,0 +1,5 @@ +module test(input [1:0] in, output [1:0] out); + +assign out = -in; + +endmodule diff --git a/tests/hana/test_simulation_inc_32_test.v b/tests/hana/test_simulation_inc_32_test.v new file mode 100644 index 00000000..5700d0ce --- /dev/null +++ b/tests/hana/test_simulation_inc_32_test.v @@ -0,0 +1,5 @@ +module test(input [31:0] in, output [31:0] out); + +assign out = -in; + +endmodule diff --git a/tests/hana/test_simulation_inc_4_test.v b/tests/hana/test_simulation_inc_4_test.v new file mode 100644 index 00000000..34940d63 --- /dev/null +++ b/tests/hana/test_simulation_inc_4_test.v @@ -0,0 +1,5 @@ +module test(input [3:0] in, output [3:0] out); + +assign out = -in; + +endmodule diff --git a/tests/hana/test_simulation_inc_8_test.v b/tests/hana/test_simulation_inc_8_test.v new file mode 100644 index 00000000..c36d69f0 --- /dev/null +++ b/tests/hana/test_simulation_inc_8_test.v @@ -0,0 +1,5 @@ +module test(input [7:0] in, output [7:0] out); + +assign out = -in; + +endmodule diff --git a/tests/hana/test_simulation_mod_1_xx.v b/tests/hana/test_simulation_mod_1_xx.v new file mode 100644 index 00000000..75144a8e --- /dev/null +++ b/tests/hana/test_simulation_mod_1_xx.v @@ -0,0 +1,13 @@ +module test(in1, in2, out); +input in1; +input in2; +output out; + +wire synth_net_0; +wire synth_net_1; +BUF synth_BUF_0(.in(synth_net_1), .out(out + )); +DIV1 synth_DIV(.in1(in1), .in2(in2), .rem(synth_net_0), .out(synth_net_1 + )); +endmodule + diff --git a/tests/hana/test_simulation_mux_16_test.v b/tests/hana/test_simulation_mux_16_test.v new file mode 100644 index 00000000..de4b6f8e --- /dev/null +++ b/tests/hana/test_simulation_mux_16_test.v @@ -0,0 +1,22 @@ +module test(input [15:0] in, input [3:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + 4: out = in[4]; + 5: out = in[5]; + 6: out = in[6]; + 7: out = in[7]; + 8: out = in[8]; + 9: out = in[9]; + 10: out = in[10]; + 11: out = in[11]; + 12: out = in[12]; + 13: out = in[13]; + 14: out = in[14]; + 15: out = in[15]; + endcase +endmodule diff --git a/tests/hana/test_simulation_mux_2_test.v b/tests/hana/test_simulation_mux_2_test.v new file mode 100644 index 00000000..bc676c70 --- /dev/null +++ b/tests/hana/test_simulation_mux_2_test.v @@ -0,0 +1,8 @@ +module test(input [1:0] in, input select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + endcase +endmodule diff --git a/tests/hana/test_simulation_mux_32_test.v b/tests/hana/test_simulation_mux_32_test.v new file mode 100644 index 00000000..16de4d7f --- /dev/null +++ b/tests/hana/test_simulation_mux_32_test.v @@ -0,0 +1,39 @@ +module test(input [31:0] in, input [4:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + 4: out = in[4]; + 5: out = in[5]; + 6: out = in[6]; + 7: out = in[7]; + 8: out = in[8]; + 9: out = in[9]; + 10: out = in[10]; + 11: out = in[11]; + 12: out = in[12]; + 13: out = in[13]; + 14: out = in[14]; + 15: out = in[15]; + 16: out = in[16]; + 17: out = in[17]; + 18: out = in[18]; + 19: out = in[19]; + 20: out = in[20]; + 21: out = in[21]; + 22: out = in[22]; + 23: out = in[23]; + 24: out = in[24]; + 25: out = in[25]; + 26: out = in[26]; + 27: out = in[27]; + 28: out = in[28]; + 29: out = in[29]; + 30: out = in[30]; + 31: out = in[31]; + endcase +endmodule + diff --git a/tests/hana/test_simulation_mux_4_test.v b/tests/hana/test_simulation_mux_4_test.v new file mode 100644 index 00000000..6a112c6a --- /dev/null +++ b/tests/hana/test_simulation_mux_4_test.v @@ -0,0 +1,10 @@ +module test(input [3:0] in, input [1:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + endcase +endmodule diff --git a/tests/hana/test_simulation_mux_64_test.v b/tests/hana/test_simulation_mux_64_test.v new file mode 100644 index 00000000..420239c6 --- /dev/null +++ b/tests/hana/test_simulation_mux_64_test.v @@ -0,0 +1,71 @@ +module test(input [63:0] in, input [5:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + 4: out = in[4]; + 5: out = in[5]; + 6: out = in[6]; + 7: out = in[7]; + 8: out = in[8]; + 9: out = in[9]; + 10: out = in[10]; + 11: out = in[11]; + 12: out = in[12]; + 13: out = in[13]; + 14: out = in[14]; + 15: out = in[15]; + 16: out = in[16]; + 17: out = in[17]; + 18: out = in[18]; + 19: out = in[19]; + 20: out = in[20]; + 21: out = in[21]; + 22: out = in[22]; + 23: out = in[23]; + 24: out = in[24]; + 25: out = in[25]; + 26: out = in[26]; + 27: out = in[27]; + 28: out = in[28]; + 29: out = in[29]; + 30: out = in[30]; + 31: out = in[31]; + 32: out = in[32]; + 33: out = in[33]; + 34: out = in[34]; + 35: out = in[35]; + 36: out = in[36]; + 37: out = in[37]; + 38: out = in[38]; + 39: out = in[39]; + 40: out = in[40]; + 41: out = in[41]; + 42: out = in[42]; + 43: out = in[43]; + 44: out = in[44]; + 45: out = in[45]; + 46: out = in[46]; + 47: out = in[47]; + 48: out = in[48]; + 49: out = in[49]; + 50: out = in[50]; + 51: out = in[51]; + 52: out = in[52]; + 53: out = in[53]; + 54: out = in[54]; + 55: out = in[55]; + 56: out = in[56]; + 57: out = in[57]; + 58: out = in[58]; + 59: out = in[59]; + 60: out = in[60]; + 61: out = in[61]; + 62: out = in[62]; + 63: out = in[63]; + endcase +endmodule + diff --git a/tests/hana/test_simulation_mux_8_test.v b/tests/hana/test_simulation_mux_8_test.v new file mode 100644 index 00000000..f53a2c57 --- /dev/null +++ b/tests/hana/test_simulation_mux_8_test.v @@ -0,0 +1,14 @@ +module test(input [7:0] in, input [2:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + 4: out = in[4]; + 5: out = in[5]; + 6: out = in[6]; + 7: out = in[7]; + endcase +endmodule diff --git a/tests/hana/test_simulation_nand_1_test.v b/tests/hana/test_simulation_nand_1_test.v new file mode 100644 index 00000000..d8f34ee1 --- /dev/null +++ b/tests/hana/test_simulation_nand_1_test.v @@ -0,0 +1,3 @@ +module test(input [1:0] in, output out); +assign out = ~(in[0] & in[1]); +endmodule diff --git a/tests/hana/test_simulation_nand_3_test.v b/tests/hana/test_simulation_nand_3_test.v new file mode 100644 index 00000000..8926cebb --- /dev/null +++ b/tests/hana/test_simulation_nand_3_test.v @@ -0,0 +1,3 @@ +module test(input [2:0] in, output out); +assign out = !(in[0] & in[1] & in[2]); +endmodule diff --git a/tests/hana/test_simulation_nand_4_test.v b/tests/hana/test_simulation_nand_4_test.v new file mode 100644 index 00000000..703a2de4 --- /dev/null +++ b/tests/hana/test_simulation_nand_4_test.v @@ -0,0 +1,3 @@ +module test(input [2:0] in, output out); +assign out = ~(in[0] && in[1] && in[2]); +endmodule diff --git a/tests/hana/test_simulation_nand_5_test.v b/tests/hana/test_simulation_nand_5_test.v new file mode 100644 index 00000000..adef3c90 --- /dev/null +++ b/tests/hana/test_simulation_nand_5_test.v @@ -0,0 +1,3 @@ +module test(input [3:0] in, output out); +assign out = !(in[0] & in[1] & in[2] & in[3]); +endmodule diff --git a/tests/hana/test_simulation_nand_6_test.v b/tests/hana/test_simulation_nand_6_test.v new file mode 100644 index 00000000..a2136f21 --- /dev/null +++ b/tests/hana/test_simulation_nand_6_test.v @@ -0,0 +1,3 @@ +module test(input [3:0] in, output out); +assign out = !(in[0] && in[1] && in[2] && in[3]); +endmodule diff --git a/tests/hana/test_simulation_nor_1_test.v b/tests/hana/test_simulation_nor_1_test.v new file mode 100644 index 00000000..df4e8bfa --- /dev/null +++ b/tests/hana/test_simulation_nor_1_test.v @@ -0,0 +1,3 @@ +module test(input [1:0] in, output out); +assign out = ~(in[0] | in[1]); +endmodule diff --git a/tests/hana/test_simulation_nor_2_test.v b/tests/hana/test_simulation_nor_2_test.v new file mode 100644 index 00000000..2cfffc45 --- /dev/null +++ b/tests/hana/test_simulation_nor_2_test.v @@ -0,0 +1,3 @@ +module test(input [2:0] in, output out); +assign out = ~(in[0] | in[1] | in[2]); +endmodule diff --git a/tests/hana/test_simulation_nor_3_test.v b/tests/hana/test_simulation_nor_3_test.v new file mode 100644 index 00000000..9f1ef8fe --- /dev/null +++ b/tests/hana/test_simulation_nor_3_test.v @@ -0,0 +1,3 @@ +module test(input [3:0] in, output out); +assign out = ~(in[0] | in[1] | in[2] | in[3]); +endmodule diff --git a/tests/hana/test_simulation_nor_4_test.v b/tests/hana/test_simulation_nor_4_test.v new file mode 100644 index 00000000..d8e68504 --- /dev/null +++ b/tests/hana/test_simulation_nor_4_test.v @@ -0,0 +1,3 @@ +module test(input [3:0] in, output out); +nor mynor(out, in[0], in[1], in[2], in[3]); +endmodule diff --git a/tests/hana/test_simulation_opt_constprop_contassign_1_test.v b/tests/hana/test_simulation_opt_constprop_contassign_1_test.v new file mode 100644 index 00000000..a39b58b4 --- /dev/null +++ b/tests/hana/test_simulation_opt_constprop_contassign_1_test.v @@ -0,0 +1,3 @@ +module test(input in, output out); +assign out = 1'b1; +endmodule diff --git a/tests/hana/test_simulation_or_1_test.v b/tests/hana/test_simulation_or_1_test.v new file mode 100644 index 00000000..bdfffd3d --- /dev/null +++ b/tests/hana/test_simulation_or_1_test.v @@ -0,0 +1,3 @@ +module test(input [1:0] in, output out); +assign out = in[0] | in[1]; +endmodule diff --git a/tests/hana/test_simulation_or_2_test.v b/tests/hana/test_simulation_or_2_test.v new file mode 100644 index 00000000..291c8c76 --- /dev/null +++ b/tests/hana/test_simulation_or_2_test.v @@ -0,0 +1,3 @@ +module test(input [1:0] in, output out); +assign out = in[0] || in[1]; +endmodule diff --git a/tests/hana/test_simulation_or_3_test.v b/tests/hana/test_simulation_or_3_test.v new file mode 100644 index 00000000..ad00c708 --- /dev/null +++ b/tests/hana/test_simulation_or_3_test.v @@ -0,0 +1,3 @@ +module test(input [2:0] in, output out); +assign out = in[0] | in[1] | in[2]; +endmodule diff --git a/tests/hana/test_simulation_or_4_test.v b/tests/hana/test_simulation_or_4_test.v new file mode 100644 index 00000000..2ec57fa9 --- /dev/null +++ b/tests/hana/test_simulation_or_4_test.v @@ -0,0 +1,3 @@ +module test(input [2:0] in, output out); +assign out = in[0] || in[1] || in[2]; +endmodule diff --git a/tests/hana/test_simulation_or_5_test.v b/tests/hana/test_simulation_or_5_test.v new file mode 100644 index 00000000..f6a2d14d --- /dev/null +++ b/tests/hana/test_simulation_or_5_test.v @@ -0,0 +1,3 @@ +module test(input [3:0] in, output out); +assign out = in[0] | in[1] | in[2] | in[3]; +endmodule diff --git a/tests/hana/test_simulation_or_6_test.v b/tests/hana/test_simulation_or_6_test.v new file mode 100644 index 00000000..ecd85c36 --- /dev/null +++ b/tests/hana/test_simulation_or_6_test.v @@ -0,0 +1,3 @@ +module test(input [3:0] in, output out); +assign out = in[0] || in[1] || in[2] || in[3]; +endmodule diff --git a/tests/hana/test_simulation_seq_ff_1_test.v b/tests/hana/test_simulation_seq_ff_1_test.v new file mode 100644 index 00000000..5aac49c0 --- /dev/null +++ b/tests/hana/test_simulation_seq_ff_1_test.v @@ -0,0 +1,4 @@ +module test(input in, input clk, output reg out); +always @(posedge clk) + out <= in; +endmodule diff --git a/tests/hana/test_simulation_seq_ff_2_test.v b/tests/hana/test_simulation_seq_ff_2_test.v new file mode 100644 index 00000000..f1d2b7b4 --- /dev/null +++ b/tests/hana/test_simulation_seq_ff_2_test.v @@ -0,0 +1,4 @@ +module test(input in, input clk, output reg out); +always @(negedge clk) + out <= in; +endmodule diff --git a/tests/hana/test_simulation_shifter_left_16_test.v b/tests/hana/test_simulation_shifter_left_16_test.v new file mode 100644 index 00000000..a57dac49 --- /dev/null +++ b/tests/hana/test_simulation_shifter_left_16_test.v @@ -0,0 +1,4 @@ +module test(input [15:0] IN, input [4:0] SHIFT, output [15:0] OUT); + +assign OUT = IN << SHIFT; +endmodule diff --git a/tests/hana/test_simulation_shifter_left_32_test.v b/tests/hana/test_simulation_shifter_left_32_test.v new file mode 100644 index 00000000..672938ac --- /dev/null +++ b/tests/hana/test_simulation_shifter_left_32_test.v @@ -0,0 +1,4 @@ +module test(input [31:0] IN, input [5:0] SHIFT, output [31:0] OUT); + +assign OUT = IN << SHIFT; +endmodule diff --git a/tests/hana/test_simulation_shifter_left_4_test.v b/tests/hana/test_simulation_shifter_left_4_test.v new file mode 100644 index 00000000..c525401f --- /dev/null +++ b/tests/hana/test_simulation_shifter_left_4_test.v @@ -0,0 +1,4 @@ +module test(input [3:0] IN, input [2:0] SHIFT, output [3:0] OUT); + +assign OUT = IN << SHIFT; +endmodule diff --git a/tests/hana/test_simulation_shifter_left_64_test.v b/tests/hana/test_simulation_shifter_left_64_test.v new file mode 100644 index 00000000..276a7c5a --- /dev/null +++ b/tests/hana/test_simulation_shifter_left_64_test.v @@ -0,0 +1,4 @@ +module test(input [63:0] IN, input [6:0] SHIFT, output [63:0] OUT); + +assign OUT = IN << SHIFT; +endmodule diff --git a/tests/hana/test_simulation_shifter_left_8_test.v b/tests/hana/test_simulation_shifter_left_8_test.v new file mode 100644 index 00000000..c1727700 --- /dev/null +++ b/tests/hana/test_simulation_shifter_left_8_test.v @@ -0,0 +1,4 @@ +module test(input [7:0] IN, input [3:0] SHIFT, output [7:0] OUT); + +assign OUT = IN << SHIFT; +endmodule diff --git a/tests/hana/test_simulation_shifter_right_16_test.v b/tests/hana/test_simulation_shifter_right_16_test.v new file mode 100644 index 00000000..6152adc0 --- /dev/null +++ b/tests/hana/test_simulation_shifter_right_16_test.v @@ -0,0 +1,4 @@ +module test(input [15:0] IN, input [4:0] SHIFT, output [15:0] OUT); + +assign OUT = IN >> SHIFT; +endmodule diff --git a/tests/hana/test_simulation_shifter_right_32_test.v b/tests/hana/test_simulation_shifter_right_32_test.v new file mode 100644 index 00000000..e910cdd6 --- /dev/null +++ b/tests/hana/test_simulation_shifter_right_32_test.v @@ -0,0 +1,4 @@ +module test(input [31:0] IN, input [5:0] SHIFT, output [31:0] OUT); + +assign OUT = IN >> SHIFT; +endmodule diff --git a/tests/hana/test_simulation_shifter_right_4_test.v b/tests/hana/test_simulation_shifter_right_4_test.v new file mode 100644 index 00000000..608c196d --- /dev/null +++ b/tests/hana/test_simulation_shifter_right_4_test.v @@ -0,0 +1,4 @@ +module test(input [3:0] IN, input [2:0] SHIFT, output [3:0] OUT); + +assign OUT = IN >> SHIFT; +endmodule diff --git a/tests/hana/test_simulation_shifter_right_64_test.v b/tests/hana/test_simulation_shifter_right_64_test.v new file mode 100644 index 00000000..c26d5938 --- /dev/null +++ b/tests/hana/test_simulation_shifter_right_64_test.v @@ -0,0 +1,4 @@ +module test(input [63:0] IN, input [6:0] SHIFT, output [63:0] OUT); + +assign OUT = IN >> SHIFT; +endmodule diff --git a/tests/hana/test_simulation_shifter_right_8_test.v b/tests/hana/test_simulation_shifter_right_8_test.v new file mode 100644 index 00000000..a91c594e --- /dev/null +++ b/tests/hana/test_simulation_shifter_right_8_test.v @@ -0,0 +1,4 @@ +module test(input [7:0] IN, input [3:0] SHIFT, output [7:0] OUT); + +assign OUT = IN >> SHIFT; +endmodule diff --git a/tests/hana/test_simulation_sop_basic_10_test.v b/tests/hana/test_simulation_sop_basic_10_test.v new file mode 100644 index 00000000..bc676c70 --- /dev/null +++ b/tests/hana/test_simulation_sop_basic_10_test.v @@ -0,0 +1,8 @@ +module test(input [1:0] in, input select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + endcase +endmodule diff --git a/tests/hana/test_simulation_sop_basic_11_test.v b/tests/hana/test_simulation_sop_basic_11_test.v new file mode 100644 index 00000000..6a112c6a --- /dev/null +++ b/tests/hana/test_simulation_sop_basic_11_test.v @@ -0,0 +1,10 @@ +module test(input [3:0] in, input [1:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + endcase +endmodule diff --git a/tests/hana/test_simulation_sop_basic_12_test.v b/tests/hana/test_simulation_sop_basic_12_test.v new file mode 100644 index 00000000..f53a2c57 --- /dev/null +++ b/tests/hana/test_simulation_sop_basic_12_test.v @@ -0,0 +1,14 @@ +module test(input [7:0] in, input [2:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + 4: out = in[4]; + 5: out = in[5]; + 6: out = in[6]; + 7: out = in[7]; + endcase +endmodule diff --git a/tests/hana/test_simulation_sop_basic_18_test.v b/tests/hana/test_simulation_sop_basic_18_test.v new file mode 100644 index 00000000..03fc35b3 --- /dev/null +++ b/tests/hana/test_simulation_sop_basic_18_test.v @@ -0,0 +1,5 @@ +module test(input [7:0] in, output out); + +assign out = ~^in; + +endmodule diff --git a/tests/hana/test_simulation_sop_basic_3_test.v b/tests/hana/test_simulation_sop_basic_3_test.v new file mode 100644 index 00000000..81759c25 --- /dev/null +++ b/tests/hana/test_simulation_sop_basic_3_test.v @@ -0,0 +1,3 @@ +module test(input in, output out); +assign out = ~in; +endmodule diff --git a/tests/hana/test_simulation_sop_basic_7_test.v b/tests/hana/test_simulation_sop_basic_7_test.v new file mode 100644 index 00000000..e9bb7f61 --- /dev/null +++ b/tests/hana/test_simulation_sop_basic_7_test.v @@ -0,0 +1,3 @@ +module test(input in, output out); +assign out = in; +endmodule diff --git a/tests/hana/test_simulation_sop_basic_8_test.v b/tests/hana/test_simulation_sop_basic_8_test.v new file mode 100644 index 00000000..a51ead0b --- /dev/null +++ b/tests/hana/test_simulation_sop_basic_8_test.v @@ -0,0 +1,3 @@ +module test(output out); +assign out = 1'b0; +endmodule diff --git a/tests/hana/test_simulation_sop_basic_9_test.v b/tests/hana/test_simulation_sop_basic_9_test.v new file mode 100644 index 00000000..81759c25 --- /dev/null +++ b/tests/hana/test_simulation_sop_basic_9_test.v @@ -0,0 +1,3 @@ +module test(input in, output out); +assign out = ~in; +endmodule diff --git a/tests/hana/test_simulation_techmap_and_19_tech.v b/tests/hana/test_simulation_techmap_and_19_tech.v new file mode 100644 index 00000000..2491087c --- /dev/null +++ b/tests/hana/test_simulation_techmap_and_19_tech.v @@ -0,0 +1,7 @@ +module TECH_AND18(input [17:0] in, output out); +assign out = ∈ +endmodule + +module TECH_AND4(input [3:0] in, output out); +assign out = ∈ +endmodule diff --git a/tests/hana/test_simulation_techmap_and_5_tech.v b/tests/hana/test_simulation_techmap_and_5_tech.v new file mode 100644 index 00000000..6ec6a61c --- /dev/null +++ b/tests/hana/test_simulation_techmap_and_5_tech.v @@ -0,0 +1,3 @@ +module TECH_AND5(input [4:0] in, output out); +assign out = ∈ +endmodule diff --git a/tests/hana/test_simulation_techmap_buf_test.v b/tests/hana/test_simulation_techmap_buf_test.v new file mode 100644 index 00000000..e9bb7f61 --- /dev/null +++ b/tests/hana/test_simulation_techmap_buf_test.v @@ -0,0 +1,3 @@ +module test(input in, output out); +assign out = in; +endmodule diff --git a/tests/hana/test_simulation_techmap_inv_test.v b/tests/hana/test_simulation_techmap_inv_test.v new file mode 100644 index 00000000..81759c25 --- /dev/null +++ b/tests/hana/test_simulation_techmap_inv_test.v @@ -0,0 +1,3 @@ +module test(input in, output out); +assign out = ~in; +endmodule diff --git a/tests/hana/test_simulation_techmap_mux_0_test.v b/tests/hana/test_simulation_techmap_mux_0_test.v new file mode 100644 index 00000000..bc676c70 --- /dev/null +++ b/tests/hana/test_simulation_techmap_mux_0_test.v @@ -0,0 +1,8 @@ +module test(input [1:0] in, input select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + endcase +endmodule diff --git a/tests/hana/test_simulation_techmap_mux_128_test.v b/tests/hana/test_simulation_techmap_mux_128_test.v new file mode 100644 index 00000000..544c016a --- /dev/null +++ b/tests/hana/test_simulation_techmap_mux_128_test.v @@ -0,0 +1,134 @@ +module test(input [127:0] in, input [6:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + 4: out = in[4]; + 5: out = in[5]; + 6: out = in[6]; + 7: out = in[7]; + 8: out = in[8]; + 9: out = in[9]; + 10: out = in[10]; + 11: out = in[11]; + 12: out = in[12]; + 13: out = in[13]; + 14: out = in[14]; + 15: out = in[15]; + 16: out = in[16]; + 17: out = in[17]; + 18: out = in[18]; + 19: out = in[19]; + 20: out = in[20]; + 21: out = in[21]; + 22: out = in[22]; + 23: out = in[23]; + 24: out = in[24]; + 25: out = in[25]; + 26: out = in[26]; + 27: out = in[27]; + 28: out = in[28]; + 29: out = in[29]; + 30: out = in[30]; + 31: out = in[31]; + 32: out = in[32]; + 33: out = in[33]; + 34: out = in[34]; + 35: out = in[35]; + 36: out = in[36]; + 37: out = in[37]; + 38: out = in[38]; + 39: out = in[39]; + 40: out = in[40]; + 41: out = in[41]; + 42: out = in[42]; + 43: out = in[43]; + 44: out = in[44]; + 45: out = in[45]; + 46: out = in[46]; + 47: out = in[47]; + 48: out = in[48]; + 49: out = in[49]; + 50: out = in[50]; + 51: out = in[51]; + 52: out = in[52]; + 53: out = in[53]; + 54: out = in[54]; + 55: out = in[55]; + 56: out = in[56]; + 57: out = in[57]; + 58: out = in[58]; + 59: out = in[59]; + 60: out = in[60]; + 61: out = in[61]; + 62: out = in[62]; + 63: out = in[63]; + 64: out = in[64]; + 65: out = in[65]; + 66: out = in[66]; + 67: out = in[67]; + 68: out = in[68]; + 69: out = in[69]; + 70: out = in[70]; + 71: out = in[71]; + 72: out = in[72]; + 73: out = in[73]; + 74: out = in[74]; + 75: out = in[75]; + 76: out = in[76]; + 77: out = in[77]; + 78: out = in[78]; + 79: out = in[79]; + 80: out = in[80]; + 81: out = in[81]; + 82: out = in[82]; + 83: out = in[83]; + 84: out = in[84]; + 85: out = in[85]; + 86: out = in[86]; + 87: out = in[87]; + 88: out = in[88]; + 89: out = in[89]; + 90: out = in[90]; + 91: out = in[91]; + 92: out = in[92]; + 93: out = in[93]; + 94: out = in[94]; + 95: out = in[95]; + 96: out = in[96]; + 97: out = in[97]; + 98: out = in[98]; + 99: out = in[99]; + 100: out = in[100]; + 101: out = in[101]; + 102: out = in[102]; + 103: out = in[103]; + 104: out = in[104]; + 105: out = in[105]; + 106: out = in[106]; + 107: out = in[107]; + 108: out = in[108]; + 109: out = in[109]; + 110: out = in[110]; + 111: out = in[111]; + 112: out = in[112]; + 113: out = in[113]; + 114: out = in[114]; + 115: out = in[115]; + 116: out = in[116]; + 117: out = in[117]; + 118: out = in[118]; + 119: out = in[119]; + 120: out = in[120]; + 121: out = in[121]; + 122: out = in[122]; + 123: out = in[123]; + 124: out = in[124]; + 125: out = in[125]; + 126: out = in[126]; + 127: out = in[127]; + endcase +endmodule diff --git a/tests/hana/test_simulation_techmap_mux_8_test.v b/tests/hana/test_simulation_techmap_mux_8_test.v new file mode 100644 index 00000000..f53a2c57 --- /dev/null +++ b/tests/hana/test_simulation_techmap_mux_8_test.v @@ -0,0 +1,14 @@ +module test(input [7:0] in, input [2:0] select, output reg out); + +always @( in or select) + case (select) + 0: out = in[0]; + 1: out = in[1]; + 2: out = in[2]; + 3: out = in[3]; + 4: out = in[4]; + 5: out = in[5]; + 6: out = in[6]; + 7: out = in[7]; + endcase +endmodule diff --git a/tests/hana/test_simulation_techmap_nand_19_tech.v b/tests/hana/test_simulation_techmap_nand_19_tech.v new file mode 100644 index 00000000..6a119e1e --- /dev/null +++ b/tests/hana/test_simulation_techmap_nand_19_tech.v @@ -0,0 +1,11 @@ +module TECH_NAND18(input [17:0] in, output out); +assign out = ~(&in); +endmodule + +module TECH_NAND4(input [3:0] in, output out); +assign out = ~(&in); +endmodule + +module TECH_NAND2(input [1:0] in, output out); +assign out = ~(&in); +endmodule diff --git a/tests/hana/test_simulation_techmap_nand_2_tech.v b/tests/hana/test_simulation_techmap_nand_2_tech.v new file mode 100644 index 00000000..6a119e1e --- /dev/null +++ b/tests/hana/test_simulation_techmap_nand_2_tech.v @@ -0,0 +1,11 @@ +module TECH_NAND18(input [17:0] in, output out); +assign out = ~(&in); +endmodule + +module TECH_NAND4(input [3:0] in, output out); +assign out = ~(&in); +endmodule + +module TECH_NAND2(input [1:0] in, output out); +assign out = ~(&in); +endmodule diff --git a/tests/hana/test_simulation_techmap_nand_5_tech.v b/tests/hana/test_simulation_techmap_nand_5_tech.v new file mode 100644 index 00000000..6a119e1e --- /dev/null +++ b/tests/hana/test_simulation_techmap_nand_5_tech.v @@ -0,0 +1,11 @@ +module TECH_NAND18(input [17:0] in, output out); +assign out = ~(&in); +endmodule + +module TECH_NAND4(input [3:0] in, output out); +assign out = ~(&in); +endmodule + +module TECH_NAND2(input [1:0] in, output out); +assign out = ~(&in); +endmodule diff --git a/tests/hana/test_simulation_techmap_nor_19_tech.v b/tests/hana/test_simulation_techmap_nor_19_tech.v new file mode 100644 index 00000000..89fb2c7e --- /dev/null +++ b/tests/hana/test_simulation_techmap_nor_19_tech.v @@ -0,0 +1,11 @@ +module TECH_NOR18(input [17:0] in, output out); +assign out = ~(|in); +endmodule + +module TECH_NOR4(input [3:0] in, output out); +assign out = ~(|in); +endmodule + +module TECH_NOR2(input [1:0] in, output out); +assign out = ~(|in); +endmodule diff --git a/tests/hana/test_simulation_techmap_nor_2_tech.v b/tests/hana/test_simulation_techmap_nor_2_tech.v new file mode 100644 index 00000000..89fb2c7e --- /dev/null +++ b/tests/hana/test_simulation_techmap_nor_2_tech.v @@ -0,0 +1,11 @@ +module TECH_NOR18(input [17:0] in, output out); +assign out = ~(|in); +endmodule + +module TECH_NOR4(input [3:0] in, output out); +assign out = ~(|in); +endmodule + +module TECH_NOR2(input [1:0] in, output out); +assign out = ~(|in); +endmodule diff --git a/tests/hana/test_simulation_techmap_nor_5_tech.v b/tests/hana/test_simulation_techmap_nor_5_tech.v new file mode 100644 index 00000000..89fb2c7e --- /dev/null +++ b/tests/hana/test_simulation_techmap_nor_5_tech.v @@ -0,0 +1,11 @@ +module TECH_NOR18(input [17:0] in, output out); +assign out = ~(|in); +endmodule + +module TECH_NOR4(input [3:0] in, output out); +assign out = ~(|in); +endmodule + +module TECH_NOR2(input [1:0] in, output out); +assign out = ~(|in); +endmodule diff --git a/tests/hana/test_simulation_techmap_or_19_tech.v b/tests/hana/test_simulation_techmap_or_19_tech.v new file mode 100644 index 00000000..745d7b71 --- /dev/null +++ b/tests/hana/test_simulation_techmap_or_19_tech.v @@ -0,0 +1,7 @@ +module TECH_OR18(input [17:0] in, output out); +assign out = |in; +endmodule + +module TECH_OR4(input [3:0] in, output out); +assign out = |in; +endmodule diff --git a/tests/hana/test_simulation_techmap_or_5_tech.v b/tests/hana/test_simulation_techmap_or_5_tech.v new file mode 100644 index 00000000..05c38b67 --- /dev/null +++ b/tests/hana/test_simulation_techmap_or_5_tech.v @@ -0,0 +1,3 @@ +module TECH_OR5(input [4:0] in, output out); +assign out = |in; +endmodule diff --git a/tests/hana/test_simulation_techmap_xnor_2_tech.v b/tests/hana/test_simulation_techmap_xnor_2_tech.v new file mode 100644 index 00000000..4eb05683 --- /dev/null +++ b/tests/hana/test_simulation_techmap_xnor_2_tech.v @@ -0,0 +1,6 @@ +module TECH_XOR5(input [4:0] in, output out); +assign out = in[0] ^ in[1] ^ in[2] ^ in[3] ^ in[4]; +endmodule +module TECH_XOR2(input [1:0] in, output out); +assign out = in[0] ^ in[1]; +endmodule diff --git a/tests/hana/test_simulation_techmap_xnor_5_tech.v b/tests/hana/test_simulation_techmap_xnor_5_tech.v new file mode 100644 index 00000000..4eb05683 --- /dev/null +++ b/tests/hana/test_simulation_techmap_xnor_5_tech.v @@ -0,0 +1,6 @@ +module TECH_XOR5(input [4:0] in, output out); +assign out = in[0] ^ in[1] ^ in[2] ^ in[3] ^ in[4]; +endmodule +module TECH_XOR2(input [1:0] in, output out); +assign out = in[0] ^ in[1]; +endmodule diff --git a/tests/hana/test_simulation_techmap_xor_19_tech.v b/tests/hana/test_simulation_techmap_xor_19_tech.v new file mode 100644 index 00000000..2042a0ad --- /dev/null +++ b/tests/hana/test_simulation_techmap_xor_19_tech.v @@ -0,0 +1,3 @@ +module TECH_XOR2(input [1:0] in, output out); +assign out = in[0] ^ in[1]; +endmodule diff --git a/tests/hana/test_simulation_techmap_xor_2_tech.v b/tests/hana/test_simulation_techmap_xor_2_tech.v new file mode 100644 index 00000000..4eb05683 --- /dev/null +++ b/tests/hana/test_simulation_techmap_xor_2_tech.v @@ -0,0 +1,6 @@ +module TECH_XOR5(input [4:0] in, output out); +assign out = in[0] ^ in[1] ^ in[2] ^ in[3] ^ in[4]; +endmodule +module TECH_XOR2(input [1:0] in, output out); +assign out = in[0] ^ in[1]; +endmodule diff --git a/tests/hana/test_simulation_techmap_xor_5_tech.v b/tests/hana/test_simulation_techmap_xor_5_tech.v new file mode 100644 index 00000000..4eb05683 --- /dev/null +++ b/tests/hana/test_simulation_techmap_xor_5_tech.v @@ -0,0 +1,6 @@ +module TECH_XOR5(input [4:0] in, output out); +assign out = in[0] ^ in[1] ^ in[2] ^ in[3] ^ in[4]; +endmodule +module TECH_XOR2(input [1:0] in, output out); +assign out = in[0] ^ in[1]; +endmodule diff --git a/tests/hana/test_simulation_tribuf_2_test.v b/tests/hana/test_simulation_tribuf_2_test.v new file mode 100644 index 00000000..1e82aaf0 --- /dev/null +++ b/tests/hana/test_simulation_tribuf_2_test.v @@ -0,0 +1,3 @@ +module test(input [1:0] in, input enable, output [1:0] out); +assign out = enable ? in : 2'bzz; +endmodule diff --git a/tests/hana/test_simulation_xnor_1_test.v b/tests/hana/test_simulation_xnor_1_test.v new file mode 100644 index 00000000..adc6ae5c --- /dev/null +++ b/tests/hana/test_simulation_xnor_1_test.v @@ -0,0 +1,3 @@ +module test(input [1:0] in, output out); +assign out = ~(in[0] ^ in[1]); +endmodule diff --git a/tests/hana/test_simulation_xnor_2_test.v b/tests/hana/test_simulation_xnor_2_test.v new file mode 100644 index 00000000..701bcc77 --- /dev/null +++ b/tests/hana/test_simulation_xnor_2_test.v @@ -0,0 +1,3 @@ +module test(input [2:0] in, output out); +assign out = ~(in[0] ^ in[1] ^ in[2]); +endmodule diff --git a/tests/hana/test_simulation_xnor_3_test.v b/tests/hana/test_simulation_xnor_3_test.v new file mode 100644 index 00000000..a8c87cc6 --- /dev/null +++ b/tests/hana/test_simulation_xnor_3_test.v @@ -0,0 +1,3 @@ +module test(input [3:0] in, output out); +assign out = ~(in[0] ^ in[1] ^ in[2] ^ in[3]); +endmodule diff --git a/tests/hana/test_simulation_xnor_4_test.v b/tests/hana/test_simulation_xnor_4_test.v new file mode 100644 index 00000000..fa671ff9 --- /dev/null +++ b/tests/hana/test_simulation_xnor_4_test.v @@ -0,0 +1,3 @@ +module test(input [3:0] in, output out); +xnor myxnor(out, in[0], in[1], in[2], in[3]); +endmodule diff --git a/tests/hana/test_simulation_xor_1_test.v b/tests/hana/test_simulation_xor_1_test.v new file mode 100644 index 00000000..f6447f81 --- /dev/null +++ b/tests/hana/test_simulation_xor_1_test.v @@ -0,0 +1,3 @@ +module test(input [1:0] in, output out); +assign out = (in[0] ^ in[1]); +endmodule diff --git a/tests/hana/test_simulation_xor_2_test.v b/tests/hana/test_simulation_xor_2_test.v new file mode 100644 index 00000000..d94081df --- /dev/null +++ b/tests/hana/test_simulation_xor_2_test.v @@ -0,0 +1,3 @@ +module test(input [2:0] in, output out); +assign out = (in[0] ^ in[1] ^ in[2]); +endmodule diff --git a/tests/hana/test_simulation_xor_3_test.v b/tests/hana/test_simulation_xor_3_test.v new file mode 100644 index 00000000..cfa13187 --- /dev/null +++ b/tests/hana/test_simulation_xor_3_test.v @@ -0,0 +1,3 @@ +module test(input [3:0] in, output out); +assign out = (in[0] ^ in[1] ^ in[2] ^ in[3]); +endmodule diff --git a/tests/hana/test_simulation_xor_4_test.v b/tests/hana/test_simulation_xor_4_test.v new file mode 100644 index 00000000..be6cab63 --- /dev/null +++ b/tests/hana/test_simulation_xor_4_test.v @@ -0,0 +1,3 @@ +module test(input [3:0] in, output out); +xor myxor(out, in[0], in[1], in[2], in[3]); +endmodule diff --git a/tests/i2c_bench/i2c_master_bit_ctrl.v b/tests/i2c_bench/i2c_master_bit_ctrl.v new file mode 100644 index 00000000..6594fd60 --- /dev/null +++ b/tests/i2c_bench/i2c_master_bit_ctrl.v @@ -0,0 +1,576 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// 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.14 2009-01-20 10:25:29 rherveille Exp $ +// +// $Date: 2009-01-20 10:25:29 $ +// $Revision: 1.14 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: $ +// Revision 1.14 2009/01/20 10:25:29 rherveille +// Added clock synchronization logic +// Fixed slave_wait signal +// +// Revision 1.13 2009/01/19 20:29:26 rherveille +// Fixed synopsys miss spell (synopsis) +// Fixed cr[0] register width +// Fixed ! usage instead of ~ +// Fixed bit controller parameter width to 18bits +// +// Revision 1.12 2006/09/04 09:08:13 rherveille +// fixed short scl high pulse after clock stretch +// fixed slave model not returning correct '(n)ack' signal +// +// 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 ( + input clk, // system clock + input rst, // synchronous active high reset + input nReset, // asynchronous active low reset + input ena, // core enable signal + + input [15:0] clk_cnt, // clock prescale value + + input [ 3:0] cmd, // command (from byte controller) + output reg cmd_ack, // command complete acknowledge + output reg busy, // i2c bus busy + output reg al, // i2c bus arbitration lost + + input din, + output reg dout, + + input scl_i, // i2c clock line input + output scl_o, // i2c clock line output + output reg scl_oen, // i2c clock line output enable (active low) + input sda_i, // i2c data line input + output sda_o, // i2c data line output + output reg sda_oen // i2c data line output enable (active low) +); + + + // + // variable declarations + // + + reg [ 1:0] cSCL, cSDA; // capture SCL and SDA + reg [ 2:0] fSCL, fSDA; // SCL and SDA filter inputs + reg sSCL, sSDA; // filtered and synchronized SCL and SDA inputs + reg dSCL, dSDA; // delayed versions of sSCL and sSDA + reg dscl_oen; // delayed scl_oen + reg sda_chk; // check SDA output (Multi-master arbitration) + reg clk_en; // clock generation signals + reg slave_wait; // slave inserts wait states + reg [15:0] cnt; // clock divider counter (synthesis) + reg [13:0] filter_cnt; // clock divider for filter + + + // state machine variable + reg [17: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 <= scl_oen; + + // slave_wait is asserted when master wants to drive SCL high, but the slave pulls it low + // slave_wait remains asserted until the slave releases SCL + always @(posedge clk or negedge nReset) + if (!nReset) slave_wait <= 1'b0; + else slave_wait <= (scl_oen & ~dscl_oen & ~sSCL) | (slave_wait & ~sSCL); + + // master drives SCL high, but another master pulls it low + // master start counting down its low cycle now (clock synchronization) + wire scl_sync = dSCL & ~sSCL & scl_oen; + + + // generate clk enable signal + always @(posedge clk or negedge nReset) + if (~nReset) + begin + cnt <= 16'h0; + clk_en <= 1'b1; + end + else if (rst || ~|cnt || !ena || scl_sync) + begin + cnt <= clk_cnt; + clk_en <= 1'b1; + end + else if (slave_wait) + begin + cnt <= cnt; + clk_en <= 1'b0; + end + else + begin + cnt <= cnt - 16'h1; + clk_en <= 1'b0; + end + + + // generate bus status controller + + // capture SDA and SCL + // reduce metastability risk + always @(posedge clk or negedge nReset) + if (!nReset) + begin + cSCL <= 2'b00; + cSDA <= 2'b00; + end + else if (rst) + begin + cSCL <= 2'b00; + cSDA <= 2'b00; + end + else + begin + cSCL <= {cSCL[0],scl_i}; + cSDA <= {cSDA[0],sda_i}; + end + + + // filter SCL and SDA signals; (attempt to) remove glitches + always @(posedge clk or negedge nReset) + if (!nReset ) filter_cnt <= 14'h0; + else if (rst || !ena ) filter_cnt <= 14'h0; + else if (~|filter_cnt) filter_cnt <= clk_cnt[15:2]; //16x I2C bus frequency + else filter_cnt <= filter_cnt -1; + + + always @(posedge clk or negedge nReset) + if (!nReset) + begin + fSCL <= 3'b111; + fSDA <= 3'b111; + end + else if (rst) + begin + fSCL <= 3'b111; + fSDA <= 3'b111; + end + else if (~|filter_cnt) + begin + fSCL <= {fSCL[1:0],cSCL[1]}; + fSDA <= {fSDA[1:0],cSDA[1]}; + end + + + // generate filtered SCL and SDA signals + always @(posedge clk or negedge nReset) + if (~nReset) + begin + sSCL <= 1'b1; + sSDA <= 1'b1; + + dSCL <= 1'b1; + dSDA <= 1'b1; + end + else if (rst) + begin + sSCL <= 1'b1; + sSDA <= 1'b1; + + dSCL <= 1'b1; + dSDA <= 1'b1; + end + else + begin + sSCL <= &fSCL[2:1] | &fSCL[1:0] | (fSCL[2] & fSCL[0]); + sSDA <= &fSDA[2:1] | &fSDA[1:0] | (fSDA[2] & fSDA[0]); + + dSCL <= sSCL; + dSDA <= 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 + reg sta_condition; + reg sto_condition; + always @(posedge clk or negedge nReset) + if (~nReset) + begin + sta_condition <= 1'b0; + sto_condition <= 1'b0; + end + else if (rst) + begin + sta_condition <= 1'b0; + sto_condition <= 1'b0; + end + else + begin + sta_condition <= ~sSDA & dSDA & sSCL; + sto_condition <= sSDA & ~dSDA & sSCL; + end + + + // generate i2c bus busy signal + always @(posedge clk or negedge nReset) + if (!nReset) busy <= 1'b0; + else if (rst ) busy <= 1'b0; + else busy <= (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'b0; + else if (rst) + cmd_stop <= 1'b0; + else if (clk_en) + cmd_stop <= cmd == `I2C_CMD_STOP; + + always @(posedge clk or negedge nReset) + if (~nReset) + al <= 1'b0; + else if (rst) + al <= 1'b0; + else + al <= (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 <= sSDA; + + + // generate statemachine + + // nxt_state decoder + parameter [17:0] idle = 18'b0_0000_0000_0000_0000; + parameter [17:0] start_a = 18'b0_0000_0000_0000_0001; + parameter [17:0] start_b = 18'b0_0000_0000_0000_0010; + parameter [17:0] start_c = 18'b0_0000_0000_0000_0100; + parameter [17:0] start_d = 18'b0_0000_0000_0000_1000; + parameter [17:0] start_e = 18'b0_0000_0000_0001_0000; + parameter [17:0] stop_a = 18'b0_0000_0000_0010_0000; + parameter [17:0] stop_b = 18'b0_0000_0000_0100_0000; + parameter [17:0] stop_c = 18'b0_0000_0000_1000_0000; + parameter [17:0] stop_d = 18'b0_0000_0001_0000_0000; + parameter [17:0] rd_a = 18'b0_0000_0010_0000_0000; + parameter [17:0] rd_b = 18'b0_0000_0100_0000_0000; + parameter [17:0] rd_c = 18'b0_0000_1000_0000_0000; + parameter [17:0] rd_d = 18'b0_0001_0000_0000_0000; + parameter [17:0] wr_a = 18'b0_0010_0000_0000_0000; + parameter [17:0] wr_b = 18'b0_0100_0000_0000_0000; + parameter [17:0] wr_c = 18'b0_1000_0000_0000_0000; + parameter [17:0] wr_d = 18'b1_0000_0000_0000_0000; + + always @(posedge clk or negedge nReset) + if (!nReset) + begin + c_state <= idle; + cmd_ack <= 1'b0; + scl_oen <= 1'b1; + sda_oen <= 1'b1; + sda_chk <= 1'b0; + end + else if (rst | al) + begin + c_state <= idle; + cmd_ack <= 1'b0; + scl_oen <= 1'b1; + sda_oen <= 1'b1; + sda_chk <= 1'b0; + end + else + begin + cmd_ack <= 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 <= start_a; + `I2C_CMD_STOP: c_state <= stop_a; + `I2C_CMD_WRITE: c_state <= wr_a; + `I2C_CMD_READ: c_state <= rd_a; + default: c_state <= idle; + endcase + + scl_oen <= scl_oen; // keep SCL in same state + sda_oen <= sda_oen; // keep SDA in same state + sda_chk <= 1'b0; // don't check SDA output + end + + // start + start_a: + begin + c_state <= start_b; + scl_oen <= scl_oen; // keep SCL in same state + sda_oen <= 1'b1; // set SDA high + sda_chk <= 1'b0; // don't check SDA output + end + + start_b: + begin + c_state <= start_c; + scl_oen <= 1'b1; // set SCL high + sda_oen <= 1'b1; // keep SDA high + sda_chk <= 1'b0; // don't check SDA output + end + + start_c: + begin + c_state <= start_d; + scl_oen <= 1'b1; // keep SCL high + sda_oen <= 1'b0; // set SDA low + sda_chk <= 1'b0; // don't check SDA output + end + + start_d: + begin + c_state <= start_e; + scl_oen <= 1'b1; // keep SCL high + sda_oen <= 1'b0; // keep SDA low + sda_chk <= 1'b0; // don't check SDA output + end + + start_e: + begin + c_state <= idle; + cmd_ack <= 1'b1; + scl_oen <= 1'b0; // set SCL low + sda_oen <= 1'b0; // keep SDA low + sda_chk <= 1'b0; // don't check SDA output + end + + // stop + stop_a: + begin + c_state <= stop_b; + scl_oen <= 1'b0; // keep SCL low + sda_oen <= 1'b0; // set SDA low + sda_chk <= 1'b0; // don't check SDA output + end + + stop_b: + begin + c_state <= stop_c; + scl_oen <= 1'b1; // set SCL high + sda_oen <= 1'b0; // keep SDA low + sda_chk <= 1'b0; // don't check SDA output + end + + stop_c: + begin + c_state <= stop_d; + scl_oen <= 1'b1; // keep SCL high + sda_oen <= 1'b0; // keep SDA low + sda_chk <= 1'b0; // don't check SDA output + end + + stop_d: + begin + c_state <= idle; + cmd_ack <= 1'b1; + scl_oen <= 1'b1; // keep SCL high + sda_oen <= 1'b1; // set SDA high + sda_chk <= 1'b0; // don't check SDA output + end + + // read + rd_a: + begin + c_state <= rd_b; + scl_oen <= 1'b0; // keep SCL low + sda_oen <= 1'b1; // tri-state SDA + sda_chk <= 1'b0; // don't check SDA output + end + + rd_b: + begin + c_state <= rd_c; + scl_oen <= 1'b1; // set SCL high + sda_oen <= 1'b1; // keep SDA tri-stated + sda_chk <= 1'b0; // don't check SDA output + end + + rd_c: + begin + c_state <= rd_d; + scl_oen <= 1'b1; // keep SCL high + sda_oen <= 1'b1; // keep SDA tri-stated + sda_chk <= 1'b0; // don't check SDA output + end + + rd_d: + begin + c_state <= idle; + cmd_ack <= 1'b1; + scl_oen <= 1'b0; // set SCL low + sda_oen <= 1'b1; // keep SDA tri-stated + sda_chk <= 1'b0; // don't check SDA output + end + + // write + wr_a: + begin + c_state <= wr_b; + scl_oen <= 1'b0; // keep SCL low + sda_oen <= din; // set SDA + sda_chk <= 1'b0; // don't check SDA output (SCL low) + end + + wr_b: + begin + c_state <= wr_c; + scl_oen <= 1'b1; // set SCL high + sda_oen <= din; // keep SDA + sda_chk <= 1'b0; // don't check SDA output yet + // allow some time for SDA and SCL to settle + end + + wr_c: + begin + c_state <= wr_d; + scl_oen <= 1'b1; // keep SCL high + sda_oen <= din; + sda_chk <= 1'b1; // check SDA output + end + + wr_d: + begin + c_state <= idle; + cmd_ack <= 1'b1; + scl_oen <= 1'b0; // set SCL low + sda_oen <= din; + sda_chk <= 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/i2c_bench/i2c_master_byte_ctrl.v b/tests/i2c_bench/i2c_master_byte_ctrl.v new file mode 100644 index 00000000..513953a8 --- /dev/null +++ b/tests/i2c_bench/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.8 2009-01-19 20:29:26 rherveille Exp $ +// +// $Date: 2009-01-19 20:29:26 $ +// $Revision: 1.8 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// 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 <= 8'h0; + else if (rst) + sr <= 8'h0; + else if (ld) + sr <= din; + else if (shift) + sr <= {sr[6:0], core_rxd}; + + // generate counter + always @(posedge clk or negedge nReset) + if (!nReset) + dcnt <= 3'h0; + else if (rst) + dcnt <= 3'h0; + else if (ld) + dcnt <= 3'h7; + else if (shift) + dcnt <= dcnt - 3'h1; + + assign cnt_done = ~(|dcnt); + + // + // state machine + // + reg [4:0] c_state; // synopsys enum_state + + always @(posedge clk or negedge nReset) + if (!nReset) + begin + core_cmd <= `I2C_CMD_NOP; + core_txd <= 1'b0; + shift <= 1'b0; + ld <= 1'b0; + cmd_ack <= 1'b0; + c_state <= ST_IDLE; + ack_out <= 1'b0; + end + else if (rst | i2c_al) + begin + core_cmd <= `I2C_CMD_NOP; + core_txd <= 1'b0; + shift <= 1'b0; + ld <= 1'b0; + cmd_ack <= 1'b0; + c_state <= ST_IDLE; + ack_out <= 1'b0; + end + else + begin + // initially reset all signals + core_txd <= sr[7]; + shift <= 1'b0; + ld <= 1'b0; + cmd_ack <= 1'b0; + + case (c_state) // synopsys full_case parallel_case + ST_IDLE: + if (go) + begin + if (start) + begin + c_state <= ST_START; + core_cmd <= `I2C_CMD_START; + end + else if (read) + begin + c_state <= ST_READ; + core_cmd <= `I2C_CMD_READ; + end + else if (write) + begin + c_state <= ST_WRITE; + core_cmd <= `I2C_CMD_WRITE; + end + else // stop + begin + c_state <= ST_STOP; + core_cmd <= `I2C_CMD_STOP; + end + + ld <= 1'b1; + end + + ST_START: + if (core_ack) + begin + if (read) + begin + c_state <= ST_READ; + core_cmd <= `I2C_CMD_READ; + end + else + begin + c_state <= ST_WRITE; + core_cmd <= `I2C_CMD_WRITE; + end + + ld <= 1'b1; + end + + ST_WRITE: + if (core_ack) + if (cnt_done) + begin + c_state <= ST_ACK; + core_cmd <= `I2C_CMD_READ; + end + else + begin + c_state <= ST_WRITE; // stay in same state + core_cmd <= `I2C_CMD_WRITE; // write next bit + shift <= 1'b1; + end + + ST_READ: + if (core_ack) + begin + if (cnt_done) + begin + c_state <= ST_ACK; + core_cmd <= `I2C_CMD_WRITE; + end + else + begin + c_state <= ST_READ; // stay in same state + core_cmd <= `I2C_CMD_READ; // read next bit + end + + shift <= 1'b1; + core_txd <= ack_in; + end + + ST_ACK: + if (core_ack) + begin + if (stop) + begin + c_state <= ST_STOP; + core_cmd <= `I2C_CMD_STOP; + end + else + begin + c_state <= ST_IDLE; + core_cmd <= `I2C_CMD_NOP; + + // generate command acknowledge signal + cmd_ack <= 1'b1; + end + + // assign ack_out output to bit_controller_rxd (contains last received bit) + ack_out <= core_rxd; + + core_txd <= 1'b1; + end + else + core_txd <= ack_in; + + ST_STOP: + if (core_ack) + begin + c_state <= ST_IDLE; + core_cmd <= `I2C_CMD_NOP; + + // generate command acknowledge signal + cmd_ack <= 1'b1; + end + + endcase + end +endmodule diff --git a/tests/i2c_bench/i2c_master_defines.v b/tests/i2c_bench/i2c_master_defines.v new file mode 100644 index 00000000..e81c546a --- /dev/null +++ b/tests/i2c_bench/i2c_master_defines.v @@ -0,0 +1,59 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// 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: not supported by cvs2svn $ + + +// 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/i2c_bench/i2c_master_top.v b/tests/i2c_bench/i2c_master_top.v new file mode 100644 index 00000000..5e9cde7e --- /dev/null +++ b/tests/i2c_bench/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.12 2009-01-19 20:29:26 rherveille Exp $ +// +// $Date: 2009-01-19 20:29:26 $ +// $Revision: 1.12 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// 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_we_i & wb_ack_o; + + // generate acknowledge output signal + always @(posedge wb_clk_i) + wb_ack_o <= 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) // synopsys parallel_case + 3'b000: wb_dat_o <= prer[ 7:0]; + 3'b001: wb_dat_o <= prer[15:8]; + 3'b010: wb_dat_o <= ctr; + 3'b011: wb_dat_o <= rxr; // write is transmit register (txr) + 3'b100: wb_dat_o <= sr; // write is command register (cr) + 3'b101: wb_dat_o <= txr; + 3'b110: wb_dat_o <= cr; + 3'b111: wb_dat_o <= 0; // reserved + default: wb_dat_o <= 16'bx; + endcase + end + + // generate registers + always @(posedge wb_clk_i or negedge rst_i) + if (!rst_i) + begin + prer <= 16'hffff; + ctr <= 8'h0; + txr <= 8'h0; + end + else if (wb_rst_i) + begin + prer <= 16'hffff; + ctr <= 8'h0; + txr <= 8'h0; + end + else + if (wb_wacc) + case (wb_adr_i) // synopsys parallel_case + 3'b000 : prer [ 7:0] <= wb_dat_i; + 3'b001 : prer [15:8] <= wb_dat_i; + 3'b010 : ctr <= wb_dat_i; + 3'b011 : txr <= wb_dat_i; + default: ; + endcase + + // generate command register (special case) + always @(posedge wb_clk_i or negedge rst_i) + if (!rst_i) + cr <= 8'h0; + else if (wb_rst_i) + cr <= 8'h0; + else if (wb_wacc) + begin + if (core_en & (wb_adr_i == 3'b100) ) + cr <= wb_dat_i; + end + else + begin + if (done | i2c_al) + cr[7:4] <= 4'h0; // clear command bits when done + // or when aribitration lost + cr[2:1] <= 2'b0; // reserved bits + cr[0] <= 1'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'b0; + rxack <= 1'b0; + tip <= 1'b0; + irq_flag <= 1'b0; + end + else if (wb_rst_i) + begin + al <= 1'b0; + rxack <= 1'b0; + tip <= 1'b0; + irq_flag <= 1'b0; + end + else + begin + al <= i2c_al | (al & ~sta); + rxack <= irxack; + tip <= (rd | wr); + irq_flag <= (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'b0; + else if (wb_rst_i) + wb_inta_o <= 1'b0; + else + wb_inta_o <= 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/i2c_bench/i2c_slave_model.v b/tests/i2c_bench/i2c_slave_model.v new file mode 100644 index 00000000..02b7572c --- /dev/null +++ b/tests/i2c_bench/i2c_slave_model.v @@ -0,0 +1,361 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant synthesizable I2C Slave model //// +//// //// +//// //// +//// Authors: Richard Herveille (richard@asics.ws) www.asics.ws //// +//// John Sheahan (jrsheahan@optushome.com.au) //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/i2c/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001,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: i2c_slave_model.v,v 1.7 2006-09-04 09:08:51 rherveille Exp $ +// +// $Date: 2006-09-04 09:08:51 $ +// $Revision: 1.7 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// Revision 1.6 2005/02/28 11:33:48 rherveille +// Fixed Tsu:sta timing check. +// Added Thd:sta timing check. +// +// Revision 1.5 2003/12/05 11:05:19 rherveille +// Fixed slave address MSB='1' bug +// +// Revision 1.4 2003/09/11 08:25:37 rherveille +// Fixed a bug in the timing section. Changed 'tst_scl' into 'tst_sto'. +// +// Revision 1.3 2002/10/30 18:11:06 rherveille +// Added timing tests to i2c_model. +// Updated testbench. +// +// Revision 1.2 2002/03/17 10:26:38 rherveille +// Fixed some race conditions in the i2c-slave model. +// Added debug information. +// Added headers. +// + +`include "timescale.v" + +module i2c_slave_model (scl, sda); + + // + // parameters + // + parameter I2C_ADR = 7'b001_0000; + + // + // input && outpus + // + input scl; + inout sda; + + // + // Variable declaration + // + wire debug = 1'b1; + + reg [7:0] mem [3:0]; // initiate memory + reg [7:0] mem_adr; // memory address + reg [7:0] mem_do; // memory data output + + reg sta, d_sta; + reg sto, d_sto; + + reg [7:0] sr; // 8bit shift register + reg rw; // read/write direction + + wire my_adr; // my address called ?? + wire i2c_reset; // i2c-statemachine reset + reg [2:0] bit_cnt; // 3bit downcounter + wire acc_done; // 8bits transfered + reg ld; // load downcounter + + reg sda_o; // sda-drive level + wire sda_dly; // delayed version of sda + + // statemachine declaration + parameter idle = 3'b000; + parameter slave_ack = 3'b001; + parameter get_mem_adr = 3'b010; + parameter gma_ack = 3'b011; + parameter data = 3'b100; + parameter data_ack = 3'b101; + + reg [2:0] state; // synopsys enum_state + + // + // module body + // + + initial + begin + sda_o = 1'b1; + state = idle; + mem[0] = 0; + mem[1] = 0; + mem[2] = 0; + mem[3] = 0; + end + + // generate shift register + always @(posedge scl) + sr <= #1 {sr[6:0],sda}; + + //detect my_address + assign my_adr = (sr[7:1] == I2C_ADR); + // FIXME: This should not be a generic assign, but rather + // qualified on address transfer phase and probably reset by stop + + //generate bit-counter + always @(posedge scl) + if(ld) + bit_cnt <= #1 3'b111; + else + bit_cnt <= #1 bit_cnt - 3'h1; + + //generate access done signal + assign acc_done = !(|bit_cnt); + + // generate delayed version of sda + // this model assumes a hold time for sda after the falling edge of scl. + // According to the Phillips i2c spec, there s/b a 0 ns hold time for sda + // with regards to scl. If the data changes coincident with the clock, the + // acknowledge is missed + // Fix by Michael Sosnoski + assign #1 sda_dly = sda; + + + //detect start condition + always @(negedge sda) + if(scl) + begin + sta <= #1 1'b1; + d_sta <= #1 1'b0; + sto <= #1 1'b0; + + if(debug) + $display("DEBUG i2c_slave; start condition detected at %t", $time); + end + else + sta <= #1 1'b0; + + always @(posedge scl) + d_sta <= #1 sta; + + // detect stop condition + always @(posedge sda) + if(scl) + begin + sta <= #1 1'b0; + sto <= #1 1'b1; + + if(debug) + $display("DEBUG i2c_slave; stop condition detected at %t", $time); + end + else + sto <= #1 1'b0; + + //generate i2c_reset signal + assign i2c_reset = sta || sto; + + // generate statemachine + always @(negedge scl or posedge sto) + if (sto || (sta && !d_sta) ) + begin + state <= #1 idle; // reset statemachine + + sda_o <= #1 1'b1; + ld <= #1 1'b1; + end + else + begin + // initial settings + sda_o <= #1 1'b1; + ld <= #1 1'b0; + + case(state) // synopsys full_case parallel_case + idle: // idle state + if (acc_done && my_adr) + begin + state <= #1 slave_ack; + rw <= #1 sr[0]; + sda_o <= #1 1'b0; // generate i2c_ack + + #2; + if(debug && rw) + $display("DEBUG i2c_slave; command byte received (read) at %t", $time); + if(debug && !rw) + $display("DEBUG i2c_slave; command byte received (write) at %t", $time); + + if(rw) + begin + mem_do <= #1 mem[mem_adr % 4]; + + if(debug) + begin + #2 $display("DEBUG i2c_slave; data block read %x from address %x (1)", mem_do, mem_adr); + #2 $display("DEBUG i2c_slave; memcheck [0]=%x, [1]=%x, [2]=%x", mem[4'h0], mem[4'h1], mem[4'h2]); + end + end + end + + slave_ack: + begin + if(rw) + begin + state <= #1 data; + sda_o <= #1 mem_do[7]; + end + else + state <= #1 get_mem_adr; + + ld <= #1 1'b1; + end + + get_mem_adr: // wait for memory address + if(acc_done) + begin + state <= #1 gma_ack; + mem_adr <= #1 sr; // store memory address + sda_o <= #1 !(sr <= 15); // generate i2c_ack, for valid address + + if(debug) + #1 $display("DEBUG i2c_slave; address received. adr=%x, ack=%b", sr, sda_o); + end + + gma_ack: + begin + state <= #1 data; + ld <= #1 1'b1; + end + + data: // receive or drive data + begin + if(rw) + sda_o <= #1 mem_do[7]; + + if(acc_done) + begin + state <= #1 data_ack; + mem_adr <= #2 mem_adr + 8'h1; + sda_o <= #1 (rw && (mem_adr <= 15) ); // send ack on write, receive ack on read + + if(rw) + begin + #3 mem_do <= mem[mem_adr % 4]; + + if(debug) + #5 $display("DEBUG i2c_slave; data block read %x from address %x (2)", mem_do, mem_adr); + end + + if(!rw) + begin + mem[ mem_adr[3:0] ] <= #1 sr; // store data in memory + + if(debug) + #2 $display("DEBUG i2c_slave; data block write %x to address %x", sr, mem_adr); + end + end + end + + data_ack: + begin + ld <= #1 1'b1; + + if(rw) + if(sr[0]) // read operation && master send NACK + begin + state <= #1 idle; + sda_o <= #1 1'b1; + end + else + begin + state <= #1 data; + sda_o <= #1 mem_do[7]; + end + else + begin + state <= #1 data; + sda_o <= #1 1'b1; + end + end + + endcase + end + + // read data from memory + always @(posedge scl) + if(!acc_done && rw) + mem_do <= #1 {mem_do[6:0], 1'b1}; // insert 1'b1 for host ack generation + + // generate tri-states + assign sda = sda_o ? 1'bz : 1'b0; + + + // + // Timing checks + // + + wire tst_sto = sto; + wire tst_sta = sta; + + specify + specparam normal_scl_low = 4700, + normal_scl_high = 4000, + normal_tsu_sta = 4700, + normal_thd_sta = 4000, + normal_tsu_sto = 4000, + normal_tbuf = 4700, + + fast_scl_low = 1300, + fast_scl_high = 600, + fast_tsu_sta = 1300, + fast_thd_sta = 600, + fast_tsu_sto = 600, + fast_tbuf = 1300; + + $width(negedge scl, normal_scl_low); // scl low time + $width(posedge scl, normal_scl_high); // scl high time + + $setup(posedge scl, negedge sda &&& scl, normal_tsu_sta); // setup start + $setup(negedge sda &&& scl, negedge scl, normal_thd_sta); // hold start + $setup(posedge scl, posedge sda &&& scl, normal_tsu_sto); // setup stop + + $setup(posedge tst_sta, posedge tst_sto, normal_tbuf); // stop to start time + endspecify + +endmodule + + diff --git a/tests/i2c_bench/run-test.sh b/tests/i2c_bench/run-test.sh new file mode 100755 index 00000000..5fdbb059 --- /dev/null +++ b/tests/i2c_bench/run-test.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +set -e +make -C ../.. +../../yosys -l i2c_master_syn.log -o i2c_master_syn.v \ + -p hierarchy -p proc -p memory -p techmap -p opt -p abc -p opt \ + i2c_master_top.v i2c_master_bit_ctrl.v i2c_master_byte_ctrl.v +. /opt/Xilinx/13.4/ISE_DS/settings64.sh + +vlogcomp --work ref i2c_master_bit_ctrl.v +vlogcomp --work ref i2c_master_byte_ctrl.v +vlogcomp --work ref i2c_master_top.v +vlogcomp --work ref i2c_slave_model.v +vlogcomp --work ref spi_slave_model.v +vlogcomp --work ref tst_bench_top.v +vlogcomp --work ref wb_master_model.v +fuse --work ref -o testbench_ref --top tst_bench_top + +cat > testbench_ref.tcl << EOT +vcd dumpfile testbench_ref.vcd +vcd dumpvars -m tst_bench_top -l 0 +vcd dumpon +run 2 ms +exit +EOT + +./testbench_ref -tclbatch testbench_ref.tcl + +vlogcomp --work syn i2c_master_syn.v +vlogcomp --work syn ../../techlibs/simlib.v +vlogcomp --work syn ../../techlibs/stdcells_sim.v +vlogcomp --work syn i2c_slave_model.v +vlogcomp --work syn spi_slave_model.v +vlogcomp --work syn tst_bench_top.v +vlogcomp --work syn wb_master_model.v +fuse --work syn -o testbench_syn --top tst_bench_top + +cat > testbench_syn.tcl << EOT +vcd dumpfile testbench_syn.vcd +vcd dumpvars -m tst_bench_top -l 0 +vcd dumpon +run 2 ms +exit +EOT + +./testbench_syn -tclbatch testbench_syn.tcl + +perl ../tools/vcdcd.pl testbench_ref.vcd testbench_syn.vcd | tee testbench_diff.txt +echo READY. + diff --git a/tests/i2c_bench/spi_slave_model.v b/tests/i2c_bench/spi_slave_model.v new file mode 100644 index 00000000..d49347b0 --- /dev/null +++ b/tests/i2c_bench/spi_slave_model.v @@ -0,0 +1,125 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// SPI Slave Model //// +//// //// +//// //// +//// Authors: Richard Herveille (richard@asics.ws) www.asics.ws //// +//// //// +//// http://www.opencores.org/projects/simple_spi/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2004 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: spi_slave_model.v,v 1.1 2004-02-28 15:32:54 rherveille Exp $ +// +// $Date: 2004-02-28 15:32:54 $ +// $Revision: 1.1 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// +// + + +// Requires: Verilog2001 + +`include "timescale.v" + +module spi_slave_model ( + input wire csn, + input wire sc, + input wire di, + output wire do +); + + // + // Variable declaration + // + wire debug = 1'b1; + + wire cpol = 1'b0; + wire cpha = 1'b0; + + reg [7:0] mem [7:0]; // initiate memory + reg [2:0] mem_adr; // memory address + reg [7:0] mem_do; // memory data output + + reg [7:0] sri, sro; // 8bit shift register + + reg [2:0] bit_cnt; + reg ld; + + wire clk; + + // + // module body + // + + assign clk = cpol ^ cpha ^ sc; + + // generate shift registers + always @(posedge clk) + sri <= #1 {sri[6:0],di}; + + always @(posedge clk) + if (&bit_cnt) + sro <= #1 mem[mem_adr]; + else + sro <= #1 {sro[6:0],1'bx}; + + assign do = sro[7]; + + //generate bit-counter + always @(posedge clk, posedge csn) + if(csn) + bit_cnt <= #1 3'b111; + else + bit_cnt <= #1 bit_cnt - 3'h1; + + //generate access done signal + always @(posedge clk) + ld <= #1 ~(|bit_cnt); + + always @(negedge clk) + if (ld) begin + mem[mem_adr] <= #1 sri; + mem_adr <= #1 mem_adr + 1'b1; + end + + initial + begin + bit_cnt=3'b111; + mem_adr = 0; + sro = mem[mem_adr]; + end +endmodule + + diff --git a/tests/i2c_bench/timescale.v b/tests/i2c_bench/timescale.v new file mode 100644 index 00000000..60d4ecbd --- /dev/null +++ b/tests/i2c_bench/timescale.v @@ -0,0 +1,2 @@ +`timescale 1ns / 10ps + diff --git a/tests/i2c_bench/tst_bench_top.v b/tests/i2c_bench/tst_bench_top.v new file mode 100644 index 00000000..9458de05 --- /dev/null +++ b/tests/i2c_bench/tst_bench_top.v @@ -0,0 +1,468 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant I2C Master controller Testbench //// +//// //// +//// //// +//// 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: tst_bench_top.v,v 1.8 2006-09-04 09:08:51 rherveille Exp $ +// +// $Date: 2006-09-04 09:08:51 $ +// $Revision: 1.8 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// Revision 1.7 2005/02/27 09:24:18 rherveille +// Fixed scl, sda delay. +// +// Revision 1.6 2004/02/28 15:40:42 rherveille +// *** empty log message *** +// +// Revision 1.4 2003/12/05 11:04:38 rherveille +// Added slave address configurability +// +// Revision 1.3 2002/10/30 18:11:06 rherveille +// Added timing tests to i2c_model. +// Updated testbench. +// +// Revision 1.2 2002/03/17 10:26:38 rherveille +// Fixed some race conditions in the i2c-slave model. +// Added debug information. +// Added headers. +// + +`include "timescale.v" + +module tst_bench_top(); + + // + // wires && regs + // + reg clk; + reg rstn; + + wire [31:0] adr; + wire [ 7:0] dat_i, dat_o, dat0_i, dat1_i; + wire we; + wire stb; + wire cyc; + wire ack0, ack1; + wire inta; + + reg [7:0] q, qq; + + wire scl, scl0_o, scl0_oen, scl1_o, scl1_oen; + wire sda, sda0_o, sda0_oen, sda1_o, sda1_oen; + + parameter PRER_LO = 3'b000; + parameter PRER_HI = 3'b001; + parameter CTR = 3'b010; + parameter RXR = 3'b011; + parameter TXR = 3'b011; + parameter CR = 3'b100; + parameter SR = 3'b100; + + parameter TXR_R = 3'b101; // undocumented / reserved output + parameter CR_R = 3'b110; // undocumented / reserved output + + parameter RD = 1'b1; + parameter WR = 1'b0; + parameter SADR = 7'b0010_000; + + // + // Module body + // + + // generate clock + always #5 clk = ~clk; + + // hookup wishbone master model + wb_master_model #(8, 32) u0 ( + .clk(clk), + .rst(rstn), + .adr(adr), + .din(dat_i), + .dout(dat_o), + .cyc(cyc), + .stb(stb), + .we(we), + .sel(), + .ack(ack0 || ack1), + .err(1'b0), + .rty(1'b0) + ); + + wire stb0 = stb & ~adr[3]; + wire stb1 = stb & adr[3]; + + assign dat_i = ({{8'd8}{stb0}} & dat0_i) | ({{8'd8}{stb1}} & dat1_i); + + // hookup wishbone_i2c_master core + i2c_master_top i2c_top ( + + // wishbone interface + .wb_clk_i(clk), + .wb_rst_i(1'b0), + .arst_i(rstn), + .wb_adr_i(adr[2:0]), + .wb_dat_i(dat_o), + .wb_dat_o(dat0_i), + .wb_we_i(we), + .wb_stb_i(stb0), + .wb_cyc_i(cyc), + .wb_ack_o(ack0), + .wb_inta_o(inta), + + // i2c signals + .scl_pad_i(scl), + .scl_pad_o(scl0_o), + .scl_padoen_o(scl0_oen), + .sda_pad_i(sda), + .sda_pad_o(sda0_o), + .sda_padoen_o(sda0_oen) + ), + i2c_top2 ( + + // wishbone interface + .wb_clk_i(clk), + .wb_rst_i(1'b0), + .arst_i(rstn), + .wb_adr_i(adr[2:0]), + .wb_dat_i(dat_o), + .wb_dat_o(dat1_i), + .wb_we_i(we), + .wb_stb_i(stb1), + .wb_cyc_i(cyc), + .wb_ack_o(ack1), + .wb_inta_o(inta), + + // i2c signals + .scl_pad_i(scl), + .scl_pad_o(scl1_o), + .scl_padoen_o(scl1_oen), + .sda_pad_i(sda), + .sda_pad_o(sda1_o), + .sda_padoen_o(sda1_oen) + ); + + + // hookup i2c slave model + i2c_slave_model #(SADR) i2c_slave ( + .scl(scl), + .sda(sda) + ); + + //assign scl = ~((!scl0_oen && !scl0_o) || (!scl1_oen && !scl1_o)); + //assign sda = ~((!sda0_oen && !sda0_o) || (!sda1_oen && !sda1_o)); + + // create i2c lines + delay m0_scl (scl0_oen ? 1'bz : scl0_o, scl), + m1_scl (scl1_oen ? 1'bz : scl1_o, scl), + m0_sda (sda0_oen ? 1'bz : sda0_o, sda), + m1_sda (sda1_oen ? 1'bz : sda1_o, sda); + + pullup p1(scl); // pullup scl line + pullup p2(sda); // pullup sda line + + initial + begin + `ifdef WAVES + $shm_open("waves"); + $shm_probe("AS",tst_bench_top,"AS"); + $display("INFO: Signal dump enabled ...\n\n"); + `endif + +// force i2c_slave.debug = 1'b1; // enable i2c_slave debug information + force i2c_slave.debug = 1'b0; // disable i2c_slave debug information + + $display("\nstatus: %t Testbench started\n\n", $time); + +// $dumpfile("bench.vcd"); +// $dumpvars(1, tst_bench_top); +// $dumpvars(1, tst_bench_top.i2c_slave); + + // initially values + clk = 0; + + // reset system + rstn = 1'b1; // negate reset + #2; + rstn = 1'b0; // assert reset + #1000; + repeat(1) @(posedge clk); + rstn = 1'b1; // negate reset + + $display("status: %t done reset", $time); + + @(posedge clk); + + // + // program core + // + + // program internal registers + u0.wb_write(1, PRER_LO, 8'hfa); // load prescaler lo-byte + u0.wb_write(1, PRER_LO, 8'hc8); // load prescaler lo-byte + u0.wb_write(1, PRER_HI, 8'h00); // load prescaler hi-byte + $display("status: %t programmed registers", $time); + + u0.wb_cmp(0, PRER_LO, 8'hc8); // verify prescaler lo-byte + u0.wb_cmp(0, PRER_HI, 8'h00); // verify prescaler hi-byte + $display("status: %t verified registers", $time); + + u0.wb_write(1, CTR, 8'h80); // enable core + $display("status: %t core enabled", $time); + + // + // access slave (write) + // + + // drive slave address + u0.wb_write(1, TXR, {SADR,WR} ); // present slave address, set write-bit + u0.wb_write(0, CR, 8'h90 ); // set command (start, write) + $display("status: %t generate 'start', write cmd %0h (slave address+write)", $time, {SADR,WR} ); + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(0, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + // send memory address + u0.wb_write(1, TXR, 8'h01); // present slave's memory address + u0.wb_write(0, CR, 8'h10); // set command (write) + $display("status: %t write slave memory address 01", $time); + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(0, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + // send memory contents + u0.wb_write(1, TXR, 8'ha5); // present data + u0.wb_write(0, CR, 8'h10); // set command (write) + $display("status: %t write data a5", $time); + +while (scl) #1; +force scl= 1'b0; +#100000; +release scl; + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(1, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + // send memory contents for next memory address (auto_inc) + u0.wb_write(1, TXR, 8'h5a); // present data + u0.wb_write(0, CR, 8'h50); // set command (stop, write) + $display("status: %t write next data 5a, generate 'stop'", $time); + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(1, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + // + // delay + // +// #100000; // wait for 100us. +// $display("status: %t wait 100us", $time); + + // + // access slave (read) + // + + // drive slave address + u0.wb_write(1, TXR,{SADR,WR} ); // present slave address, set write-bit + u0.wb_write(0, CR, 8'h90 ); // set command (start, write) + $display("status: %t generate 'start', write cmd %0h (slave address+write)", $time, {SADR,WR} ); + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(1, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + // send memory address + u0.wb_write(1, TXR, 8'h01); // present slave's memory address + u0.wb_write(0, CR, 8'h10); // set command (write) + $display("status: %t write slave address 01", $time); + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(1, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + // drive slave address + u0.wb_write(1, TXR, {SADR,RD} ); // present slave's address, set read-bit + u0.wb_write(0, CR, 8'h90 ); // set command (start, write) + $display("status: %t generate 'repeated start', write cmd %0h (slave address+read)", $time, {SADR,RD} ); + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(1, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + // read data from slave + u0.wb_write(1, CR, 8'h20); // set command (read, ack_read) + $display("status: %t read + ack", $time); + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(1, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + // check data just received + u0.wb_read(1, RXR, qq); + if(qq !== 8'ha5) + $display("\nERROR: Expected a5, received %x at time %t", qq, $time); + else + $display("status: %t received %x", $time, qq); + + // read data from slave + u0.wb_write(1, CR, 8'h20); // set command (read, ack_read) + $display("status: %t read + ack", $time); + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(1, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + // check data just received + u0.wb_read(1, RXR, qq); + if(qq !== 8'h5a) + $display("\nERROR: Expected 5a, received %x at time %t", qq, $time); + else + $display("status: %t received %x", $time, qq); + + // read data from slave + u0.wb_write(1, CR, 8'h20); // set command (read, ack_read) + $display("status: %t read + ack", $time); + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(1, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + // check data just received + u0.wb_read(1, RXR, qq); + $display("status: %t received %x from 3rd read address", $time, qq); + + // read data from slave + u0.wb_write(1, CR, 8'h28); // set command (read, nack_read) + $display("status: %t read + nack", $time); + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(1, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + // check data just received + u0.wb_read(1, RXR, qq); + $display("status: %t received %x from 4th read address", $time, qq); + + // + // check invalid slave memory address + // + + // drive slave address + u0.wb_write(1, TXR, {SADR,WR} ); // present slave address, set write-bit + u0.wb_write(0, CR, 8'h90 ); // set command (start, write) + $display("status: %t generate 'start', write cmd %0h (slave address+write). Check invalid address", $time, {SADR,WR} ); + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(1, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + // send memory address + u0.wb_write(1, TXR, 8'h10); // present slave's memory address + u0.wb_write(0, CR, 8'h10); // set command (write) + $display("status: %t write slave memory address 10", $time); + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(1, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + // slave should have send NACK + $display("status: %t Check for nack", $time); + if(!q[7]) + $display("\nERROR: Expected NACK, received ACK\n"); + + // read data from slave + u0.wb_write(1, CR, 8'h40); // set command (stop) + $display("status: %t generate 'stop'", $time); + + // check tip bit + u0.wb_read(1, SR, q); + while(q[1]) + u0.wb_read(1, SR, q); // poll it until it is zero + $display("status: %t tip==0", $time); + + #250000; // wait 250us + $display("\n\nstatus: %t Testbench done", $time); + $finish; + end + +endmodule + +module delay (in, out); + input in; + output out; + + assign out = in; + + specify + (in => out) = (599,599); + endspecify +endmodule + + diff --git a/tests/i2c_bench/wb_master_model.v b/tests/i2c_bench/wb_master_model.v new file mode 100644 index 00000000..65a9b798 --- /dev/null +++ b/tests/i2c_bench/wb_master_model.v @@ -0,0 +1,205 @@ +/////////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 Wishbone Master model //// +//// //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/mem_ctrl //// +//// //// +/////////////////////////////////////////////////////////////////////// +//// //// +//// 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: wb_master_model.v,v 1.4 2004-02-28 15:40:42 rherveille Exp $ +// +// $Date: 2004-02-28 15:40:42 $ +// $Revision: 1.4 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// +`include "timescale.v" + +module wb_master_model(clk, rst, adr, din, dout, cyc, stb, we, sel, ack, err, rty); + +parameter dwidth = 32; +parameter awidth = 32; + +input clk, rst; +output [awidth -1:0] adr; +input [dwidth -1:0] din; +output [dwidth -1:0] dout; +output cyc, stb; +output we; +output [dwidth/8 -1:0] sel; +input ack, err, rty; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [awidth -1:0] adr; +reg [dwidth -1:0] dout; +reg cyc, stb; +reg we; +reg [dwidth/8 -1:0] sel; + +reg [dwidth -1:0] q; + +//////////////////////////////////////////////////////////////////// +// +// Memory Logic +// + +initial + begin + //adr = 32'hxxxx_xxxx; + //adr = 0; + adr = {awidth{1'bx}}; + dout = {dwidth{1'bx}}; + cyc = 1'b0; + stb = 1'bx; + we = 1'hx; + sel = {dwidth/8{1'bx}}; + #1; + $display("\nINFO: WISHBONE MASTER MODEL INSTANTIATED (%m)\n"); + end + +//////////////////////////////////////////////////////////////////// +// +// Wishbone write cycle +// + +task wb_write; + input delay; + integer delay; + + input [awidth -1:0] a; + input [dwidth -1:0] d; + + begin + + // wait initial delay + repeat(delay) @(posedge clk); + + // assert wishbone signal + #1; + adr = a; + dout = d; + cyc = 1'b1; + stb = 1'b1; + we = 1'b1; + sel = {dwidth/8{1'b1}}; + @(posedge clk); + + // wait for acknowledge from slave + while(~ack) @(posedge clk); + + // negate wishbone signals + #1; + cyc = 1'b0; + stb = 1'bx; + adr = {awidth{1'bx}}; + dout = {dwidth{1'bx}}; + we = 1'hx; + sel = {dwidth/8{1'bx}}; + + end +endtask + +//////////////////////////////////////////////////////////////////// +// +// Wishbone read cycle +// + +task wb_read; + input delay; + integer delay; + + input [awidth -1:0] a; + output [dwidth -1:0] d; + + begin + + // wait initial delay + repeat(delay) @(posedge clk); + + // assert wishbone signals + #1; + adr = a; + dout = {dwidth{1'bx}}; + cyc = 1'b1; + stb = 1'b1; + we = 1'b0; + sel = {dwidth/8{1'b1}}; + @(posedge clk); + + // wait for acknowledge from slave + while(~ack) @(posedge clk); + + // negate wishbone signals + #1; + cyc = 1'b0; + stb = 1'bx; + adr = {awidth{1'bx}}; + dout = {dwidth{1'bx}}; + we = 1'hx; + sel = {dwidth/8{1'bx}}; + d = din; + + end +endtask + +//////////////////////////////////////////////////////////////////// +// +// Wishbone compare cycle (read data from location and compare with expected data) +// + +task wb_cmp; + input delay; + integer delay; + + input [awidth -1:0] a; + input [dwidth -1:0] d_exp; + + begin + wb_read (delay, a, q); + + if (d_exp !== q) + $display("Data compare error. Received %h, expected %h at time %t", q, d_exp, $time); + end +endtask + +endmodule + + 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 + diff --git a/tests/no-icarus/README b/tests/no-icarus/README new file mode 100644 index 00000000..b43e7c02 --- /dev/null +++ b/tests/no-icarus/README @@ -0,0 +1,2 @@ +This directory contains test cases that can't be tested using Icarus Verilog +because they exceed the Verilog subset that is supported by Icarus Verilog. diff --git a/tests/no-icarus/autowire.v b/tests/no-icarus/autowire.v new file mode 100644 index 00000000..3633d427 --- /dev/null +++ b/tests/no-icarus/autowire.v @@ -0,0 +1,25 @@ + +module test01(a, b, y); + +input [3:0] a, b; +output [3:0] y; + +assign temp1 = a + b; +assign temp2 = ~temp1; +assign y = temp2; + +endmodule + +// ------------------------------ + +module test02(a, b, y); + +input [3:0] a, b; +output [3:0] y; + +test01 test01_cell(A, B, Y); + +assign A = a, B = b, y = Y; + +endmodule + diff --git a/tests/no-icarus/var_range.v b/tests/no-icarus/var_range.v new file mode 100644 index 00000000..431eacb8 --- /dev/null +++ b/tests/no-icarus/var_range.v @@ -0,0 +1,45 @@ + +module test01(a, b, x, y, z); + +input [7:0] a; +input [2:0] b; +output [7:0] x, y; +output z; + +assign x = a >> b; +assign y = a[b+7:b]; +assign z = a[b]; + +endmodule + +module test02(clk, a, b, x, y, z); + +input clk; +input [7:0] a; +input [2:0] b; +output reg [7:0] x, y; +output reg z; + +always @(posedge clk) begin + x <= a >> b; + y <= a[b+7:b]; + z <= a[b]; +end + +endmodule + +module test03(clk, a, b, x, y); + +input clk; +input [2:0] a, b; +output reg [7:0] x; +output reg [9:0] y; + +always @(posedge clk) + y[b] <= a; + +always @(posedge clk) + y[b+2:b] <= a; + +endmodule + diff --git a/tests/openmsp430/rtl/omsp_alu.v b/tests/openmsp430/rtl/omsp_alu.v new file mode 100644 index 00000000..d1069973 --- /dev/null +++ b/tests/openmsp430/rtl/omsp_alu.v @@ -0,0 +1,258 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_alu.v +// +// *Module Description: +// openMSP430 ALU +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 134 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2012-03-22 21:31:06 +0100 (Thu, 22 Mar 2012) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module omsp_alu ( + +// OUTPUTs + alu_out, // ALU output value + alu_out_add, // ALU adder output value + alu_stat, // ALU Status {V,N,Z,C} + alu_stat_wr, // ALU Status write {V,N,Z,C} + +// INPUTs + dbg_halt_st, // Halt/Run status from CPU + exec_cycle, // Instruction execution cycle + inst_alu, // ALU control signals + inst_bw, // Decoded Inst: byte width + inst_jmp, // Decoded Inst: Conditional jump + inst_so, // Single-operand arithmetic + op_dst, // Destination operand + op_src, // Source operand + status // R2 Status {V,N,Z,C} +); + +// OUTPUTs +//========= +output [15:0] alu_out; // ALU output value +output [15:0] alu_out_add; // ALU adder output value +output [3:0] alu_stat; // ALU Status {V,N,Z,C} +output [3:0] alu_stat_wr; // ALU Status write {V,N,Z,C} + +// INPUTs +//========= +input dbg_halt_st; // Halt/Run status from CPU +input exec_cycle; // Instruction execution cycle +input [11:0] inst_alu; // ALU control signals +input inst_bw; // Decoded Inst: byte width +input [7:0] inst_jmp; // Decoded Inst: Conditional jump +input [7:0] inst_so; // Single-operand arithmetic +input [15:0] op_dst; // Destination operand +input [15:0] op_src; // Source operand +input [3:0] status; // R2 Status {V,N,Z,C} + + +//============================================================================= +// 1) FUNCTIONS +//============================================================================= + +function [4:0] bcd_add; + + input [3:0] X; + input [3:0] Y; + input C_; + + reg [4:0] Z_; + begin + Z_ = {1'b0,X}+{1'b0,Y}+{4'b0,C_}; + if (Z_<5'd10) bcd_add = Z_; + else bcd_add = Z_+5'd6; + end + +endfunction + + +//============================================================================= +// 2) INSTRUCTION FETCH/DECODE CONTROL STATE MACHINE +//============================================================================= +// SINGLE-OPERAND ARITHMETIC: +//----------------------------------------------------------------------------- +// Mnemonic S-Reg, Operation Status bits +// D-Reg, V N Z C +// +// RRC dst C->MSB->...LSB->C * * * * +// RRA dst MSB->MSB->...LSB->C 0 * * * +// SWPB dst Swap bytes - - - - +// SXT dst Bit7->Bit8...Bit15 0 * * * +// PUSH src SP-2->SP, src->@SP - - - - +// CALL dst SP-2->SP, PC+2->@SP, dst->PC - - - - +// RETI TOS->SR, SP+2->SP, TOS->PC, SP+2->SP * * * * +// +//----------------------------------------------------------------------------- +// TWO-OPERAND ARITHMETIC: +//----------------------------------------------------------------------------- +// Mnemonic S-Reg, Operation Status bits +// D-Reg, V N Z C +// +// MOV src,dst src -> dst - - - - +// ADD src,dst src + dst -> dst * * * * +// ADDC src,dst src + dst + C -> dst * * * * +// SUB src,dst dst + ~src + 1 -> dst * * * * +// SUBC src,dst dst + ~src + C -> dst * * * * +// CMP src,dst dst + ~src + 1 * * * * +// DADD src,dst src + dst + C -> dst (decimaly) * * * * +// BIT src,dst src & dst 0 * * * +// BIC src,dst ~src & dst -> dst - - - - +// BIS src,dst src | dst -> dst - - - - +// XOR src,dst src ^ dst -> dst * * * * +// AND src,dst src & dst -> dst 0 * * * +// +//----------------------------------------------------------------------------- +// * the status bit is affected +// - the status bit is not affected +// 0 the status bit is cleared +// 1 the status bit is set +//----------------------------------------------------------------------------- + +// Invert source for substract and compare instructions. +wire op_src_inv_cmd = exec_cycle & (inst_alu[`ALU_SRC_INV]); +wire [15:0] op_src_inv = {16{op_src_inv_cmd}} ^ op_src; + + +// Mask the bit 8 for the Byte instructions for correct flags generation +wire op_bit8_msk = ~exec_cycle | ~inst_bw; +wire [16:0] op_src_in = {1'b0, {op_src_inv[15:8] & {8{op_bit8_msk}}}, op_src_inv[7:0]}; +wire [16:0] op_dst_in = {1'b0, {op_dst[15:8] & {8{op_bit8_msk}}}, op_dst[7:0]}; + +// Clear the source operand (= jump offset) for conditional jumps +wire jmp_not_taken = (inst_jmp[`JL] & ~(status[3]^status[2])) | + (inst_jmp[`JGE] & (status[3]^status[2])) | + (inst_jmp[`JN] & ~status[2]) | + (inst_jmp[`JC] & ~status[0]) | + (inst_jmp[`JNC] & status[0]) | + (inst_jmp[`JEQ] & ~status[1]) | + (inst_jmp[`JNE] & status[1]); +wire [16:0] op_src_in_jmp = op_src_in & {17{~jmp_not_taken}}; + +// Adder / AND / OR / XOR +wire [16:0] alu_add = op_src_in_jmp + op_dst_in; +wire [16:0] alu_and = op_src_in & op_dst_in; +wire [16:0] alu_or = op_src_in | op_dst_in; +wire [16:0] alu_xor = op_src_in ^ op_dst_in; + + +// Incrementer +wire alu_inc = exec_cycle & ((inst_alu[`ALU_INC_C] & status[0]) | + inst_alu[`ALU_INC]); +wire [16:0] alu_add_inc = alu_add + {16'h0000, alu_inc}; + + + +// Decimal adder (DADD) +wire [4:0] alu_dadd0 = bcd_add(op_src_in[3:0], op_dst_in[3:0], status[0]); +wire [4:0] alu_dadd1 = bcd_add(op_src_in[7:4], op_dst_in[7:4], alu_dadd0[4]); +wire [4:0] alu_dadd2 = bcd_add(op_src_in[11:8], op_dst_in[11:8], alu_dadd1[4]); +wire [4:0] alu_dadd3 = bcd_add(op_src_in[15:12], op_dst_in[15:12],alu_dadd2[4]); +wire [16:0] alu_dadd = {alu_dadd3, alu_dadd2[3:0], alu_dadd1[3:0], alu_dadd0[3:0]}; + + +// Shifter for rotate instructions (RRC & RRA) +wire alu_shift_msb = inst_so[`RRC] ? status[0] : + inst_bw ? op_src[7] : op_src[15]; +wire alu_shift_7 = inst_bw ? alu_shift_msb : op_src[8]; +wire [16:0] alu_shift = {1'b0, alu_shift_msb, op_src[15:9], alu_shift_7, op_src[7:1]}; + + +// Swap bytes / Extend Sign +wire [16:0] alu_swpb = {1'b0, op_src[7:0],op_src[15:8]}; +wire [16:0] alu_sxt = {1'b0, {8{op_src[7]}},op_src[7:0]}; + + +// Combine short paths toghether to simplify final ALU mux +wire alu_short_thro = ~(inst_alu[`ALU_AND] | + inst_alu[`ALU_OR] | + inst_alu[`ALU_XOR] | + inst_alu[`ALU_SHIFT] | + inst_so[`SWPB] | + inst_so[`SXT]); + +wire [16:0] alu_short = ({17{inst_alu[`ALU_AND]}} & alu_and) | + ({17{inst_alu[`ALU_OR]}} & alu_or) | + ({17{inst_alu[`ALU_XOR]}} & alu_xor) | + ({17{inst_alu[`ALU_SHIFT]}} & alu_shift) | + ({17{inst_so[`SWPB]}} & alu_swpb) | + ({17{inst_so[`SXT]}} & alu_sxt) | + ({17{alu_short_thro}} & op_src_in); + + +// ALU output mux +wire [16:0] alu_out_nxt = (inst_so[`IRQ] | dbg_halt_st | + inst_alu[`ALU_ADD]) ? alu_add_inc : + inst_alu[`ALU_DADD] ? alu_dadd : alu_short; + +assign alu_out = alu_out_nxt[15:0]; +assign alu_out_add = alu_add[15:0]; + + +//----------------------------------------------------------------------------- +// STATUS FLAG GENERATION +//----------------------------------------------------------------------------- + +wire V_xor = inst_bw ? (op_src_in[7] & op_dst_in[7]) : + (op_src_in[15] & op_dst_in[15]); + +wire V = inst_bw ? ((~op_src_in[7] & ~op_dst_in[7] & alu_out[7]) | + ( op_src_in[7] & op_dst_in[7] & ~alu_out[7])) : + ((~op_src_in[15] & ~op_dst_in[15] & alu_out[15]) | + ( op_src_in[15] & op_dst_in[15] & ~alu_out[15])); + +wire N = inst_bw ? alu_out[7] : alu_out[15]; +wire Z = inst_bw ? (alu_out[7:0]==0) : (alu_out==0); +wire C = inst_bw ? alu_out[8] : alu_out_nxt[16]; + +assign alu_stat = inst_alu[`ALU_SHIFT] ? {1'b0, N,Z,op_src_in[0]} : + inst_alu[`ALU_STAT_7] ? {1'b0, N,Z,~Z} : + inst_alu[`ALU_XOR] ? {V_xor,N,Z,~Z} : {V,N,Z,C}; + +assign alu_stat_wr = (inst_alu[`ALU_STAT_F] & exec_cycle) ? 4'b1111 : 4'b0000; + + +endmodule // omsp_alu + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif diff --git a/tests/openmsp430/rtl/omsp_and_gate.v b/tests/openmsp430/rtl/omsp_and_gate.v new file mode 100644 index 00000000..7ceeb8d9 --- /dev/null +++ b/tests/openmsp430/rtl/omsp_and_gate.v @@ -0,0 +1,89 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_and_gate.v +// +// *Module Description: +// Generic AND gate cell for the openMSP430 +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 103 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $ +//---------------------------------------------------------------------------- + +module omsp_and_gate ( + +// OUTPUTs + y, // AND gate output + +// INPUTs + a, // AND gate input A + b // AND gate input B +); + +// OUTPUTs +//========= +output y; // AND gate output + +// INPUTs +//========= +input a; // AND gate input A +input b; // AND gate input B + + +//============================================================================= +// 1) SOME COMMENTS ON THIS MODULE +//============================================================================= +// +// In its ASIC version, some combinatorial pathes of the openMSP430 are +// sensitive to glitches, in particular the ones generating the wakeup +// signals. +// To prevent synthesis from optmizing combinatorial clouds into glitchy +// logic, this AND gate module has been instanciated in the critical places. +// +// Make sure that synthesis doesn't ungroup this module. As an alternative, +// a standard cell from the library could also be directly instanciated here +// (don't forget the "dont_touch" attribute) +// +// +//============================================================================= +// 2) AND GATE +//============================================================================= + +assign y = a & b; + + +endmodule // omsp_and_gate + + + diff --git a/tests/openmsp430/rtl/omsp_clock_gate.v b/tests/openmsp430/rtl/omsp_clock_gate.v new file mode 100644 index 00000000..8ffe8e0d --- /dev/null +++ b/tests/openmsp430/rtl/omsp_clock_gate.v @@ -0,0 +1,86 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_clock_gate.v +// +// *Module Description: +// Generic clock gate cell for the openMSP430 +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 103 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $ +//---------------------------------------------------------------------------- + +module omsp_clock_gate ( + +// OUTPUTs + gclk, // Gated clock + +// INPUTs + clk, // Clock + enable, // Clock enable + scan_enable // Scan enable (active during scan shifting) +); + +// OUTPUTs +//========= +output gclk; // Gated clock + +// INPUTs +//========= +input clk; // Clock +input enable; // Clock enable +input scan_enable; // Scan enable (active during scan shifting) + + +//============================================================================= +// CLOCK GATE: LATCH + AND +//============================================================================= + +// Enable clock gate during scan shift +// (the gate itself is checked with the scan capture cycle) +wire enable_in = (enable | scan_enable); + +// LATCH the enable signal +reg enable_latch; +always @(clk or enable_in) + if (~clk) + enable_latch <= enable_in; + +// AND gate +assign gclk = (clk & enable_latch); + + +endmodule // omsp_clock_gate + + diff --git a/tests/openmsp430/rtl/omsp_clock_module.v b/tests/openmsp430/rtl/omsp_clock_module.v new file mode 100644 index 00000000..670c5e59 --- /dev/null +++ b/tests/openmsp430/rtl/omsp_clock_module.v @@ -0,0 +1,1058 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_clock_module.v +// +// *Module Description: +// Basic clock module implementation. +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 134 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2012-03-22 21:31:06 +0100 (Thu, 22 Mar 2012) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module omsp_clock_module ( + +// OUTPUTs + aclk, // ACLK + aclk_en, // ACLK enable + cpu_en_s, // Enable CPU code execution (synchronous) + dbg_clk, // Debug unit clock + dbg_en_s, // Debug interface enable (synchronous) + dbg_rst, // Debug unit reset + dco_enable, // Fast oscillator enable + dco_wkup, // Fast oscillator wake-up (asynchronous) + lfxt_enable, // Low frequency oscillator enable + lfxt_wkup, // Low frequency oscillator wake-up (asynchronous) + mclk, // Main system clock + per_dout, // Peripheral data output + por, // Power-on reset + puc_pnd_set, // PUC pending set for the serial debug interface + puc_rst, // Main system reset + smclk, // SMCLK + smclk_en, // SMCLK enable + +// INPUTs + cpu_en, // Enable CPU code execution (asynchronous) + cpuoff, // Turns off the CPU + dbg_cpu_reset, // Reset CPU from debug interface + dbg_en, // Debug interface enable (asynchronous) + dco_clk, // Fast oscillator (fast clock) + lfxt_clk, // Low frequency oscillator (typ 32kHz) + mclk_enable, // Main System Clock enable + mclk_wkup, // Main System Clock wake-up (asynchronous) + oscoff, // Turns off LFXT1 clock input + per_addr, // Peripheral address + per_din, // Peripheral data input + per_en, // Peripheral enable (high active) + per_we, // Peripheral write enable (high active) + reset_n, // Reset Pin (low active, asynchronous) + scan_enable, // Scan enable (active during scan shifting) + scan_mode, // Scan mode + scg0, // System clock generator 1. Turns off the DCO + scg1, // System clock generator 1. Turns off the SMCLK + wdt_reset // Watchdog-timer reset +); + +// OUTPUTs +//========= +output aclk; // ACLK +output aclk_en; // ACLK enable +output cpu_en_s; // Enable CPU code execution (synchronous) +output dbg_clk; // Debug unit clock +output dbg_en_s; // Debug unit enable (synchronous) +output dbg_rst; // Debug unit reset +output dco_enable; // Fast oscillator enable +output dco_wkup; // Fast oscillator wake-up (asynchronous) +output lfxt_enable; // Low frequency oscillator enable +output lfxt_wkup; // Low frequency oscillator wake-up (asynchronous) +output mclk; // Main system clock +output [15:0] per_dout; // Peripheral data output +output por; // Power-on reset +output puc_pnd_set; // PUC pending set for the serial debug interface +output puc_rst; // Main system reset +output smclk; // SMCLK +output smclk_en; // SMCLK enable + +// INPUTs +//========= +input cpu_en; // Enable CPU code execution (asynchronous) +input cpuoff; // Turns off the CPU +input dbg_cpu_reset;// Reset CPU from debug interface +input dbg_en; // Debug interface enable (asynchronous) +input dco_clk; // Fast oscillator (fast clock) +input lfxt_clk; // Low frequency oscillator (typ 32kHz) +input mclk_enable; // Main System Clock enable +input mclk_wkup; // Main System Clock wake-up (asynchronous) +input oscoff; // Turns off LFXT1 clock input +input [13:0] per_addr; // Peripheral address +input [15:0] per_din; // Peripheral data input +input per_en; // Peripheral enable (high active) +input [1:0] per_we; // Peripheral write enable (high active) +input reset_n; // Reset Pin (low active, asynchronous) +input scan_enable; // Scan enable (active during scan shifting) +input scan_mode; // Scan mode +input scg0; // System clock generator 1. Turns off the DCO +input scg1; // System clock generator 1. Turns off the SMCLK +input wdt_reset; // Watchdog-timer reset + + +//============================================================================= +// 1) WIRES & PARAMETER DECLARATION +//============================================================================= + +// Register base address (must be aligned to decoder bit width) +parameter [14:0] BASE_ADDR = 15'h0050; + +// Decoder bit width (defines how many bits are considered for address decoding) +parameter DEC_WD = 4; + +// Register addresses offset +parameter [DEC_WD-1:0] BCSCTL1 = 'h7, + BCSCTL2 = 'h8; + +// Register one-hot decoder utilities +parameter DEC_SZ = (1 << DEC_WD); +parameter [DEC_SZ-1:0] BASE_REG = {{DEC_SZ-1{1'b0}}, 1'b1}; + +// Register one-hot decoder +parameter [DEC_SZ-1:0] BCSCTL1_D = (BASE_REG << BCSCTL1), + BCSCTL2_D = (BASE_REG << BCSCTL2); + +// Local wire declarations +wire nodiv_mclk; +wire nodiv_mclk_n; +wire nodiv_smclk; + + +//============================================================================ +// 2) REGISTER DECODER +//============================================================================ + +// Local register selection +wire reg_sel = per_en & (per_addr[13:DEC_WD-1]==BASE_ADDR[14:DEC_WD]); + +// Register local address +wire [DEC_WD-1:0] reg_addr = {1'b0, per_addr[DEC_WD-2:0]}; + +// Register address decode +wire [DEC_SZ-1:0] reg_dec = (BCSCTL1_D & {DEC_SZ{(reg_addr==(BCSCTL1 >>1))}}) | + (BCSCTL2_D & {DEC_SZ{(reg_addr==(BCSCTL2 >>1))}}); + +// Read/Write probes +wire reg_lo_write = per_we[0] & reg_sel; +wire reg_hi_write = per_we[1] & reg_sel; +wire reg_read = ~|per_we & reg_sel; + +// Read/Write vectors +wire [DEC_SZ-1:0] reg_hi_wr = reg_dec & {DEC_SZ{reg_hi_write}}; +wire [DEC_SZ-1:0] reg_lo_wr = reg_dec & {DEC_SZ{reg_lo_write}}; +wire [DEC_SZ-1:0] reg_rd = reg_dec & {DEC_SZ{reg_read}}; + + +//============================================================================ +// 3) REGISTERS +//============================================================================ + +// BCSCTL1 Register +//-------------- +reg [7:0] bcsctl1; +wire bcsctl1_wr = BCSCTL1[0] ? reg_hi_wr[BCSCTL1] : reg_lo_wr[BCSCTL1]; +wire [7:0] bcsctl1_nxt = BCSCTL1[0] ? per_din[15:8] : per_din[7:0]; + +`ifdef ASIC + `ifdef ACLK_DIVIDER +wire [7:0] divax_mask = 8'h30; + `else +wire [7:0] divax_mask = 8'h00; + `endif +`else +wire [7:0] divax_mask = 8'h30; +`endif + +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) bcsctl1 <= 8'h00; + else if (bcsctl1_wr) bcsctl1 <= bcsctl1_nxt & divax_mask; // Mask unused bits + + +// BCSCTL2 Register +//-------------- +reg [7:0] bcsctl2; +wire bcsctl2_wr = BCSCTL2[0] ? reg_hi_wr[BCSCTL2] : reg_lo_wr[BCSCTL2]; +wire [7:0] bcsctl2_nxt = BCSCTL2[0] ? per_din[15:8] : per_din[7:0]; + +`ifdef MCLK_MUX +wire [7:0] selmx_mask = 8'h80; +`else +wire [7:0] selmx_mask = 8'h00; +`endif +`ifdef MCLK_DIVIDER +wire [7:0] divmx_mask = 8'h30; +`else +wire [7:0] divmx_mask = 8'h00; +`endif +`ifdef ASIC + `ifdef SMCLK_MUX +wire [7:0] sels_mask = 8'h08; + `else +wire [7:0] sels_mask = 8'h00; + `endif + `ifdef SMCLK_DIVIDER +wire [7:0] divsx_mask = 8'h06; + `else +wire [7:0] divsx_mask = 8'h00; + `endif +`else +wire [7:0] sels_mask = 8'h08; +wire [7:0] divsx_mask = 8'h06; +`endif + +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) bcsctl2 <= 8'h00; + else if (bcsctl2_wr) bcsctl2 <= bcsctl2_nxt & ( sels_mask | divsx_mask | + selmx_mask | divmx_mask); // Mask unused bits + + +//============================================================================ +// 4) DATA OUTPUT GENERATION +//============================================================================ + +// Data output mux +wire [15:0] bcsctl1_rd = {8'h00, (bcsctl1 & {8{reg_rd[BCSCTL1]}})} << (8 & {4{BCSCTL1[0]}}); +wire [15:0] bcsctl2_rd = {8'h00, (bcsctl2 & {8{reg_rd[BCSCTL2]}})} << (8 & {4{BCSCTL2[0]}}); + +wire [15:0] per_dout = bcsctl1_rd | + bcsctl2_rd; + + +//============================================================================= +// 5) DCO_CLK / LFXT_CLK INTERFACES (WAKEUP, ENABLE, ...) +//============================================================================= + +`ifdef ASIC + wire cpuoff_and_mclk_enable; + omsp_and_gate and_cpuoff_mclk_en (.y(cpuoff_and_mclk_enable), .a(cpuoff), .b(mclk_enable)); +`endif + +//----------------------------------------------------------- +// 5.1) HIGH SPEED SYSTEM CLOCK GENERATOR (DCO_CLK) +//----------------------------------------------------------- +// Note1: switching off the DCO osillator is only +// supported in ASIC mode with SCG0 low power mode +// +// Note2: unlike the original MSP430 specification, +// we allow to switch off the DCO even +// if it is selected by MCLK or SMCLK. + +wire por_a; +wire dco_wkup; +wire cpu_en_wkup; + +`ifdef SCG0_EN + + // The DCO oscillator is synchronously disabled if: + // - the cpu pin is disabled (in that case, wait for mclk_enable==0) + // - the debug interface is disabled + // - SCG0 is set (in that case, wait for the mclk_enable==0 if selected by SELMx) + // + // Note that we make extensive use of the AND gate module in order + // to prevent glitch propagation on the wakeup logic cone. + wire cpu_enabled_with_dco; + wire dco_not_enabled_by_dbg; + wire dco_disable_by_scg0; + wire dco_disable_by_cpu_en; + wire dco_enable_nxt; + omsp_and_gate and_dco_dis1 (.y(cpu_enabled_with_dco), .a(~bcsctl2[`SELMx]), .b(cpuoff_and_mclk_enable)); + omsp_and_gate and_dco_dis2 (.y(dco_not_enabled_by_dbg), .a(~dbg_en_s), .b(~cpu_enabled_with_dco)); + omsp_and_gate and_dco_dis3 (.y(dco_disable_by_scg0), .a(scg0), .b(dco_not_enabled_by_dbg)); + omsp_and_gate and_dco_dis4 (.y(dco_disable_by_cpu_en), .a(~cpu_en_s), .b(~mclk_enable)); + omsp_and_gate and_dco_dis5 (.y(dco_enable_nxt), .a(~dco_disable_by_scg0), .b(~dco_disable_by_cpu_en)); + + // Register to prevent glitch propagation + reg dco_disable; + always @(posedge nodiv_mclk_n or posedge por) + if (por) dco_disable <= 1'b1; + else dco_disable <= ~dco_enable_nxt; + + // Note that a synchronizer is required if the MCLK mux is included + wire dco_clk_n = ~dco_clk; + `ifdef MCLK_MUX + omsp_sync_cell sync_cell_dco_disable ( + .data_out (dco_enable), + .data_in (~dco_disable), + .clk (dco_clk_n), + .rst (por) + ); + `else + + assign dco_enable = ~dco_disable; + `endif + + // The DCO oscillator will get an asynchronous wakeup if: + // - the MCLK generates a wakeup (only if the MCLK mux selects dco_clk) + // - if the DCO wants to be synchronously enabled (i.e dco_enable_nxt=1) + wire dco_mclk_wkup; + wire dco_en_wkup; + omsp_and_gate and_dco_mclk_wkup (.y(dco_mclk_wkup), .a(mclk_wkup), .b(~bcsctl2[`SELMx])); + omsp_and_gate and_dco_en_wkup (.y(dco_en_wkup), .a(~dco_enable), .b(dco_enable_nxt)); + + wire dco_wkup_set = dco_mclk_wkup | dco_en_wkup | cpu_en_wkup; + + // Scan MUX for the asynchronous SET + wire dco_wkup_set_scan; + omsp_scan_mux scan_mux_dco_wkup ( + .scan_mode (scan_mode), + .data_in_scan (por_a), + .data_in_func (dco_wkup_set | por), + .data_out (dco_wkup_set_scan) + ); + + // Scan MUX to increase coverage + wire dco_wkup_clear; + omsp_scan_mux scan_mux_dco_wkup_clear ( + .scan_mode (scan_mode), + .data_in_scan (dco_wkup_set), + .data_in_func (1'b1), + .data_out (dco_wkup_clear) + ); + + // The wakeup is asynchronously set, synchronously released + wire dco_wkup_n; + omsp_sync_cell sync_cell_dco_wkup ( + .data_out (dco_wkup_n), + .data_in (dco_wkup_clear), + .clk (dco_clk_n), + .rst (dco_wkup_set_scan) + ); + + omsp_and_gate and_dco_wkup (.y(dco_wkup), .a(~dco_wkup_n), .b(cpu_en)); + +`else + assign dco_enable = 1'b1; + assign dco_wkup = 1'b1; +`endif + + +//----------------------------------------------------------- +// 5.2) LOW FREQUENCY CRYSTAL CLOCK GENERATOR (LFXT_CLK) +//----------------------------------------------------------- + +// ASIC MODE +//------------------------------------------------ +// Note: unlike the original MSP430 specification, +// we allow to switch off the LFXT even +// if it is selected by MCLK or SMCLK. +`ifdef ASIC + +`ifdef OSCOFF_EN + + // The LFXT is synchronously disabled if: + // - the cpu pin is disabled (in that case, wait for mclk_enable==0) + // - the debug interface is disabled + // - OSCOFF is set (in that case, wait for the mclk_enable==0 if selected by SELMx) + wire cpu_enabled_with_lfxt; + wire lfxt_not_enabled_by_dbg; + wire lfxt_disable_by_oscoff; + wire lfxt_disable_by_cpu_en; + wire lfxt_enable_nxt; + omsp_and_gate and_lfxt_dis1 (.y(cpu_enabled_with_lfxt), .a(bcsctl2[`SELMx]), .b(cpuoff_and_mclk_enable)); + omsp_and_gate and_lfxt_dis2 (.y(lfxt_not_enabled_by_dbg), .a(~dbg_en_s), .b(~cpu_enabled_with_lfxt)); + omsp_and_gate and_lfxt_dis3 (.y(lfxt_disable_by_oscoff), .a(oscoff), .b(lfxt_not_enabled_by_dbg)); + omsp_and_gate and_lfxt_dis4 (.y(lfxt_disable_by_cpu_en), .a(~cpu_en_s), .b(~mclk_enable)); + omsp_and_gate and_lfxt_dis5 (.y(lfxt_enable_nxt), .a(~lfxt_disable_by_oscoff), .b(~lfxt_disable_by_cpu_en)); + + // Register to prevent glitch propagation + reg lfxt_disable; + always @(posedge nodiv_mclk_n or posedge por) + if (por) lfxt_disable <= 1'b1; + else lfxt_disable <= ~lfxt_enable_nxt; + + // Synchronize the OSCOFF control signal to the LFXT clock domain + wire lfxt_clk_n = ~lfxt_clk; + omsp_sync_cell sync_cell_lfxt_disable ( + .data_out (lfxt_enable), + .data_in (~lfxt_disable), + .clk (lfxt_clk_n), + .rst (por) + ); + + // The LFXT will get an asynchronous wakeup if: + // - the MCLK generates a wakeup (only if the MCLK mux selects lfxt_clk) + // - if the LFXT wants to be synchronously enabled (i.e lfxt_enable_nxt=1) + wire lfxt_mclk_wkup; + wire lfxt_en_wkup; + omsp_and_gate and_lfxt_mclk_wkup (.y(lfxt_mclk_wkup), .a(mclk_wkup), .b(bcsctl2[`SELMx])); + omsp_and_gate and_lfxt_en_wkup (.y(lfxt_en_wkup), .a(~lfxt_enable), .b(lfxt_enable_nxt)); + + wire lfxt_wkup_set = lfxt_mclk_wkup | lfxt_en_wkup | cpu_en_wkup; + + // Scan MUX for the asynchronous SET + wire lfxt_wkup_set_scan; + omsp_scan_mux scan_mux_lfxt_wkup ( + .scan_mode (scan_mode), + .data_in_scan (por_a), + .data_in_func (lfxt_wkup_set | por), + .data_out (lfxt_wkup_set_scan) + ); + + // Scan MUX to increase coverage + wire lfxt_wkup_clear; + omsp_scan_mux scan_mux_lfxt_wkup_clear ( + .scan_mode (scan_mode), + .data_in_scan (lfxt_wkup_set), + .data_in_func (1'b1), + .data_out (lfxt_wkup_clear) + ); + + // The wakeup is asynchronously set, synchronously released + wire lfxt_wkup_n; + omsp_sync_cell sync_cell_lfxt_wkup ( + .data_out (lfxt_wkup_n), + .data_in (lfxt_wkup_clear), + .clk (lfxt_clk_n), + .rst (lfxt_wkup_set_scan) + ); + + omsp_and_gate and_lfxt_wkup (.y(lfxt_wkup), .a(~lfxt_wkup_n), .b(cpu_en)); + +`else + assign lfxt_enable = 1'b1; + assign lfxt_wkup = 1'b0; +`endif + + +// FPGA MODE +//--------------------------------------- +// Synchronize LFXT_CLK & edge detection +`else + +wire lfxt_clk_s; + +omsp_sync_cell sync_cell_lfxt_clk ( + .data_out (lfxt_clk_s), + .data_in (lfxt_clk), + .clk (mclk), + .rst (por) +); + +reg lfxt_clk_dly; + +always @ (posedge mclk or posedge por) + if (por) lfxt_clk_dly <= 1'b0; + else lfxt_clk_dly <= lfxt_clk_s; + +wire lfxt_clk_en = (lfxt_clk_s & ~lfxt_clk_dly) & ~(oscoff & ~bcsctl2[`SELS]); +assign lfxt_enable = 1'b1; +assign lfxt_wkup = 1'b0; +`endif + + +//============================================================================= +// 6) CLOCK GENERATION +//============================================================================= + +//----------------------------------------------------------- +// 6.1) GLOBAL CPU ENABLE +//----------------------------------------------------------- +// ACLK and SMCLK are directly switched-off +// with the cpu_en pin (after synchronization). +// MCLK will be switched off once the CPU reaches +// its IDLE state (through the mclk_enable signal) + + +// Synchronize CPU_EN signal to the MCLK domain +//---------------------------------------------- +`ifdef SYNC_CPU_EN + omsp_sync_cell sync_cell_cpu_en ( + .data_out (cpu_en_s), + .data_in (cpu_en), + .clk (nodiv_mclk), + .rst (por) + ); + omsp_and_gate and_cpu_en_wkup (.y(cpu_en_wkup), .a(cpu_en), .b(~cpu_en_s)); +`else + assign cpu_en_s = cpu_en; + assign cpu_en_wkup = 1'b0; +`endif + +// Synchronize CPU_EN signal to the ACLK domain +//---------------------------------------------- +`ifdef LFXT_DOMAIN + wire cpu_en_aux_s; + omsp_sync_cell sync_cell_cpu_aux_en ( + .data_out (cpu_en_aux_s), + .data_in (cpu_en), + .clk (lfxt_clk), + .rst (por) + ); +`else + wire cpu_en_aux_s = cpu_en_s; +`endif + +// Synchronize CPU_EN signal to the SMCLK domain +//---------------------------------------------- +// Note: the synchronizer is only required if there is a SMCLK_MUX +`ifdef ASIC + `ifdef SMCLK_MUX + wire cpu_en_sm_s; + omsp_sync_cell sync_cell_cpu_sm_en ( + .data_out (cpu_en_sm_s), + .data_in (cpu_en), + .clk (nodiv_smclk), + .rst (por) + ); + `else + wire cpu_en_sm_s = cpu_en_s; + `endif +`endif + + +//----------------------------------------------------------- +// 6.2) MCLK GENERATION +//----------------------------------------------------------- + +// Clock MUX +//---------------------------- +`ifdef MCLK_MUX +omsp_clock_mux clock_mux_mclk ( + .clk_out (nodiv_mclk), + .clk_in0 (dco_clk), + .clk_in1 (lfxt_clk), + .reset (por), + .scan_mode (scan_mode), + .select (bcsctl2[`SELMx]) +); +`else +assign nodiv_mclk = dco_clk; +`endif +assign nodiv_mclk_n = ~nodiv_mclk; + + +// Wakeup synchronizer +//---------------------------- +wire mclk_wkup_s; + +`ifdef CPUOFF_EN +omsp_sync_cell sync_cell_mclk_wkup ( + .data_out (mclk_wkup_s), + .data_in (mclk_wkup), + .clk (nodiv_mclk), + .rst (puc_rst) +); +`else + assign mclk_wkup_s = 1'b0; +`endif + + +// Clock Divider +//---------------------------- +// No need for extra synchronizer as bcsctl2 +// comes from the same clock domain. + +`ifdef CPUOFF_EN +wire mclk_active = mclk_enable | mclk_wkup_s | (dbg_en_s & cpu_en_s); +`else +wire mclk_active = 1'b1; +`endif + +`ifdef MCLK_DIVIDER +reg [2:0] mclk_div; +always @ (posedge nodiv_mclk or posedge puc_rst) + if (puc_rst) mclk_div <= 3'h0; + else if ((bcsctl2[`DIVMx]!=2'b00)) mclk_div <= mclk_div+3'h1; + + wire mclk_div_en = mclk_active & ((bcsctl2[`DIVMx]==2'b00) ? 1'b1 : + (bcsctl2[`DIVMx]==2'b01) ? mclk_div[0] : + (bcsctl2[`DIVMx]==2'b10) ? &mclk_div[1:0] : + &mclk_div[2:0]); +`else + wire mclk_div_en = mclk_active; +`endif + + +// Generate main system clock +//---------------------------- +`ifdef MCLK_CGATE + +omsp_clock_gate clock_gate_mclk ( + .gclk (mclk), + .clk (nodiv_mclk), + .enable (mclk_div_en), + .scan_enable (scan_enable) +); +`else + assign mclk = nodiv_mclk; +`endif + + +//----------------------------------------------------------- +// 6.3) ACLK GENERATION +//----------------------------------------------------------- + +// ASIC MODE +//---------------------------- +`ifdef ASIC + + `ifdef ACLK_DIVIDER + `ifdef LFXT_DOMAIN + + wire nodiv_aclk = lfxt_clk; + + // Local Reset synchronizer + wire puc_lfxt_rst; + wire puc_lfxt_noscan_n; + omsp_sync_cell sync_cell_puc_lfxt ( + .data_out (puc_lfxt_noscan_n), + .data_in (1'b1), + .clk (nodiv_aclk), + .rst (puc_rst) + ); + omsp_scan_mux scan_mux_puc_lfxt ( + .scan_mode (scan_mode), + .data_in_scan (por_a), + .data_in_func (~puc_lfxt_noscan_n), + .data_out (puc_lfxt_rst) + ); + + // Local synchronizer for the bcsctl1.DIVAx configuration + // (note that we can live with a full bus synchronizer as + // it won't hurt if we get a wrong DIVAx value for a single clock cycle) + reg [1:0] divax_s; + reg [1:0] divax_ss; + always @ (posedge nodiv_aclk or posedge puc_lfxt_rst) + if (puc_lfxt_rst) + begin + divax_s <= 2'h0; + divax_ss <= 2'h0; + end + else + begin + divax_s <= bcsctl1[`DIVAx]; + divax_ss <= divax_s; + end + + // If the OSCOFF mode is enabled synchronize OSCOFF signal + wire oscoff_s; + `ifdef OSCOFF_EN + omsp_sync_cell sync_cell_oscoff ( + .data_out (oscoff_s), + .data_in (oscoff), + .clk (nodiv_aclk), + .rst (puc_lfxt_rst) + ); + `else + assign oscoff_s = 1'b0; + `endif + `else + wire puc_lfxt_rst = puc_rst; + wire nodiv_aclk = dco_clk; + wire [1:0] divax_ss = bcsctl1[`DIVAx]; + wire oscoff_s = oscoff; + `endif + + // Divider + reg [2:0] aclk_div; + always @ (posedge nodiv_aclk or posedge puc_lfxt_rst) + if (puc_lfxt_rst) aclk_div <= 3'h0; + else if ((divax_ss!=2'b00)) aclk_div <= aclk_div+3'h1; + + wire aclk_div_en = cpu_en_aux_s & ~oscoff_s & ((divax_ss==2'b00) ? 1'b1 : + (divax_ss==2'b01) ? aclk_div[0] : + (divax_ss==2'b10) ? &aclk_div[1:0] : + &aclk_div[2:0]); + + // Clock gate + omsp_clock_gate clock_gate_aclk ( + .gclk (aclk), + .clk (nodiv_aclk), + .enable (aclk_div_en), + .scan_enable (scan_enable) + ); + + `else + `ifdef LFXT_DOMAIN + assign aclk = lfxt_clk; + `else + assign aclk = dco_clk; + `endif + `endif + + + assign aclk_en = 1'b1; + + +// FPGA MODE +//---------------------------- +`else + reg aclk_en; + reg [2:0] aclk_div; + wire aclk_en_nxt = lfxt_clk_en & ((bcsctl1[`DIVAx]==2'b00) ? 1'b1 : + (bcsctl1[`DIVAx]==2'b01) ? aclk_div[0] : + (bcsctl1[`DIVAx]==2'b10) ? &aclk_div[1:0] : + &aclk_div[2:0]); + + always @ (posedge mclk or posedge puc_rst) + if (puc_rst) aclk_div <= 3'h0; + else if ((bcsctl1[`DIVAx]!=2'b00) & lfxt_clk_en) aclk_div <= aclk_div+3'h1; + + always @ (posedge mclk or posedge puc_rst) + if (puc_rst) aclk_en <= 1'b0; + else aclk_en <= aclk_en_nxt & cpu_en_s; + + assign aclk = mclk; +`endif + +//----------------------------------------------------------- +// 6.4) SMCLK GENERATION +//----------------------------------------------------------- + +// Clock MUX +//---------------------------- +`ifdef SMCLK_MUX +omsp_clock_mux clock_mux_smclk ( + .clk_out (nodiv_smclk), + .clk_in0 (dco_clk), + .clk_in1 (lfxt_clk), + .reset (por), + .scan_mode (scan_mode), + .select (bcsctl2[`SELS]) +); +`else +assign nodiv_smclk = dco_clk; +`endif + + +// ASIC MODE +//---------------------------- +`ifdef ASIC + `ifdef SMCLK_MUX + + // Synchronizers + //------------------------------------------------------ + // When the SMCLK MUX is enabled, the reset and DIVSx + // and SCG1 signals must be synchronized, otherwise not. + + // Local Reset synchronizer + wire puc_sm_noscan_n; + wire puc_sm_rst; + omsp_sync_cell sync_cell_puc_sm ( + .data_out (puc_sm_noscan_n), + .data_in (1'b1), + .clk (nodiv_smclk), + .rst (puc_rst) + ); + omsp_scan_mux scan_mux_puc_sm ( + .scan_mode (scan_mode), + .data_in_scan (por_a), + .data_in_func (~puc_sm_noscan_n), + .data_out (puc_sm_rst) + ); + + // SCG1 synchronizer + `ifdef SCG1_EN + wire scg1_s; + omsp_sync_cell sync_cell_scg1 ( + .data_out (scg1_s), + .data_in (scg1), + .clk (nodiv_smclk), + .rst (puc_sm_rst) + ); + `else + wire scg1_s = 1'b0; + `endif + + `ifdef SMCLK_DIVIDER + // Local synchronizer for the bcsctl2.DIVSx configuration + // (note that we can live with a full bus synchronizer as + // it won't hurt if we get a wrong DIVSx value for a single clock cycle) + reg [1:0] divsx_s; + reg [1:0] divsx_ss; + always @ (posedge nodiv_smclk or posedge puc_sm_rst) + if (puc_sm_rst) + begin + divsx_s <= 2'h0; + divsx_ss <= 2'h0; + end + else + begin + divsx_s <= bcsctl2[`DIVSx]; + divsx_ss <= divsx_s; + end + `endif + + `else + + wire puc_sm_rst = puc_rst; + wire [1:0] divsx_ss = bcsctl2[`DIVSx]; + wire scg1_s = scg1; + `endif + + + + // Clock Divider + //---------------------------- + `ifdef SMCLK_DIVIDER + + reg [2:0] smclk_div; + always @ (posedge nodiv_smclk or posedge puc_sm_rst) + if (puc_sm_rst) smclk_div <= 3'h0; + else if ((divsx_ss!=2'b00)) smclk_div <= smclk_div+3'h1; + + wire smclk_div_en = cpu_en_sm_s & ~scg1_s & ((divsx_ss==2'b00) ? 1'b1 : + (divsx_ss==2'b01) ? smclk_div[0] : + (divsx_ss==2'b10) ? &smclk_div[1:0] : + &smclk_div[2:0]); + `else + `ifdef SCG1_EN + wire smclk_div_en = cpu_en_sm_s & ~scg1_s; + `else + wire smclk_div_en = cpu_en_sm_s; + `endif + `endif + + + // Generate sub-system clock + //---------------------------- + `ifdef SMCLK_CGATE + omsp_clock_gate clock_gate_smclk ( + .gclk (smclk), + .clk (nodiv_smclk), + .enable (smclk_div_en), + .scan_enable (scan_enable) + ); + `else + assign smclk = nodiv_smclk; + `endif + + assign smclk_en = 1'b1; + + +// FPGA MODE +//---------------------------- +`else +reg smclk_en; +reg [2:0] smclk_div; + +wire smclk_in = ~scg1 & (bcsctl2[`SELS] ? lfxt_clk_en : 1'b1); + +wire smclk_en_nxt = smclk_in & ((bcsctl2[`DIVSx]==2'b00) ? 1'b1 : + (bcsctl2[`DIVSx]==2'b01) ? smclk_div[0] : + (bcsctl2[`DIVSx]==2'b10) ? &smclk_div[1:0] : + &smclk_div[2:0]); + +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) smclk_en <= 1'b0; + else smclk_en <= smclk_en_nxt & cpu_en_s; + +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) smclk_div <= 3'h0; + else if ((bcsctl2[`DIVSx]!=2'b00) & smclk_in) smclk_div <= smclk_div+3'h1; + +wire smclk = mclk; + +`endif + +//----------------------------------------------------------- +// 6.5) DEBUG INTERFACE CLOCK GENERATION (DBG_CLK) +//----------------------------------------------------------- + +// Synchronize DBG_EN signal to MCLK domain +//------------------------------------------ +`ifdef DBG_EN +`ifdef SYNC_DBG_EN + wire dbg_en_n_s; + omsp_sync_cell sync_cell_dbg_en ( + .data_out (dbg_en_n_s), + .data_in (~dbg_en), + .clk (mclk), + .rst (por) + ); + assign dbg_en_s = ~dbg_en_n_s; + wire dbg_rst_nxt = dbg_en_n_s; +`else + assign dbg_en_s = dbg_en; + wire dbg_rst_nxt = ~dbg_en; +`endif +`else + assign dbg_en_s = 1'b0; + wire dbg_rst_nxt = 1'b0; +`endif + + +// Serial Debug Interface Clock gate +//------------------------------------------------ +`ifdef DBG_EN + `ifdef ASIC + omsp_clock_gate clock_gate_dbg_clk ( + .gclk (dbg_clk), + .clk (mclk), + .enable (dbg_en_s), + .scan_enable (scan_enable) + ); + `else + assign dbg_clk = dco_clk; + `endif +`else + assign dbg_clk = 1'b0; +`endif + + +//============================================================================= +// 7) RESET GENERATION +//============================================================================= +// +// Whenever the reset pin (reset_n) is deasserted, the internal resets of the +// openMSP430 will be released in the following order: +// 1- POR +// 2- DBG_RST (if the sdi interface is enabled, i.e. dbg_en=1) +// 3- PUC +// +// Note: releasing the DBG_RST before PUC is particularly important in order +// to allow the sdi interface to halt the cpu immediately after a PUC. +// + +// Generate synchronized POR to MCLK domain +//------------------------------------------ + +// Asynchronous reset source +assign por_a = !reset_n; +wire por_noscan; + +// Reset Synchronizer +omsp_sync_reset sync_reset_por ( + .rst_s (por_noscan), + .clk (nodiv_mclk), + .rst_a (por_a) +); + +// Scan Reset Mux +`ifdef ASIC +omsp_scan_mux scan_mux_por ( + .scan_mode (scan_mode), + .data_in_scan (por_a), + .data_in_func (por_noscan), + .data_out (por) +); +`else + assign por = por_noscan; +`endif + +// Generate synchronized reset for the SDI +//------------------------------------------ +`ifdef DBG_EN + +// Reset Generation +reg dbg_rst_noscan; +always @ (posedge mclk or posedge por) + if (por) dbg_rst_noscan <= 1'b1; + else dbg_rst_noscan <= dbg_rst_nxt; + + // Scan Reset Mux + `ifdef ASIC + omsp_scan_mux scan_mux_dbg_rst ( + .scan_mode (scan_mode), + .data_in_scan (por_a), + .data_in_func (dbg_rst_noscan), + .data_out (dbg_rst) + ); + `else + assign dbg_rst = dbg_rst_noscan; + `endif + +`else + wire dbg_rst_noscan = 1'b1; + assign dbg_rst = 1'b1; +`endif + + +// Generate main system reset (PUC_RST) +//-------------------------------------- +wire puc_noscan_n; +wire puc_a_scan; + +// Asynchronous PUC reset +wire puc_a = por | wdt_reset; + +// Synchronous PUC reset +wire puc_s = dbg_cpu_reset | // With the debug interface command + + (dbg_en_s & dbg_rst_noscan & ~puc_noscan_n); // Sequencing making sure PUC is released + // after DBG_RST if the debug interface is + // enabled at power-on-reset time +// Scan Reset Mux +`ifdef ASIC +omsp_scan_mux scan_mux_puc_rst_a ( + .scan_mode (scan_mode), + .data_in_scan (por_a), + .data_in_func (puc_a), + .data_out (puc_a_scan) +); +`else + assign puc_a_scan = puc_a; +`endif + +// Reset Synchronizer +// (required because of the asynchronous watchdog reset) +omsp_sync_cell sync_cell_puc ( + .data_out (puc_noscan_n), + .data_in (~puc_s), + .clk (mclk), + .rst (puc_a_scan) +); + +// Scan Reset Mux +`ifdef ASIC +omsp_scan_mux scan_mux_puc_rst ( + .scan_mode (scan_mode), + .data_in_scan (por_a), + .data_in_func (~puc_noscan_n), + .data_out (puc_rst) +); +`else + assign puc_rst = ~puc_noscan_n; +`endif + +// PUC pending set the serial debug interface +assign puc_pnd_set = ~puc_noscan_n; + + +endmodule // omsp_clock_module + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif diff --git a/tests/openmsp430/rtl/omsp_clock_mux.v b/tests/openmsp430/rtl/omsp_clock_mux.v new file mode 100644 index 00000000..5f8406ad --- /dev/null +++ b/tests/openmsp430/rtl/omsp_clock_mux.v @@ -0,0 +1,192 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_clock_mux.v +// +// *Module Description: +// Standard clock mux for the openMSP430 +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 103 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $ +//---------------------------------------------------------------------------- + +module omsp_clock_mux ( + +// OUTPUTs + clk_out, // Clock output + +// INPUTs + clk_in0, // Clock input 0 + clk_in1, // Clock input 1 + reset, // Reset + scan_mode, // Scan mode (clk_in0 is selected in scan mode) + select // Clock selection +); + +// OUTPUTs +//========= +output clk_out; // Clock output + +// INPUTs +//========= +input clk_in0; // Clock input 0 +input clk_in1; // Clock input 1 +input reset; // Reset +input scan_mode; // Scan mode (clk_in0 is selected in scan mode) +input select; // Clock selection + + +//===========================================================================================================================// +// 1) CLOCK MUX // +//===========================================================================================================================// +// // +// The following (glitch free) clock mux is implemented as following: // +// // +// // +// // +// // +// +-----. +--------+ +--------+ // +// select >>----+-------------O| \ | | | | +-----. // +// | | |---| D Q |---| D Q |--+-------| \ // +// | +-------O| / | | | | | | |O-+ // +// | | +-----' | | | | | +--O| / | // +// | | | /\ | | /\ | | | +-----' | // +// | | +--+--+--+ +--+--+--+ | | | // +// | | O | | | | // +// | | | | | | | +-----. // +// clk_in0 >>----------------------------------+------------+-----------+ +--| \ // +// | | | | |----<< clk_out // +// | | +---------------------------------------+ +--| / // +// | | | | +-----' // +// | +---------------------------------------------+ | // +// | | | | // +// | | +-----. +--------+ +--------+ | | // +// | +-O| \ | | | | | +-----. | // +// | | |---| D Q |---| D Q |--+-------| \ | // +// +--------------| / | | | | | |O-+ // +// +-----' | | | | +--O| / // +// | /\ | | /\ | | +-----' // +// +--+--+--+ +--+--+--+ | // +// O | | // +// | | | // +// clk_in1 >>----------------------------------+------------+-----------+ // +// // +// // +//===========================================================================================================================// + +//----------------------------------------------------------------------------- +// Wire declarations +//----------------------------------------------------------------------------- + +wire in0_select; +reg in0_select_s; +reg in0_select_ss; +wire in0_enable; + +wire in1_select; +reg in1_select_s; +reg in1_select_ss; +wire in1_enable; + +wire clk_in0_inv; +wire clk_in1_inv; +wire gated_clk_in0; +wire gated_clk_in1; + + +//----------------------------------------------------------------------------- +// CLK_IN0 Selection +//----------------------------------------------------------------------------- + +assign in0_select = ~select & ~in1_select_ss; + +always @ (posedge clk_in0_inv or posedge reset) + if (reset) in0_select_s <= 1'b1; + else in0_select_s <= in0_select; + +always @ (posedge clk_in0 or posedge reset) + if (reset) in0_select_ss <= 1'b1; + else in0_select_ss <= in0_select_s; + +assign in0_enable = in0_select_ss | scan_mode; + + +//----------------------------------------------------------------------------- +// CLK_IN1 Selection +//----------------------------------------------------------------------------- + +assign in1_select = select & ~in0_select_ss; + +always @ (posedge clk_in1_inv or posedge reset) + if (reset) in1_select_s <= 1'b0; + else in1_select_s <= in1_select; + +always @ (posedge clk_in1 or posedge reset) + if (reset) in1_select_ss <= 1'b0; + else in1_select_ss <= in1_select_s; + +assign in1_enable = in1_select_ss & ~scan_mode; + + +//----------------------------------------------------------------------------- +// Clock MUX +//----------------------------------------------------------------------------- +// +// IMPORTANT NOTE: +// Because the clock network is a critical part of the design, +// the following combinatorial logic should be replaced with +// direct instanciation of standard cells from target library. +// Don't forget the "dont_touch" attribute to make sure +// synthesis won't mess it up. +// + +// Replace with standard cell INVERTER +assign clk_in0_inv = ~clk_in0; +assign clk_in1_inv = ~clk_in1; + + +// Replace with standard cell NAND2 +assign gated_clk_in0 = ~(clk_in0_inv & in0_enable); +assign gated_clk_in1 = ~(clk_in1_inv & in1_enable); + + +// Replace with standard cell AND2 +assign clk_out = (gated_clk_in0 & gated_clk_in1); + + + +endmodule // omsp_clock_gate + + + diff --git a/tests/openmsp430/rtl/omsp_dbg.v b/tests/openmsp430/rtl/omsp_dbg.v new file mode 100644 index 00000000..97e9ede4 --- /dev/null +++ b/tests/openmsp430/rtl/omsp_dbg.v @@ -0,0 +1,827 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_dbg.v +// +// *Module Description: +// Debug interface +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 149 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2012-07-19 22:21:12 +0200 (Thu, 19 Jul 2012) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module omsp_dbg ( + +// OUTPUTs + dbg_freeze, // Freeze peripherals + dbg_halt_cmd, // Halt CPU command + dbg_mem_addr, // Debug address for rd/wr access + dbg_mem_dout, // Debug unit data output + dbg_mem_en, // Debug unit memory enable + dbg_mem_wr, // Debug unit memory write + dbg_reg_wr, // Debug unit CPU register write + dbg_cpu_reset, // Reset CPU from debug interface + dbg_uart_txd, // Debug interface: UART TXD + +// INPUTs + cpu_en_s, // Enable CPU code execution (synchronous) + cpu_id, // CPU ID + dbg_clk, // Debug unit clock + dbg_en_s, // Debug interface enable (synchronous) + dbg_halt_st, // Halt/Run status from CPU + dbg_mem_din, // Debug unit Memory data input + dbg_reg_din, // Debug unit CPU register data input + dbg_rst, // Debug unit reset + dbg_uart_rxd, // Debug interface: UART RXD (asynchronous) + decode_noirq, // Frontend decode instruction + eu_mab, // Execution-Unit Memory address bus + eu_mb_en, // Execution-Unit Memory bus enable + eu_mb_wr, // Execution-Unit Memory bus write transfer + eu_mdb_in, // Memory data bus input + eu_mdb_out, // Memory data bus output + exec_done, // Execution completed + fe_mb_en, // Frontend Memory bus enable + fe_mdb_in, // Frontend Memory data bus input + pc, // Program counter + puc_pnd_set // PUC pending set for the serial debug interface +); + +// OUTPUTs +//========= +output dbg_freeze; // Freeze peripherals +output dbg_halt_cmd; // Halt CPU command +output [15:0] dbg_mem_addr; // Debug address for rd/wr access +output [15:0] dbg_mem_dout; // Debug unit data output +output dbg_mem_en; // Debug unit memory enable +output [1:0] dbg_mem_wr; // Debug unit memory write +output dbg_reg_wr; // Debug unit CPU register write +output dbg_cpu_reset; // Reset CPU from debug interface +output dbg_uart_txd; // Debug interface: UART TXD + +// INPUTs +//========= +input cpu_en_s; // Enable CPU code execution (synchronous) +input [31:0] cpu_id; // CPU ID +input dbg_clk; // Debug unit clock +input dbg_en_s; // Debug interface enable (synchronous) +input dbg_halt_st; // Halt/Run status from CPU +input [15:0] dbg_mem_din; // Debug unit Memory data input +input [15:0] dbg_reg_din; // Debug unit CPU register data input +input dbg_rst; // Debug unit reset +input dbg_uart_rxd; // Debug interface: UART RXD (asynchronous) +input decode_noirq; // Frontend decode instruction +input [15:0] eu_mab; // Execution-Unit Memory address bus +input eu_mb_en; // Execution-Unit Memory bus enable +input [1:0] eu_mb_wr; // Execution-Unit Memory bus write transfer +input [15:0] eu_mdb_in; // Memory data bus input +input [15:0] eu_mdb_out; // Memory data bus output +input exec_done; // Execution completed +input fe_mb_en; // Frontend Memory bus enable +input [15:0] fe_mdb_in; // Frontend Memory data bus input +input [15:0] pc; // Program counter +input puc_pnd_set; // PUC pending set for the serial debug interface + + +//============================================================================= +// 1) WIRE & PARAMETER DECLARATION +//============================================================================= + +// Diverse wires and registers +wire [5:0] dbg_addr; +wire [15:0] dbg_din; +wire dbg_wr; +reg mem_burst; +wire dbg_reg_rd; +wire dbg_mem_rd; +reg dbg_mem_rd_dly; +wire dbg_swbrk; +wire dbg_rd; +reg dbg_rd_rdy; +wire mem_burst_rd; +wire mem_burst_wr; +wire brk0_halt; +wire brk0_pnd; +wire [15:0] brk0_dout; +wire brk1_halt; +wire brk1_pnd; +wire [15:0] brk1_dout; +wire brk2_halt; +wire brk2_pnd; +wire [15:0] brk2_dout; +wire brk3_halt; +wire brk3_pnd; +wire [15:0] brk3_dout; + +// Number of registers +parameter NR_REG = 24; + +// Register addresses +parameter CPU_ID_LO = 6'h00; +parameter CPU_ID_HI = 6'h01; +parameter CPU_CTL = 6'h02; +parameter CPU_STAT = 6'h03; +parameter MEM_CTL = 6'h04; +parameter MEM_ADDR = 6'h05; +parameter MEM_DATA = 6'h06; +parameter MEM_CNT = 6'h07; +`ifdef DBG_HWBRK_0 +parameter BRK0_CTL = 6'h08; +parameter BRK0_STAT = 6'h09; +parameter BRK0_ADDR0 = 6'h0A; +parameter BRK0_ADDR1 = 6'h0B; +`endif +`ifdef DBG_HWBRK_1 +parameter BRK1_CTL = 6'h0C; +parameter BRK1_STAT = 6'h0D; +parameter BRK1_ADDR0 = 6'h0E; +parameter BRK1_ADDR1 = 6'h0F; +`endif +`ifdef DBG_HWBRK_2 +parameter BRK2_CTL = 6'h10; +parameter BRK2_STAT = 6'h11; +parameter BRK2_ADDR0 = 6'h12; +parameter BRK2_ADDR1 = 6'h13; +`endif +`ifdef DBG_HWBRK_3 +parameter BRK3_CTL = 6'h14; +parameter BRK3_STAT = 6'h15; +parameter BRK3_ADDR0 = 6'h16; +parameter BRK3_ADDR1 = 6'h17; +`endif + +// Register one-hot decoder +parameter BASE_D = {{NR_REG-1{1'b0}}, 1'b1}; +parameter CPU_ID_LO_D = (BASE_D << CPU_ID_LO); +parameter CPU_ID_HI_D = (BASE_D << CPU_ID_HI); +parameter CPU_CTL_D = (BASE_D << CPU_CTL); +parameter CPU_STAT_D = (BASE_D << CPU_STAT); +parameter MEM_CTL_D = (BASE_D << MEM_CTL); +parameter MEM_ADDR_D = (BASE_D << MEM_ADDR); +parameter MEM_DATA_D = (BASE_D << MEM_DATA); +parameter MEM_CNT_D = (BASE_D << MEM_CNT); +`ifdef DBG_HWBRK_0 +parameter BRK0_CTL_D = (BASE_D << BRK0_CTL); +parameter BRK0_STAT_D = (BASE_D << BRK0_STAT); +parameter BRK0_ADDR0_D = (BASE_D << BRK0_ADDR0); +parameter BRK0_ADDR1_D = (BASE_D << BRK0_ADDR1); +`endif +`ifdef DBG_HWBRK_1 +parameter BRK1_CTL_D = (BASE_D << BRK1_CTL); +parameter BRK1_STAT_D = (BASE_D << BRK1_STAT); +parameter BRK1_ADDR0_D = (BASE_D << BRK1_ADDR0); +parameter BRK1_ADDR1_D = (BASE_D << BRK1_ADDR1); +`endif +`ifdef DBG_HWBRK_2 +parameter BRK2_CTL_D = (BASE_D << BRK2_CTL); +parameter BRK2_STAT_D = (BASE_D << BRK2_STAT); +parameter BRK2_ADDR0_D = (BASE_D << BRK2_ADDR0); +parameter BRK2_ADDR1_D = (BASE_D << BRK2_ADDR1); +`endif +`ifdef DBG_HWBRK_3 +parameter BRK3_CTL_D = (BASE_D << BRK3_CTL); +parameter BRK3_STAT_D = (BASE_D << BRK3_STAT); +parameter BRK3_ADDR0_D = (BASE_D << BRK3_ADDR0); +parameter BRK3_ADDR1_D = (BASE_D << BRK3_ADDR1); +`endif + + +//============================================================================ +// 2) REGISTER DECODER +//============================================================================ + +// Select Data register during a burst +wire [5:0] dbg_addr_in = mem_burst ? MEM_DATA : dbg_addr; + +// Register address decode +reg [NR_REG-1:0] reg_dec; +always @(dbg_addr_in) + case (dbg_addr_in) + CPU_ID_LO : reg_dec = CPU_ID_LO_D; + CPU_ID_HI : reg_dec = CPU_ID_HI_D; + CPU_CTL : reg_dec = CPU_CTL_D; + CPU_STAT : reg_dec = CPU_STAT_D; + MEM_CTL : reg_dec = MEM_CTL_D; + MEM_ADDR : reg_dec = MEM_ADDR_D; + MEM_DATA : reg_dec = MEM_DATA_D; + MEM_CNT : reg_dec = MEM_CNT_D; +`ifdef DBG_HWBRK_0 + BRK0_CTL : reg_dec = BRK0_CTL_D; + BRK0_STAT : reg_dec = BRK0_STAT_D; + BRK0_ADDR0: reg_dec = BRK0_ADDR0_D; + BRK0_ADDR1: reg_dec = BRK0_ADDR1_D; +`endif +`ifdef DBG_HWBRK_1 + BRK1_CTL : reg_dec = BRK1_CTL_D; + BRK1_STAT : reg_dec = BRK1_STAT_D; + BRK1_ADDR0: reg_dec = BRK1_ADDR0_D; + BRK1_ADDR1: reg_dec = BRK1_ADDR1_D; +`endif +`ifdef DBG_HWBRK_2 + BRK2_CTL : reg_dec = BRK2_CTL_D; + BRK2_STAT : reg_dec = BRK2_STAT_D; + BRK2_ADDR0: reg_dec = BRK2_ADDR0_D; + BRK2_ADDR1: reg_dec = BRK2_ADDR1_D; +`endif +`ifdef DBG_HWBRK_3 + BRK3_CTL : reg_dec = BRK3_CTL_D; + BRK3_STAT : reg_dec = BRK3_STAT_D; + BRK3_ADDR0: reg_dec = BRK3_ADDR0_D; + BRK3_ADDR1: reg_dec = BRK3_ADDR1_D; +`endif + // pragma coverage off + default: reg_dec = {NR_REG{1'b0}}; + // pragma coverage on + endcase + +// Read/Write probes +wire reg_write = dbg_wr; +wire reg_read = 1'b1; + +// Read/Write vectors +wire [NR_REG-1:0] reg_wr = reg_dec & {NR_REG{reg_write}}; +wire [NR_REG-1:0] reg_rd = reg_dec & {NR_REG{reg_read}}; + + +//============================================================================= +// 3) REGISTER: CORE INTERFACE +//============================================================================= + +// CPU_ID Register +//----------------- +// ------------------------------------------------------------------- +// CPU_ID_LO: | 15 14 13 12 11 10 9 | 8 7 6 5 4 | 3 | 2 1 0 | +// |----------------------------+-----------------+------+-------------| +// | PER_SPACE | USER_VERSION | ASIC | CPU_VERSION | +// -------------------------------------------------------------------- +// CPU_ID_HI: | 15 14 13 12 11 10 | 9 8 7 6 5 4 3 2 1 | 0 | +// |----------------------------+-------------------------------+------| +// | PMEM_SIZE | DMEM_SIZE | MPY | +// ------------------------------------------------------------------- + +// This register is assigned in the SFR module + + +// CPU_CTL Register +//----------------------------------------------------------------------------- +// 7 6 5 4 3 2 1 0 +// Reserved CPU_RST RST_BRK_EN FRZ_BRK_EN SW_BRK_EN ISTEP RUN HALT +//----------------------------------------------------------------------------- +reg [6:3] cpu_ctl; + +wire cpu_ctl_wr = reg_wr[CPU_CTL]; + +always @ (posedge dbg_clk or posedge dbg_rst) +`ifdef DBG_RST_BRK_EN + if (dbg_rst) cpu_ctl <= 4'h6; +`else + if (dbg_rst) cpu_ctl <= 4'h2; +`endif + else if (cpu_ctl_wr) cpu_ctl <= dbg_din[6:3]; + +wire [7:0] cpu_ctl_full = {1'b0, cpu_ctl, 3'b000}; + +wire halt_cpu = cpu_ctl_wr & dbg_din[`HALT] & ~dbg_halt_st; +wire run_cpu = cpu_ctl_wr & dbg_din[`RUN] & dbg_halt_st; +wire istep = cpu_ctl_wr & dbg_din[`ISTEP] & dbg_halt_st; + + +// CPU_STAT Register +//------------------------------------------------------------------------------------ +// 7 6 5 4 3 2 1 0 +// HWBRK3_PND HWBRK2_PND HWBRK1_PND HWBRK0_PND SWBRK_PND PUC_PND Res. HALT_RUN +//------------------------------------------------------------------------------------ +reg [3:2] cpu_stat; + +wire cpu_stat_wr = reg_wr[CPU_STAT]; +wire [3:2] cpu_stat_set = {dbg_swbrk, puc_pnd_set}; +wire [3:2] cpu_stat_clr = ~dbg_din[3:2]; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) cpu_stat <= 2'b00; + else if (cpu_stat_wr) cpu_stat <= ((cpu_stat & cpu_stat_clr) | cpu_stat_set); + else cpu_stat <= (cpu_stat | cpu_stat_set); + +wire [7:0] cpu_stat_full = {brk3_pnd, brk2_pnd, brk1_pnd, brk0_pnd, + cpu_stat, 1'b0, dbg_halt_st}; + + +//============================================================================= +// 4) REGISTER: MEMORY INTERFACE +//============================================================================= + +// MEM_CTL Register +//----------------------------------------------------------------------------- +// 7 6 5 4 3 2 1 0 +// Reserved B/W MEM/REG RD/WR START +// +// START : - 0 : Do nothing. +// - 1 : Initiate memory transfer. +// +// RD/WR : - 0 : Read access. +// - 1 : Write access. +// +// MEM/REG: - 0 : Memory access. +// - 1 : CPU Register access. +// +// B/W : - 0 : 16 bit access. +// - 1 : 8 bit access (not valid for CPU Registers). +// +//----------------------------------------------------------------------------- +reg [3:1] mem_ctl; + +wire mem_ctl_wr = reg_wr[MEM_CTL]; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) mem_ctl <= 3'h0; + else if (mem_ctl_wr) mem_ctl <= dbg_din[3:1]; + +wire [7:0] mem_ctl_full = {4'b0000, mem_ctl, 1'b0}; + +reg mem_start; +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) mem_start <= 1'b0; + else mem_start <= mem_ctl_wr & dbg_din[0]; + +wire mem_bw = mem_ctl[3]; + +// MEM_DATA Register +//------------------ +reg [15:0] mem_data; +reg [15:0] mem_addr; +wire mem_access; + +wire mem_data_wr = reg_wr[MEM_DATA]; + +wire [15:0] dbg_mem_din_bw = ~mem_bw ? dbg_mem_din : + mem_addr[0] ? {8'h00, dbg_mem_din[15:8]} : + {8'h00, dbg_mem_din[7:0]}; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) mem_data <= 16'h0000; + else if (mem_data_wr) mem_data <= dbg_din; + else if (dbg_reg_rd) mem_data <= dbg_reg_din; + else if (dbg_mem_rd_dly) mem_data <= dbg_mem_din_bw; + + +// MEM_ADDR Register +//------------------ +reg [15:0] mem_cnt; + +wire mem_addr_wr = reg_wr[MEM_ADDR]; +wire dbg_mem_acc = (|dbg_mem_wr | (dbg_rd_rdy & ~mem_ctl[2])); +wire dbg_reg_acc = ( dbg_reg_wr | (dbg_rd_rdy & mem_ctl[2])); + +wire [15:0] mem_addr_inc = (mem_cnt==16'h0000) ? 16'h0000 : + (dbg_mem_acc & ~mem_bw) ? 16'h0002 : + (dbg_mem_acc | dbg_reg_acc) ? 16'h0001 : 16'h0000; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) mem_addr <= 16'h0000; + else if (mem_addr_wr) mem_addr <= dbg_din; + else mem_addr <= mem_addr + mem_addr_inc; + +// MEM_CNT Register +//------------------ + +wire mem_cnt_wr = reg_wr[MEM_CNT]; + +wire [15:0] mem_cnt_dec = (mem_cnt==16'h0000) ? 16'h0000 : + (mem_burst & (dbg_mem_acc | dbg_reg_acc)) ? 16'hffff : 16'h0000; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) mem_cnt <= 16'h0000; + else if (mem_cnt_wr) mem_cnt <= dbg_din; + else mem_cnt <= mem_cnt + mem_cnt_dec; + + +//============================================================================= +// 5) BREAKPOINTS / WATCHPOINTS +//============================================================================= + +`ifdef DBG_HWBRK_0 +// Hardware Breakpoint/Watchpoint Register read select +wire [3:0] brk0_reg_rd = {reg_rd[BRK0_ADDR1], + reg_rd[BRK0_ADDR0], + reg_rd[BRK0_STAT], + reg_rd[BRK0_CTL]}; + +// Hardware Breakpoint/Watchpoint Register write select +wire [3:0] brk0_reg_wr = {reg_wr[BRK0_ADDR1], + reg_wr[BRK0_ADDR0], + reg_wr[BRK0_STAT], + reg_wr[BRK0_CTL]}; + +omsp_dbg_hwbrk dbg_hwbr_0 ( + +// OUTPUTs + .brk_halt (brk0_halt), // Hardware breakpoint command + .brk_pnd (brk0_pnd), // Hardware break/watch-point pending + .brk_dout (brk0_dout), // Hardware break/watch-point register data input + +// INPUTs + .brk_reg_rd (brk0_reg_rd), // Hardware break/watch-point register read select + .brk_reg_wr (brk0_reg_wr), // Hardware break/watch-point register write select + .dbg_clk (dbg_clk), // Debug unit clock + .dbg_din (dbg_din), // Debug register data input + .dbg_rst (dbg_rst), // Debug unit reset + .eu_mab (eu_mab), // Execution-Unit Memory address bus + .eu_mb_en (eu_mb_en), // Execution-Unit Memory bus enable + .eu_mb_wr (eu_mb_wr), // Execution-Unit Memory bus write transfer + .eu_mdb_in (eu_mdb_in), // Memory data bus input + .eu_mdb_out (eu_mdb_out), // Memory data bus output + .exec_done (exec_done), // Execution completed + .fe_mb_en (fe_mb_en), // Frontend Memory bus enable + .pc (pc) // Program counter +); + +`else +assign brk0_halt = 1'b0; +assign brk0_pnd = 1'b0; +assign brk0_dout = 16'h0000; +`endif + +`ifdef DBG_HWBRK_1 +// Hardware Breakpoint/Watchpoint Register read select +wire [3:0] brk1_reg_rd = {reg_rd[BRK1_ADDR1], + reg_rd[BRK1_ADDR0], + reg_rd[BRK1_STAT], + reg_rd[BRK1_CTL]}; + +// Hardware Breakpoint/Watchpoint Register write select +wire [3:0] brk1_reg_wr = {reg_wr[BRK1_ADDR1], + reg_wr[BRK1_ADDR0], + reg_wr[BRK1_STAT], + reg_wr[BRK1_CTL]}; + +omsp_dbg_hwbrk dbg_hwbr_1 ( + +// OUTPUTs + .brk_halt (brk1_halt), // Hardware breakpoint command + .brk_pnd (brk1_pnd), // Hardware break/watch-point pending + .brk_dout (brk1_dout), // Hardware break/watch-point register data input + +// INPUTs + .brk_reg_rd (brk1_reg_rd), // Hardware break/watch-point register read select + .brk_reg_wr (brk1_reg_wr), // Hardware break/watch-point register write select + .dbg_clk (dbg_clk), // Debug unit clock + .dbg_din (dbg_din), // Debug register data input + .dbg_rst (dbg_rst), // Debug unit reset + .eu_mab (eu_mab), // Execution-Unit Memory address bus + .eu_mb_en (eu_mb_en), // Execution-Unit Memory bus enable + .eu_mb_wr (eu_mb_wr), // Execution-Unit Memory bus write transfer + .eu_mdb_in (eu_mdb_in), // Memory data bus input + .eu_mdb_out (eu_mdb_out), // Memory data bus output + .exec_done (exec_done), // Execution completed + .fe_mb_en (fe_mb_en), // Frontend Memory bus enable + .pc (pc) // Program counter +); + +`else +assign brk1_halt = 1'b0; +assign brk1_pnd = 1'b0; +assign brk1_dout = 16'h0000; +`endif + + `ifdef DBG_HWBRK_2 +// Hardware Breakpoint/Watchpoint Register read select +wire [3:0] brk2_reg_rd = {reg_rd[BRK2_ADDR1], + reg_rd[BRK2_ADDR0], + reg_rd[BRK2_STAT], + reg_rd[BRK2_CTL]}; + +// Hardware Breakpoint/Watchpoint Register write select +wire [3:0] brk2_reg_wr = {reg_wr[BRK2_ADDR1], + reg_wr[BRK2_ADDR0], + reg_wr[BRK2_STAT], + reg_wr[BRK2_CTL]}; + +omsp_dbg_hwbrk dbg_hwbr_2 ( + +// OUTPUTs + .brk_halt (brk2_halt), // Hardware breakpoint command + .brk_pnd (brk2_pnd), // Hardware break/watch-point pending + .brk_dout (brk2_dout), // Hardware break/watch-point register data input + +// INPUTs + .brk_reg_rd (brk2_reg_rd), // Hardware break/watch-point register read select + .brk_reg_wr (brk2_reg_wr), // Hardware break/watch-point register write select + .dbg_clk (dbg_clk), // Debug unit clock + .dbg_din (dbg_din), // Debug register data input + .dbg_rst (dbg_rst), // Debug unit reset + .eu_mab (eu_mab), // Execution-Unit Memory address bus + .eu_mb_en (eu_mb_en), // Execution-Unit Memory bus enable + .eu_mb_wr (eu_mb_wr), // Execution-Unit Memory bus write transfer + .eu_mdb_in (eu_mdb_in), // Memory data bus input + .eu_mdb_out (eu_mdb_out), // Memory data bus output + .exec_done (exec_done), // Execution completed + .fe_mb_en (fe_mb_en), // Frontend Memory bus enable + .pc (pc) // Program counter +); + +`else +assign brk2_halt = 1'b0; +assign brk2_pnd = 1'b0; +assign brk2_dout = 16'h0000; +`endif + +`ifdef DBG_HWBRK_3 +// Hardware Breakpoint/Watchpoint Register read select +wire [3:0] brk3_reg_rd = {reg_rd[BRK3_ADDR1], + reg_rd[BRK3_ADDR0], + reg_rd[BRK3_STAT], + reg_rd[BRK3_CTL]}; + +// Hardware Breakpoint/Watchpoint Register write select +wire [3:0] brk3_reg_wr = {reg_wr[BRK3_ADDR1], + reg_wr[BRK3_ADDR0], + reg_wr[BRK3_STAT], + reg_wr[BRK3_CTL]}; + +omsp_dbg_hwbrk dbg_hwbr_3 ( + +// OUTPUTs + .brk_halt (brk3_halt), // Hardware breakpoint command + .brk_pnd (brk3_pnd), // Hardware break/watch-point pending + .brk_dout (brk3_dout), // Hardware break/watch-point register data input + +// INPUTs + .brk_reg_rd (brk3_reg_rd), // Hardware break/watch-point register read select + .brk_reg_wr (brk3_reg_wr), // Hardware break/watch-point register write select + .dbg_clk (dbg_clk), // Debug unit clock + .dbg_din (dbg_din), // Debug register data input + .dbg_rst (dbg_rst), // Debug unit reset + .eu_mab (eu_mab), // Execution-Unit Memory address bus + .eu_mb_en (eu_mb_en), // Execution-Unit Memory bus enable + .eu_mb_wr (eu_mb_wr), // Execution-Unit Memory bus write transfer + .eu_mdb_in (eu_mdb_in), // Memory data bus input + .eu_mdb_out (eu_mdb_out), // Memory data bus output + .exec_done (exec_done), // Execution completed + .fe_mb_en (fe_mb_en), // Frontend Memory bus enable + .pc (pc) // Program counter +); + +`else +assign brk3_halt = 1'b0; +assign brk3_pnd = 1'b0; +assign brk3_dout = 16'h0000; +`endif + + +//============================================================================ +// 6) DATA OUTPUT GENERATION +//============================================================================ + +wire [15:0] cpu_id_lo_rd = cpu_id[15:0] & {16{reg_rd[CPU_ID_LO]}}; +wire [15:0] cpu_id_hi_rd = cpu_id[31:16] & {16{reg_rd[CPU_ID_HI]}}; +wire [15:0] cpu_ctl_rd = {8'h00, cpu_ctl_full} & {16{reg_rd[CPU_CTL]}}; +wire [15:0] cpu_stat_rd = {8'h00, cpu_stat_full} & {16{reg_rd[CPU_STAT]}}; +wire [15:0] mem_ctl_rd = {8'h00, mem_ctl_full} & {16{reg_rd[MEM_CTL]}}; +wire [15:0] mem_data_rd = mem_data & {16{reg_rd[MEM_DATA]}}; +wire [15:0] mem_addr_rd = mem_addr & {16{reg_rd[MEM_ADDR]}}; +wire [15:0] mem_cnt_rd = mem_cnt & {16{reg_rd[MEM_CNT]}}; + +wire [15:0] dbg_dout = cpu_id_lo_rd | + cpu_id_hi_rd | + cpu_ctl_rd | + cpu_stat_rd | + mem_ctl_rd | + mem_data_rd | + mem_addr_rd | + mem_cnt_rd | + brk0_dout | + brk1_dout | + brk2_dout | + brk3_dout; + +// Tell UART/JTAG interface that the data is ready to be read +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) dbg_rd_rdy <= 1'b0; + else if (mem_burst | mem_burst_rd) dbg_rd_rdy <= (dbg_reg_rd | dbg_mem_rd_dly); + else dbg_rd_rdy <= dbg_rd; + + +//============================================================================ +// 7) CPU CONTROL +//============================================================================ + +// Reset CPU +//-------------------------- +wire dbg_cpu_reset = cpu_ctl[`CPU_RST]; + + +// Break after reset +//-------------------------- +wire halt_rst = cpu_ctl[`RST_BRK_EN] & dbg_en_s & puc_pnd_set; + + +// Freeze peripherals +//-------------------------- +wire dbg_freeze = dbg_halt_st & (cpu_ctl[`FRZ_BRK_EN] | ~cpu_en_s); + + +// Software break +//-------------------------- +assign dbg_swbrk = (fe_mdb_in==`DBG_SWBRK_OP) & decode_noirq & cpu_ctl[`SW_BRK_EN]; + + +// Single step +//-------------------------- +reg [1:0] inc_step; +always @(posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) inc_step <= 2'b00; + else if (istep) inc_step <= 2'b11; + else inc_step <= {inc_step[0], 1'b0}; + + +// Run / Halt +//-------------------------- +reg halt_flag; + +wire mem_halt_cpu; +wire mem_run_cpu; + +wire halt_flag_clr = run_cpu | mem_run_cpu; +wire halt_flag_set = halt_cpu | halt_rst | dbg_swbrk | mem_halt_cpu | + brk0_halt | brk1_halt | brk2_halt | brk3_halt; + +always @(posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) halt_flag <= 1'b0; + else if (halt_flag_clr) halt_flag <= 1'b0; + else if (halt_flag_set) halt_flag <= 1'b1; + +wire dbg_halt_cmd = (halt_flag | halt_flag_set) & ~inc_step[1]; + + +//============================================================================ +// 8) MEMORY CONTROL +//============================================================================ + +// Control Memory bursts +//------------------------------ + +wire mem_burst_start = (mem_start & |mem_cnt); +wire mem_burst_end = ((dbg_wr | dbg_rd_rdy) & ~|mem_cnt); + +// Detect when burst is on going +always @(posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) mem_burst <= 1'b0; + else if (mem_burst_start) mem_burst <= 1'b1; + else if (mem_burst_end) mem_burst <= 1'b0; + +// Control signals for UART/JTAG interface +assign mem_burst_rd = (mem_burst_start & ~mem_ctl[1]); +assign mem_burst_wr = (mem_burst_start & mem_ctl[1]); + +// Trigger CPU Register or memory access during a burst +reg mem_startb; +always @(posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) mem_startb <= 1'b0; + else mem_startb <= (mem_burst & (dbg_wr | dbg_rd)) | mem_burst_rd; + +// Combine single and burst memory start of sequence +wire mem_seq_start = ((mem_start & ~|mem_cnt) | mem_startb); + + +// Memory access state machine +//------------------------------ +reg [1:0] mem_state; +reg [1:0] mem_state_nxt; + +// State machine definition +parameter M_IDLE = 2'h0; +parameter M_SET_BRK = 2'h1; +parameter M_ACCESS_BRK = 2'h2; +parameter M_ACCESS = 2'h3; + +// State transition +always @(mem_state or mem_seq_start or dbg_halt_st) + case (mem_state) + M_IDLE : mem_state_nxt = ~mem_seq_start ? M_IDLE : + dbg_halt_st ? M_ACCESS : M_SET_BRK; + M_SET_BRK : mem_state_nxt = dbg_halt_st ? M_ACCESS_BRK : M_SET_BRK; + M_ACCESS_BRK : mem_state_nxt = M_IDLE; + M_ACCESS : mem_state_nxt = M_IDLE; + // pragma coverage off + default : mem_state_nxt = M_IDLE; + // pragma coverage on + endcase + +// State machine +always @(posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) mem_state <= M_IDLE; + else mem_state <= mem_state_nxt; + +// Utility signals +assign mem_halt_cpu = (mem_state==M_IDLE) & (mem_state_nxt==M_SET_BRK); +assign mem_run_cpu = (mem_state==M_ACCESS_BRK) & (mem_state_nxt==M_IDLE); +assign mem_access = (mem_state==M_ACCESS) | (mem_state==M_ACCESS_BRK); + + +// Interface to CPU Registers and Memory bacbkone +//------------------------------------------------ +assign dbg_mem_addr = mem_addr; +assign dbg_mem_dout = ~mem_bw ? mem_data : + mem_addr[0] ? {mem_data[7:0], 8'h00} : + {8'h00, mem_data[7:0]}; + +assign dbg_reg_wr = mem_access & mem_ctl[1] & mem_ctl[2]; +assign dbg_reg_rd = mem_access & ~mem_ctl[1] & mem_ctl[2]; + +assign dbg_mem_en = mem_access & ~mem_ctl[2]; +assign dbg_mem_rd = dbg_mem_en & ~mem_ctl[1]; + +wire [1:0] dbg_mem_wr_msk = ~mem_bw ? 2'b11 : + mem_addr[0] ? 2'b10 : 2'b01; +assign dbg_mem_wr = {2{dbg_mem_en & mem_ctl[1]}} & dbg_mem_wr_msk; + + +// It takes one additional cycle to read from Memory as from registers +always @(posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) dbg_mem_rd_dly <= 1'b0; + else dbg_mem_rd_dly <= dbg_mem_rd; + + +//============================================================================= +// 9) UART COMMUNICATION +//============================================================================= +`ifdef DBG_UART +omsp_dbg_uart dbg_uart_0 ( + +// OUTPUTs + .dbg_addr (dbg_addr), // Debug register address + .dbg_din (dbg_din), // Debug register data input + .dbg_rd (dbg_rd), // Debug register data read + .dbg_uart_txd (dbg_uart_txd), // Debug interface: UART TXD + .dbg_wr (dbg_wr), // Debug register data write + +// INPUTs + .dbg_clk (dbg_clk), // Debug unit clock + .dbg_dout (dbg_dout), // Debug register data output + .dbg_rd_rdy (dbg_rd_rdy), // Debug register data is ready for read + .dbg_rst (dbg_rst), // Debug unit reset + .dbg_uart_rxd (dbg_uart_rxd), // Debug interface: UART RXD + .mem_burst (mem_burst), // Burst on going + .mem_burst_end(mem_burst_end), // End TX/RX burst + .mem_burst_rd (mem_burst_rd), // Start TX burst + .mem_burst_wr (mem_burst_wr), // Start RX burst + .mem_bw (mem_bw) // Burst byte width +); + +`else +assign dbg_addr = 6'h00; +assign dbg_din = 16'h0000; +assign dbg_rd = 1'b0; +assign dbg_uart_txd = 1'b0; +assign dbg_wr = 1'b0; +`endif + + +//============================================================================= +// 10) JTAG COMMUNICATION +//============================================================================= +`ifdef DBG_JTAG +JTAG INTERFACE IS NOT SUPPORTED YET +`else +`endif + +endmodule // dbg + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif diff --git a/tests/openmsp430/rtl/omsp_dbg_hwbrk.v b/tests/openmsp430/rtl/omsp_dbg_hwbrk.v new file mode 100644 index 00000000..6f639aee --- /dev/null +++ b/tests/openmsp430/rtl/omsp_dbg_hwbrk.v @@ -0,0 +1,282 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_dbg_hwbrk.v +// +// *Module Description: +// Hardware Breakpoint / Watchpoint module +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 117 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2011-06-23 21:30:51 +0200 (Thu, 23 Jun 2011) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module omsp_dbg_hwbrk ( + +// OUTPUTs + brk_halt, // Hardware breakpoint command + brk_pnd, // Hardware break/watch-point pending + brk_dout, // Hardware break/watch-point register data input + +// INPUTs + brk_reg_rd, // Hardware break/watch-point register read select + brk_reg_wr, // Hardware break/watch-point register write select + dbg_clk, // Debug unit clock + dbg_din, // Debug register data input + dbg_rst, // Debug unit reset + eu_mab, // Execution-Unit Memory address bus + eu_mb_en, // Execution-Unit Memory bus enable + eu_mb_wr, // Execution-Unit Memory bus write transfer + eu_mdb_in, // Memory data bus input + eu_mdb_out, // Memory data bus output + exec_done, // Execution completed + fe_mb_en, // Frontend Memory bus enable + pc // Program counter +); + +// OUTPUTs +//========= +output brk_halt; // Hardware breakpoint command +output brk_pnd; // Hardware break/watch-point pending +output [15:0] brk_dout; // Hardware break/watch-point register data input + +// INPUTs +//========= +input [3:0] brk_reg_rd; // Hardware break/watch-point register read select +input [3:0] brk_reg_wr; // Hardware break/watch-point register write select +input dbg_clk; // Debug unit clock +input [15:0] dbg_din; // Debug register data input +input dbg_rst; // Debug unit reset +input [15:0] eu_mab; // Execution-Unit Memory address bus +input eu_mb_en; // Execution-Unit Memory bus enable +input [1:0] eu_mb_wr; // Execution-Unit Memory bus write transfer +input [15:0] eu_mdb_in; // Memory data bus input +input [15:0] eu_mdb_out; // Memory data bus output +input exec_done; // Execution completed +input fe_mb_en; // Frontend Memory bus enable +input [15:0] pc; // Program counter + + +//============================================================================= +// 1) WIRE & PARAMETER DECLARATION +//============================================================================= + +wire range_wr_set; +wire range_rd_set; +wire addr1_wr_set; +wire addr1_rd_set; +wire addr0_wr_set; +wire addr0_rd_set; + + +parameter BRK_CTL = 0, + BRK_STAT = 1, + BRK_ADDR0 = 2, + BRK_ADDR1 = 3; + + +//============================================================================= +// 2) CONFIGURATION REGISTERS +//============================================================================= + +// BRK_CTL Register +//----------------------------------------------------------------------------- +// 7 6 5 4 3 2 1 0 +// Reserved RANGE_MODE INST_EN BREAK_EN ACCESS_MODE +// +// ACCESS_MODE: - 00 : Disabled +// - 01 : Detect read access +// - 10 : Detect write access +// - 11 : Detect read/write access +// NOTE: '10' & '11' modes are not supported on the instruction flow +// +// BREAK_EN: - 0 : Watchmode enable +// - 1 : Break enable +// +// INST_EN: - 0 : Checks are done on the execution unit (data flow) +// - 1 : Checks are done on the frontend (instruction flow) +// +// RANGE_MODE: - 0 : Address match on BRK_ADDR0 or BRK_ADDR1 +// - 1 : Address match on BRK_ADDR0->BRK_ADDR1 range +// +//----------------------------------------------------------------------------- +reg [4:0] brk_ctl; + +wire brk_ctl_wr = brk_reg_wr[BRK_CTL]; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) brk_ctl <= 5'h00; + else if (brk_ctl_wr) brk_ctl <= {`HWBRK_RANGE & dbg_din[4], dbg_din[3:0]}; + +wire [7:0] brk_ctl_full = {3'b000, brk_ctl}; + + +// BRK_STAT Register +//----------------------------------------------------------------------------- +// 7 6 5 4 3 2 1 0 +// Reserved RANGE_WR RANGE_RD ADDR1_WR ADDR1_RD ADDR0_WR ADDR0_RD +//----------------------------------------------------------------------------- +reg [5:0] brk_stat; + +wire brk_stat_wr = brk_reg_wr[BRK_STAT]; +wire [5:0] brk_stat_set = {range_wr_set & `HWBRK_RANGE, + range_rd_set & `HWBRK_RANGE, + addr1_wr_set, addr1_rd_set, + addr0_wr_set, addr0_rd_set}; +wire [5:0] brk_stat_clr = ~dbg_din[5:0]; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) brk_stat <= 6'h00; + else if (brk_stat_wr) brk_stat <= ((brk_stat & brk_stat_clr) | brk_stat_set); + else brk_stat <= (brk_stat | brk_stat_set); + +wire [7:0] brk_stat_full = {2'b00, brk_stat}; +wire brk_pnd = |brk_stat; + + +// BRK_ADDR0 Register +//----------------------------------------------------------------------------- +reg [15:0] brk_addr0; + +wire brk_addr0_wr = brk_reg_wr[BRK_ADDR0]; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) brk_addr0 <= 16'h0000; + else if (brk_addr0_wr) brk_addr0 <= dbg_din; + + +// BRK_ADDR1/DATA0 Register +//----------------------------------------------------------------------------- +reg [15:0] brk_addr1; + +wire brk_addr1_wr = brk_reg_wr[BRK_ADDR1]; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) brk_addr1 <= 16'h0000; + else if (brk_addr1_wr) brk_addr1 <= dbg_din; + + +//============================================================================ +// 3) DATA OUTPUT GENERATION +//============================================================================ + +wire [15:0] brk_ctl_rd = {8'h00, brk_ctl_full} & {16{brk_reg_rd[BRK_CTL]}}; +wire [15:0] brk_stat_rd = {8'h00, brk_stat_full} & {16{brk_reg_rd[BRK_STAT]}}; +wire [15:0] brk_addr0_rd = brk_addr0 & {16{brk_reg_rd[BRK_ADDR0]}}; +wire [15:0] brk_addr1_rd = brk_addr1 & {16{brk_reg_rd[BRK_ADDR1]}}; + +wire [15:0] brk_dout = brk_ctl_rd | + brk_stat_rd | + brk_addr0_rd | + brk_addr1_rd; + + +//============================================================================ +// 4) BREAKPOINT / WATCHPOINT GENERATION +//============================================================================ + +// Comparators +//--------------------------- +// Note: here the comparison logic is instanciated several times in order +// to improve the timings, at the cost of a bit more area. + +wire equ_d_addr0 = eu_mb_en & (eu_mab==brk_addr0) & ~brk_ctl[`BRK_RANGE]; +wire equ_d_addr1 = eu_mb_en & (eu_mab==brk_addr1) & ~brk_ctl[`BRK_RANGE]; +wire equ_d_range = eu_mb_en & ((eu_mab>=brk_addr0) & (eu_mab<=brk_addr1)) & + brk_ctl[`BRK_RANGE] & `HWBRK_RANGE; + +reg fe_mb_en_buf; +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) fe_mb_en_buf <= 1'b0; + else fe_mb_en_buf <= fe_mb_en; + +wire equ_i_addr0 = fe_mb_en_buf & (pc==brk_addr0) & ~brk_ctl[`BRK_RANGE]; +wire equ_i_addr1 = fe_mb_en_buf & (pc==brk_addr1) & ~brk_ctl[`BRK_RANGE]; +wire equ_i_range = fe_mb_en_buf & ((pc>=brk_addr0) & (pc<=brk_addr1)) & + brk_ctl[`BRK_RANGE] & `HWBRK_RANGE; + + +// Detect accesses +//--------------------------- + +// Detect Instruction read access +wire i_addr0_rd = equ_i_addr0 & brk_ctl[`BRK_I_EN]; +wire i_addr1_rd = equ_i_addr1 & brk_ctl[`BRK_I_EN]; +wire i_range_rd = equ_i_range & brk_ctl[`BRK_I_EN]; + +// Detect Execution-Unit write access +wire d_addr0_wr = equ_d_addr0 & ~brk_ctl[`BRK_I_EN] & |eu_mb_wr; +wire d_addr1_wr = equ_d_addr1 & ~brk_ctl[`BRK_I_EN] & |eu_mb_wr; +wire d_range_wr = equ_d_range & ~brk_ctl[`BRK_I_EN] & |eu_mb_wr; + +// Detect DATA read access +// Whenever an "ADD r9. &0x200" instruction is executed, &0x200 will be read +// before being written back. In that case, the read flag should not be set. +// In general, We should here make sure no write access occures during the +// same instruction cycle before setting the read flag. +reg [2:0] d_rd_trig; +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) d_rd_trig <= 3'h0; + else if (exec_done) d_rd_trig <= 3'h0; + else d_rd_trig <= {equ_d_range & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr, + equ_d_addr1 & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr, + equ_d_addr0 & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr}; + +wire d_addr0_rd = d_rd_trig[0] & exec_done & ~d_addr0_wr; +wire d_addr1_rd = d_rd_trig[1] & exec_done & ~d_addr1_wr; +wire d_range_rd = d_rd_trig[2] & exec_done & ~d_range_wr; + + +// Set flags +assign addr0_rd_set = brk_ctl[`BRK_MODE_RD] & (d_addr0_rd | i_addr0_rd); +assign addr0_wr_set = brk_ctl[`BRK_MODE_WR] & d_addr0_wr; +assign addr1_rd_set = brk_ctl[`BRK_MODE_RD] & (d_addr1_rd | i_addr1_rd); +assign addr1_wr_set = brk_ctl[`BRK_MODE_WR] & d_addr1_wr; +assign range_rd_set = brk_ctl[`BRK_MODE_RD] & (d_range_rd | i_range_rd); +assign range_wr_set = brk_ctl[`BRK_MODE_WR] & d_range_wr; + + +// Break CPU +assign brk_halt = brk_ctl[`BRK_EN] & |brk_stat_set; + + +endmodule // omsp_dbg_hwbrk + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif diff --git a/tests/openmsp430/rtl/omsp_dbg_uart.v b/tests/openmsp430/rtl/omsp_dbg_uart.v new file mode 100644 index 00000000..319099a5 --- /dev/null +++ b/tests/openmsp430/rtl/omsp_dbg_uart.v @@ -0,0 +1,298 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_dbg_uart.v +// +// *Module Description: +// Debug UART communication interface (8N1, Half-duplex) +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 134 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2012-03-22 21:31:06 +0100 (Thu, 22 Mar 2012) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module omsp_dbg_uart ( + +// OUTPUTs + dbg_addr, // Debug register address + dbg_din, // Debug register data input + dbg_rd, // Debug register data read + dbg_uart_txd, // Debug interface: UART TXD + dbg_wr, // Debug register data write + +// INPUTs + dbg_clk, // Debug unit clock + dbg_dout, // Debug register data output + dbg_rd_rdy, // Debug register data is ready for read + dbg_rst, // Debug unit reset + dbg_uart_rxd, // Debug interface: UART RXD + mem_burst, // Burst on going + mem_burst_end, // End TX/RX burst + mem_burst_rd, // Start TX burst + mem_burst_wr, // Start RX burst + mem_bw // Burst byte width +); + +// OUTPUTs +//========= +output [5:0] dbg_addr; // Debug register address +output [15:0] dbg_din; // Debug register data input +output dbg_rd; // Debug register data read +output dbg_uart_txd; // Debug interface: UART TXD +output dbg_wr; // Debug register data write + +// INPUTs +//========= +input dbg_clk; // Debug unit clock +input [15:0] dbg_dout; // Debug register data output +input dbg_rd_rdy; // Debug register data is ready for read +input dbg_rst; // Debug unit reset +input dbg_uart_rxd; // Debug interface: UART RXD +input mem_burst; // Burst on going +input mem_burst_end; // End TX/RX burst +input mem_burst_rd; // Start TX burst +input mem_burst_wr; // Start RX burst +input mem_bw; // Burst byte width + + +//============================================================================= +// 1) UART RECEIVE LINE SYNCHRONIZTION & FILTERING +//============================================================================= + +// Synchronize RXD input +//-------------------------------- +`ifdef SYNC_DBG_UART_RXD + + wire uart_rxd_n; + + omsp_sync_cell sync_cell_uart_rxd ( + .data_out (uart_rxd_n), + .data_in (~dbg_uart_rxd), + .clk (dbg_clk), + .rst (dbg_rst) + ); + wire uart_rxd = ~uart_rxd_n; +`else + wire uart_rxd = dbg_uart_rxd; +`endif + +// RXD input buffer +//-------------------------------- +reg [1:0] rxd_buf; +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) rxd_buf <= 2'h3; + else rxd_buf <= {rxd_buf[0], uart_rxd}; + +// Majority decision +//------------------------ +reg rxd_maj; + +wire rxd_maj_nxt = (uart_rxd & rxd_buf[0]) | + (uart_rxd & rxd_buf[1]) | + (rxd_buf[0] & rxd_buf[1]); + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) rxd_maj <= 1'b1; + else rxd_maj <= rxd_maj_nxt; + +wire rxd_s = rxd_maj; +wire rxd_fe = rxd_maj & ~rxd_maj_nxt; +wire rxd_re = ~rxd_maj & rxd_maj_nxt; +wire rxd_edge = rxd_maj ^ rxd_maj_nxt; + +//============================================================================= +// 2) UART STATE MACHINE +//============================================================================= + +// Receive state +//------------------------ +reg [2:0] uart_state; +reg [2:0] uart_state_nxt; + +wire sync_done; +wire xfer_done; +reg [19:0] xfer_buf; +wire [19:0] xfer_buf_nxt; + +// State machine definition +parameter RX_SYNC = 3'h0; +parameter RX_CMD = 3'h1; +parameter RX_DATA1 = 3'h2; +parameter RX_DATA2 = 3'h3; +parameter TX_DATA1 = 3'h4; +parameter TX_DATA2 = 3'h5; + +// State transition +always @(uart_state or xfer_buf_nxt or mem_burst or mem_burst_wr or mem_burst_rd or mem_burst_end or mem_bw) + case (uart_state) + RX_SYNC : uart_state_nxt = RX_CMD; + RX_CMD : uart_state_nxt = mem_burst_wr ? + (mem_bw ? RX_DATA2 : RX_DATA1) : + mem_burst_rd ? + (mem_bw ? TX_DATA2 : TX_DATA1) : + (xfer_buf_nxt[`DBG_UART_WR] ? + (xfer_buf_nxt[`DBG_UART_BW] ? RX_DATA2 : RX_DATA1) : + (xfer_buf_nxt[`DBG_UART_BW] ? TX_DATA2 : TX_DATA1)); + RX_DATA1 : uart_state_nxt = RX_DATA2; + RX_DATA2 : uart_state_nxt = (mem_burst & ~mem_burst_end) ? + (mem_bw ? RX_DATA2 : RX_DATA1) : + RX_CMD; + TX_DATA1 : uart_state_nxt = TX_DATA2; + TX_DATA2 : uart_state_nxt = (mem_burst & ~mem_burst_end) ? + (mem_bw ? TX_DATA2 : TX_DATA1) : + RX_CMD; + // pragma coverage off + default : uart_state_nxt = RX_CMD; + // pragma coverage on + endcase + +// State machine +always @(posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) uart_state <= RX_SYNC; + else if (xfer_done | sync_done | + mem_burst_wr | mem_burst_rd) uart_state <= uart_state_nxt; + +// Utility signals +wire cmd_valid = (uart_state==RX_CMD) & xfer_done; +wire rx_active = (uart_state==RX_DATA1) | (uart_state==RX_DATA2) | (uart_state==RX_CMD); +wire tx_active = (uart_state==TX_DATA1) | (uart_state==TX_DATA2); + + +//============================================================================= +// 3) UART SYNCHRONIZATION +//============================================================================= +// After DBG_RST, the host needs to fist send a synchronization character (0x80) +// If this feature doesn't work properly, it is possible to disable it by +// commenting the DBG_UART_AUTO_SYNC define in the openMSP430.inc file. + +reg sync_busy; +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) sync_busy <= 1'b0; + else if ((uart_state==RX_SYNC) & rxd_fe) sync_busy <= 1'b1; + else if ((uart_state==RX_SYNC) & rxd_re) sync_busy <= 1'b0; + +assign sync_done = (uart_state==RX_SYNC) & rxd_re & sync_busy; + +`ifdef DBG_UART_AUTO_SYNC + +reg [`DBG_UART_XFER_CNT_W+2:0] sync_cnt; +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) sync_cnt <= {{`DBG_UART_XFER_CNT_W{1'b1}}, 3'b000}; + else if (sync_busy | (~sync_busy & sync_cnt[2])) sync_cnt <= sync_cnt+{{`DBG_UART_XFER_CNT_W+2{1'b0}}, 1'b1}; + +wire [`DBG_UART_XFER_CNT_W-1:0] bit_cnt_max = sync_cnt[`DBG_UART_XFER_CNT_W+2:3]; +`else +wire [`DBG_UART_XFER_CNT_W-1:0] bit_cnt_max = `DBG_UART_CNT; +`endif + + +//============================================================================= +// 4) UART RECEIVE / TRANSMIT +//============================================================================= + +// Transfer counter +//------------------------ +reg [3:0] xfer_bit; +reg [`DBG_UART_XFER_CNT_W-1:0] xfer_cnt; + +wire txd_start = dbg_rd_rdy | (xfer_done & (uart_state==TX_DATA1)); +wire rxd_start = (xfer_bit==4'h0) & rxd_fe & ((uart_state!=RX_SYNC)); +wire xfer_bit_inc = (xfer_bit!=4'h0) & (xfer_cnt=={`DBG_UART_XFER_CNT_W{1'b0}}); +assign xfer_done = rx_active ? (xfer_bit==4'ha) : (xfer_bit==4'hb); + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) xfer_bit <= 4'h0; + else if (txd_start | rxd_start) xfer_bit <= 4'h1; + else if (xfer_done) xfer_bit <= 4'h0; + else if (xfer_bit_inc) xfer_bit <= xfer_bit+4'h1; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) xfer_cnt <= {`DBG_UART_XFER_CNT_W{1'b0}}; + else if (rx_active & rxd_edge) xfer_cnt <= {1'b0, bit_cnt_max[`DBG_UART_XFER_CNT_W-1:1]}; + else if (txd_start | xfer_bit_inc) xfer_cnt <= bit_cnt_max; + else if (|xfer_cnt) xfer_cnt <= xfer_cnt+{`DBG_UART_XFER_CNT_W{1'b1}}; + + +// Receive/Transmit buffer +//------------------------- +assign xfer_buf_nxt = {rxd_s, xfer_buf[19:1]}; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) xfer_buf <= 20'h00000; + else if (dbg_rd_rdy) xfer_buf <= {1'b1, dbg_dout[15:8], 2'b01, dbg_dout[7:0], 1'b0}; + else if (xfer_bit_inc) xfer_buf <= xfer_buf_nxt; + + +// Generate TXD output +//------------------------ +reg dbg_uart_txd; + +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) dbg_uart_txd <= 1'b1; + else if (xfer_bit_inc & tx_active) dbg_uart_txd <= xfer_buf[0]; + + +//============================================================================= +// 5) INTERFACE TO DEBUG REGISTERS +//============================================================================= + +reg [5:0] dbg_addr; + always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) dbg_addr <= 6'h00; + else if (cmd_valid) dbg_addr <= xfer_buf_nxt[`DBG_UART_ADDR]; + +reg dbg_bw; +always @ (posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) dbg_bw <= 1'b0; + else if (cmd_valid) dbg_bw <= xfer_buf_nxt[`DBG_UART_BW]; + +wire dbg_din_bw = mem_burst ? mem_bw : dbg_bw; + +wire [15:0] dbg_din = dbg_din_bw ? {8'h00, xfer_buf_nxt[18:11]} : + {xfer_buf_nxt[18:11], xfer_buf_nxt[9:2]}; +wire dbg_wr = (xfer_done & (uart_state==RX_DATA2)); +wire dbg_rd = mem_burst ? (xfer_done & (uart_state==TX_DATA2)) : + (cmd_valid & ~xfer_buf_nxt[`DBG_UART_WR]) | mem_burst_rd; + + + +endmodule // omsp_dbg_uart + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif diff --git a/tests/openmsp430/rtl/omsp_execution_unit.v b/tests/openmsp430/rtl/omsp_execution_unit.v new file mode 100644 index 00000000..8a2965e5 --- /dev/null +++ b/tests/openmsp430/rtl/omsp_execution_unit.v @@ -0,0 +1,420 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_execution_unit.v +// +// *Module Description: +// openMSP430 Execution unit +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 134 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2012-03-22 21:31:06 +0100 (Thu, 22 Mar 2012) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module omsp_execution_unit ( + +// OUTPUTs + cpuoff, // Turns off the CPU + dbg_reg_din, // Debug unit CPU register data input + gie, // General interrupt enable + mab, // Memory address bus + mb_en, // Memory bus enable + mb_wr, // Memory bus write transfer + mdb_out, // Memory data bus output + oscoff, // Turns off LFXT1 clock input + pc_sw, // Program counter software value + pc_sw_wr, // Program counter software write + scg0, // System clock generator 1. Turns off the DCO + scg1, // System clock generator 1. Turns off the SMCLK + +// INPUTs + dbg_halt_st, // Halt/Run status from CPU + dbg_mem_dout, // Debug unit data output + dbg_reg_wr, // Debug unit CPU register write + e_state, // Execution state + exec_done, // Execution completed + inst_ad, // Decoded Inst: destination addressing mode + inst_as, // Decoded Inst: source addressing mode + inst_alu, // ALU control signals + inst_bw, // Decoded Inst: byte width + inst_dest, // Decoded Inst: destination (one hot) + inst_dext, // Decoded Inst: destination extended instruction word + inst_irq_rst, // Decoded Inst: reset interrupt + inst_jmp, // Decoded Inst: Conditional jump + inst_mov, // Decoded Inst: mov instruction + inst_sext, // Decoded Inst: source extended instruction word + inst_so, // Decoded Inst: Single-operand arithmetic + inst_src, // Decoded Inst: source (one hot) + inst_type, // Decoded Instruction type + mclk, // Main system clock + mdb_in, // Memory data bus input + pc, // Program counter + pc_nxt, // Next PC value (for CALL & IRQ) + puc_rst, // Main system reset + scan_enable // Scan enable (active during scan shifting) +); + +// OUTPUTs +//========= +output cpuoff; // Turns off the CPU +output [15:0] dbg_reg_din; // Debug unit CPU register data input +output gie; // General interrupt enable +output [15:0] mab; // Memory address bus +output mb_en; // Memory bus enable +output [1:0] mb_wr; // Memory bus write transfer +output [15:0] mdb_out; // Memory data bus output +output oscoff; // Turns off LFXT1 clock input +output [15:0] pc_sw; // Program counter software value +output pc_sw_wr; // Program counter software write +output scg0; // System clock generator 1. Turns off the DCO +output scg1; // System clock generator 1. Turns off the SMCLK + +// INPUTs +//========= +input dbg_halt_st; // Halt/Run status from CPU +input [15:0] dbg_mem_dout; // Debug unit data output +input dbg_reg_wr; // Debug unit CPU register write +input [3:0] e_state; // Execution state +input exec_done; // Execution completed +input [7:0] inst_ad; // Decoded Inst: destination addressing mode +input [7:0] inst_as; // Decoded Inst: source addressing mode +input [11:0] inst_alu; // ALU control signals +input inst_bw; // Decoded Inst: byte width +input [15:0] inst_dest; // Decoded Inst: destination (one hot) +input [15:0] inst_dext; // Decoded Inst: destination extended instruction word +input inst_irq_rst; // Decoded Inst: reset interrupt +input [7:0] inst_jmp; // Decoded Inst: Conditional jump +input inst_mov; // Decoded Inst: mov instruction +input [15:0] inst_sext; // Decoded Inst: source extended instruction word +input [7:0] inst_so; // Decoded Inst: Single-operand arithmetic +input [15:0] inst_src; // Decoded Inst: source (one hot) +input [2:0] inst_type; // Decoded Instruction type +input mclk; // Main system clock +input [15:0] mdb_in; // Memory data bus input +input [15:0] pc; // Program counter +input [15:0] pc_nxt; // Next PC value (for CALL & IRQ) +input puc_rst; // Main system reset +input scan_enable; // Scan enable (active during scan shifting) + + +//============================================================================= +// 1) INTERNAL WIRES/REGISTERS/PARAMETERS DECLARATION +//============================================================================= + +wire [15:0] alu_out; +wire [15:0] alu_out_add; +wire [3:0] alu_stat; +wire [3:0] alu_stat_wr; +wire [15:0] op_dst; +wire [15:0] op_src; +wire [15:0] reg_dest; +wire [15:0] reg_src; +wire [15:0] mdb_in_bw; +wire [15:0] mdb_in_val; +wire [3:0] status; + + +//============================================================================= +// 2) REGISTER FILE +//============================================================================= + +wire reg_dest_wr = ((e_state==`E_EXEC) & ( + (inst_type[`INST_TO] & inst_ad[`DIR] & ~inst_alu[`EXEC_NO_WR]) | + (inst_type[`INST_SO] & inst_as[`DIR] & ~(inst_so[`PUSH] | inst_so[`CALL] | inst_so[`RETI])) | + inst_type[`INST_JMP])) | dbg_reg_wr; + +wire reg_sp_wr = (((e_state==`E_IRQ_1) | (e_state==`E_IRQ_3)) & ~inst_irq_rst) | + ((e_state==`E_DST_RD) & ((inst_so[`PUSH] | inst_so[`CALL]) & ~inst_as[`IDX] & ~((inst_as[`INDIR] | inst_as[`INDIR_I]) & inst_src[1]))) | + ((e_state==`E_SRC_AD) & ((inst_so[`PUSH] | inst_so[`CALL]) & inst_as[`IDX])) | + ((e_state==`E_SRC_RD) & ((inst_so[`PUSH] | inst_so[`CALL]) & ((inst_as[`INDIR] | inst_as[`INDIR_I]) & inst_src[1]))); + +wire reg_sr_wr = (e_state==`E_DST_RD) & inst_so[`RETI]; + +wire reg_sr_clr = (e_state==`E_IRQ_2); + +wire reg_pc_call = ((e_state==`E_EXEC) & inst_so[`CALL]) | + ((e_state==`E_DST_WR) & inst_so[`RETI]); + +wire reg_incr = (exec_done & inst_as[`INDIR_I]) | + ((e_state==`E_SRC_RD) & inst_so[`RETI]) | + ((e_state==`E_EXEC) & inst_so[`RETI]); + +assign dbg_reg_din = reg_dest; + + +omsp_register_file register_file_0 ( + +// OUTPUTs + .cpuoff (cpuoff), // Turns off the CPU + .gie (gie), // General interrupt enable + .oscoff (oscoff), // Turns off LFXT1 clock input + .pc_sw (pc_sw), // Program counter software value + .pc_sw_wr (pc_sw_wr), // Program counter software write + .reg_dest (reg_dest), // Selected register destination content + .reg_src (reg_src), // Selected register source content + .scg0 (scg0), // System clock generator 1. Turns off the DCO + .scg1 (scg1), // System clock generator 1. Turns off the SMCLK + .status (status), // R2 Status {V,N,Z,C} + +// INPUTs + .alu_stat (alu_stat), // ALU Status {V,N,Z,C} + .alu_stat_wr (alu_stat_wr), // ALU Status write {V,N,Z,C} + .inst_bw (inst_bw), // Decoded Inst: byte width + .inst_dest (inst_dest), // Register destination selection + .inst_src (inst_src), // Register source selection + .mclk (mclk), // Main system clock + .pc (pc), // Program counter + .puc_rst (puc_rst), // Main system reset + .reg_dest_val (alu_out), // Selected register destination value + .reg_dest_wr (reg_dest_wr), // Write selected register destination + .reg_pc_call (reg_pc_call), // Trigger PC update for a CALL instruction + .reg_sp_val (alu_out_add), // Stack Pointer next value + .reg_sp_wr (reg_sp_wr), // Stack Pointer write + .reg_sr_clr (reg_sr_clr), // Status register clear for interrupts + .reg_sr_wr (reg_sr_wr), // Status Register update for RETI instruction + .reg_incr (reg_incr), // Increment source register + .scan_enable (scan_enable) // Scan enable (active during scan shifting) +); + + +//============================================================================= +// 3) SOURCE OPERAND MUXING +//============================================================================= +// inst_as[`DIR] : Register direct. -> Source is in register +// inst_as[`IDX] : Register indexed. -> Source is in memory, address is register+offset +// inst_as[`INDIR] : Register indirect. +// inst_as[`INDIR_I]: Register indirect autoincrement. +// inst_as[`SYMB] : Symbolic (operand is in memory at address PC+x). +// inst_as[`IMM] : Immediate (operand is next word in the instruction stream). +// inst_as[`ABS] : Absolute (operand is in memory at address x). +// inst_as[`CONST] : Constant. + +wire src_reg_src_sel = (e_state==`E_IRQ_0) | + (e_state==`E_IRQ_2) | + ((e_state==`E_SRC_RD) & ~inst_as[`ABS]) | + ((e_state==`E_SRC_WR) & ~inst_as[`ABS]) | + ((e_state==`E_EXEC) & inst_as[`DIR] & ~inst_type[`INST_JMP]); + +wire src_reg_dest_sel = (e_state==`E_IRQ_1) | + (e_state==`E_IRQ_3) | + ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL])) | + ((e_state==`E_SRC_AD) & (inst_so[`PUSH] | inst_so[`CALL]) & inst_as[`IDX]); + +wire src_mdb_in_val_sel = ((e_state==`E_DST_RD) & inst_so[`RETI]) | + ((e_state==`E_EXEC) & (inst_as[`INDIR] | inst_as[`INDIR_I] | + inst_as[`IDX] | inst_as[`SYMB] | + inst_as[`ABS])); + +wire src_inst_dext_sel = ((e_state==`E_DST_RD) & ~(inst_so[`PUSH] | inst_so[`CALL])) | + ((e_state==`E_DST_WR) & ~(inst_so[`PUSH] | inst_so[`CALL] | + inst_so[`RETI])); + +wire src_inst_sext_sel = ((e_state==`E_EXEC) & (inst_type[`INST_JMP] | inst_as[`IMM] | + inst_as[`CONST] | inst_so[`RETI])); + + +assign op_src = src_reg_src_sel ? reg_src : + src_reg_dest_sel ? reg_dest : + src_mdb_in_val_sel ? mdb_in_val : + src_inst_dext_sel ? inst_dext : + src_inst_sext_sel ? inst_sext : 16'h0000; + + +//============================================================================= +// 4) DESTINATION OPERAND MUXING +//============================================================================= +// inst_ad[`DIR] : Register direct. +// inst_ad[`IDX] : Register indexed. +// inst_ad[`SYMB] : Symbolic (operand is in memory at address PC+x). +// inst_ad[`ABS] : Absolute (operand is in memory at address x). + + +wire dst_inst_sext_sel = ((e_state==`E_SRC_RD) & (inst_as[`IDX] | inst_as[`SYMB] | + inst_as[`ABS])) | + ((e_state==`E_SRC_WR) & (inst_as[`IDX] | inst_as[`SYMB] | + inst_as[`ABS])); + +wire dst_mdb_in_bw_sel = ((e_state==`E_DST_WR) & inst_so[`RETI]) | + ((e_state==`E_EXEC) & ~(inst_ad[`DIR] | inst_type[`INST_JMP] | + inst_type[`INST_SO]) & ~inst_so[`RETI]); + +wire dst_fffe_sel = (e_state==`E_IRQ_0) | + (e_state==`E_IRQ_1) | + (e_state==`E_IRQ_3) | + ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL]) & ~inst_so[`RETI]) | + ((e_state==`E_SRC_AD) & (inst_so[`PUSH] | inst_so[`CALL]) & inst_as[`IDX]) | + ((e_state==`E_SRC_RD) & (inst_so[`PUSH] | inst_so[`CALL]) & (inst_as[`INDIR] | inst_as[`INDIR_I]) & inst_src[1]); + +wire dst_reg_dest_sel = ((e_state==`E_DST_RD) & ~(inst_so[`PUSH] | inst_so[`CALL] | inst_ad[`ABS] | inst_so[`RETI])) | + ((e_state==`E_DST_WR) & ~inst_ad[`ABS]) | + ((e_state==`E_EXEC) & (inst_ad[`DIR] | inst_type[`INST_JMP] | + inst_type[`INST_SO]) & ~inst_so[`RETI]); + + +assign op_dst = dbg_halt_st ? dbg_mem_dout : + dst_inst_sext_sel ? inst_sext : + dst_mdb_in_bw_sel ? mdb_in_bw : + dst_reg_dest_sel ? reg_dest : + dst_fffe_sel ? 16'hfffe : 16'h0000; + + +//============================================================================= +// 5) ALU +//============================================================================= + +wire exec_cycle = (e_state==`E_EXEC); + +omsp_alu alu_0 ( + +// OUTPUTs + .alu_out (alu_out), // ALU output value + .alu_out_add (alu_out_add), // ALU adder output value + .alu_stat (alu_stat), // ALU Status {V,N,Z,C} + .alu_stat_wr (alu_stat_wr), // ALU Status write {V,N,Z,C} + +// INPUTs + .dbg_halt_st (dbg_halt_st), // Halt/Run status from CPU + .exec_cycle (exec_cycle), // Instruction execution cycle + .inst_alu (inst_alu), // ALU control signals + .inst_bw (inst_bw), // Decoded Inst: byte width + .inst_jmp (inst_jmp), // Decoded Inst: Conditional jump + .inst_so (inst_so), // Single-operand arithmetic + .op_dst (op_dst), // Destination operand + .op_src (op_src), // Source operand + .status (status) // R2 Status {V,N,Z,C} +); + + +//============================================================================= +// 6) MEMORY INTERFACE +//============================================================================= + +// Detect memory read/write access +assign mb_en = ((e_state==`E_IRQ_1) & ~inst_irq_rst) | + ((e_state==`E_IRQ_3) & ~inst_irq_rst) | + ((e_state==`E_SRC_RD) & ~inst_as[`IMM]) | + (e_state==`E_SRC_WR) | + ((e_state==`E_EXEC) & inst_so[`RETI]) | + ((e_state==`E_DST_RD) & ~inst_type[`INST_SO] + & ~inst_mov) | + (e_state==`E_DST_WR); + +wire [1:0] mb_wr_msk = inst_alu[`EXEC_NO_WR] ? 2'b00 : + ~inst_bw ? 2'b11 : + alu_out_add[0] ? 2'b10 : 2'b01; +assign mb_wr = ({2{(e_state==`E_IRQ_1)}} | + {2{(e_state==`E_IRQ_3)}} | + {2{(e_state==`E_DST_WR)}} | + {2{(e_state==`E_SRC_WR)}}) & mb_wr_msk; + +// Memory address bus +assign mab = alu_out_add[15:0]; + +// Memory data bus output +reg [15:0] mdb_out_nxt; + +`ifdef CLOCK_GATING +wire mdb_out_nxt_en = (e_state==`E_DST_RD) | + (((e_state==`E_EXEC) & ~inst_so[`CALL]) | + (e_state==`E_IRQ_0) | (e_state==`E_IRQ_2)); +wire mclk_mdb_out_nxt; +omsp_clock_gate clock_gate_mdb_out_nxt (.gclk(mclk_mdb_out_nxt), + .clk (mclk), .enable(mdb_out_nxt_en), .scan_enable(scan_enable)); +`else +wire mclk_mdb_out_nxt = mclk; +`endif + +always @(posedge mclk_mdb_out_nxt or posedge puc_rst) + if (puc_rst) mdb_out_nxt <= 16'h0000; + else if (e_state==`E_DST_RD) mdb_out_nxt <= pc_nxt; +`ifdef CLOCK_GATING + else mdb_out_nxt <= alu_out; +`else + else if ((e_state==`E_EXEC & ~inst_so[`CALL]) | + (e_state==`E_IRQ_0) | (e_state==`E_IRQ_2)) mdb_out_nxt <= alu_out; +`endif + +assign mdb_out = inst_bw ? {2{mdb_out_nxt[7:0]}} : mdb_out_nxt; + +// Format memory data bus input depending on BW +reg mab_lsb; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) mab_lsb <= 1'b0; + else if (mb_en) mab_lsb <= alu_out_add[0]; + +assign mdb_in_bw = ~inst_bw ? mdb_in : + mab_lsb ? {2{mdb_in[15:8]}} : mdb_in; + +// Memory data bus input buffer (buffer after a source read) +reg mdb_in_buf_en; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) mdb_in_buf_en <= 1'b0; + else mdb_in_buf_en <= (e_state==`E_SRC_RD); + +reg mdb_in_buf_valid; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) mdb_in_buf_valid <= 1'b0; + else if (e_state==`E_EXEC) mdb_in_buf_valid <= 1'b0; + else if (mdb_in_buf_en) mdb_in_buf_valid <= 1'b1; + +reg [15:0] mdb_in_buf; + +`ifdef CLOCK_GATING +wire mclk_mdb_in_buf; +omsp_clock_gate clock_gate_mdb_in_buf (.gclk(mclk_mdb_in_buf), + .clk (mclk), .enable(mdb_in_buf_en), .scan_enable(scan_enable)); +`else +wire mclk_mdb_in_buf = mclk; +`endif + +always @(posedge mclk_mdb_in_buf or posedge puc_rst) + if (puc_rst) mdb_in_buf <= 16'h0000; +`ifdef CLOCK_GATING + else mdb_in_buf <= mdb_in_bw; +`else + else if (mdb_in_buf_en) mdb_in_buf <= mdb_in_bw; +`endif + +assign mdb_in_val = mdb_in_buf_valid ? mdb_in_buf : mdb_in_bw; + + +endmodule // omsp_execution_unit + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif diff --git a/tests/openmsp430/rtl/omsp_frontend.v b/tests/openmsp430/rtl/omsp_frontend.v new file mode 100644 index 00000000..343944bd --- /dev/null +++ b/tests/openmsp430/rtl/omsp_frontend.v @@ -0,0 +1,966 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_frontend.v +// +// *Module Description: +// openMSP430 Instruction fetch and decode unit +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 134 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2012-03-22 21:31:06 +0100 (Thu, 22 Mar 2012) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module omsp_frontend ( + +// OUTPUTs + dbg_halt_st, // Halt/Run status from CPU + decode_noirq, // Frontend decode instruction + e_state, // Execution state + exec_done, // Execution completed + inst_ad, // Decoded Inst: destination addressing mode + inst_as, // Decoded Inst: source addressing mode + inst_alu, // ALU control signals + inst_bw, // Decoded Inst: byte width + inst_dest, // Decoded Inst: destination (one hot) + inst_dext, // Decoded Inst: destination extended instruction word + inst_irq_rst, // Decoded Inst: Reset interrupt + inst_jmp, // Decoded Inst: Conditional jump + inst_mov, // Decoded Inst: mov instruction + inst_sext, // Decoded Inst: source extended instruction word + inst_so, // Decoded Inst: Single-operand arithmetic + inst_src, // Decoded Inst: source (one hot) + inst_type, // Decoded Instruction type + irq_acc, // Interrupt request accepted (one-hot signal) + mab, // Frontend Memory address bus + mb_en, // Frontend Memory bus enable + mclk_enable, // Main System Clock enable + mclk_wkup, // Main System Clock wake-up (asynchronous) + nmi_acc, // Non-Maskable interrupt request accepted + pc, // Program counter + pc_nxt, // Next PC value (for CALL & IRQ) + +// INPUTs + cpu_en_s, // Enable CPU code execution (synchronous) + cpuoff, // Turns off the CPU + dbg_halt_cmd, // Halt CPU command + dbg_reg_sel, // Debug selected register for rd/wr access + fe_pmem_wait, // Frontend wait for Instruction fetch + gie, // General interrupt enable + irq, // Maskable interrupts + mclk, // Main system clock + mdb_in, // Frontend Memory data bus input + nmi_pnd, // Non-maskable interrupt pending + nmi_wkup, // NMI Wakeup + pc_sw, // Program counter software value + pc_sw_wr, // Program counter software write + puc_rst, // Main system reset + scan_enable, // Scan enable (active during scan shifting) + wdt_irq, // Watchdog-timer interrupt + wdt_wkup, // Watchdog Wakeup + wkup // System Wake-up (asynchronous) +); + +// OUTPUTs +//========= +output dbg_halt_st; // Halt/Run status from CPU +output decode_noirq; // Frontend decode instruction +output [3:0] e_state; // Execution state +output exec_done; // Execution completed +output [7:0] inst_ad; // Decoded Inst: destination addressing mode +output [7:0] inst_as; // Decoded Inst: source addressing mode +output [11:0] inst_alu; // ALU control signals +output inst_bw; // Decoded Inst: byte width +output [15:0] inst_dest; // Decoded Inst: destination (one hot) +output [15:0] inst_dext; // Decoded Inst: destination extended instruction word +output inst_irq_rst; // Decoded Inst: Reset interrupt +output [7:0] inst_jmp; // Decoded Inst: Conditional jump +output inst_mov; // Decoded Inst: mov instruction +output [15:0] inst_sext; // Decoded Inst: source extended instruction word +output [7:0] inst_so; // Decoded Inst: Single-operand arithmetic +output [15:0] inst_src; // Decoded Inst: source (one hot) +output [2:0] inst_type; // Decoded Instruction type +output [13:0] irq_acc; // Interrupt request accepted (one-hot signal) +output [15:0] mab; // Frontend Memory address bus +output mb_en; // Frontend Memory bus enable +output mclk_enable; // Main System Clock enable +output mclk_wkup; // Main System Clock wake-up (asynchronous) +output nmi_acc; // Non-Maskable interrupt request accepted +output [15:0] pc; // Program counter +output [15:0] pc_nxt; // Next PC value (for CALL & IRQ) + +// INPUTs +//========= +input cpu_en_s; // Enable CPU code execution (synchronous) +input cpuoff; // Turns off the CPU +input dbg_halt_cmd; // Halt CPU command +input [3:0] dbg_reg_sel; // Debug selected register for rd/wr access +input fe_pmem_wait; // Frontend wait for Instruction fetch +input gie; // General interrupt enable +input [13:0] irq; // Maskable interrupts +input mclk; // Main system clock +input [15:0] mdb_in; // Frontend Memory data bus input +input nmi_pnd; // Non-maskable interrupt pending +input nmi_wkup; // NMI Wakeup +input [15:0] pc_sw; // Program counter software value +input pc_sw_wr; // Program counter software write +input puc_rst; // Main system reset +input scan_enable; // Scan enable (active during scan shifting) +input wdt_irq; // Watchdog-timer interrupt +input wdt_wkup; // Watchdog Wakeup +input wkup; // System Wake-up (asynchronous) + + +//============================================================================= +// 1) UTILITY FUNCTIONS +//============================================================================= + +// 16 bits one-hot decoder +function [15:0] one_hot16; + input [3:0] binary; + begin + one_hot16 = 16'h0000; + one_hot16[binary] = 1'b1; + end +endfunction + +// 8 bits one-hot decoder +function [7:0] one_hot8; + input [2:0] binary; + begin + one_hot8 = 8'h00; + one_hot8[binary] = 1'b1; + end +endfunction + + +//============================================================================= +// 2) PARAMETER DEFINITIONS +//============================================================================= + +// +// 2.1) Instruction State machine definitons +//------------------------------------------- + +parameter I_IRQ_FETCH = `I_IRQ_FETCH; +parameter I_IRQ_DONE = `I_IRQ_DONE; +parameter I_DEC = `I_DEC; // New instruction ready for decode +parameter I_EXT1 = `I_EXT1; // 1st Extension word +parameter I_EXT2 = `I_EXT2; // 2nd Extension word +parameter I_IDLE = `I_IDLE; // CPU is in IDLE mode + +// +// 2.2) Execution State machine definitons +//------------------------------------------- + +parameter E_IRQ_0 = `E_IRQ_0; +parameter E_IRQ_1 = `E_IRQ_1; +parameter E_IRQ_2 = `E_IRQ_2; +parameter E_IRQ_3 = `E_IRQ_3; +parameter E_IRQ_4 = `E_IRQ_4; +parameter E_SRC_AD = `E_SRC_AD; +parameter E_SRC_RD = `E_SRC_RD; +parameter E_SRC_WR = `E_SRC_WR; +parameter E_DST_AD = `E_DST_AD; +parameter E_DST_RD = `E_DST_RD; +parameter E_DST_WR = `E_DST_WR; +parameter E_EXEC = `E_EXEC; +parameter E_JUMP = `E_JUMP; +parameter E_IDLE = `E_IDLE; + + +//============================================================================= +// 3) FRONTEND STATE MACHINE +//============================================================================= + +// The wire "conv" is used as state bits to calculate the next response +reg [2:0] i_state; +reg [2:0] i_state_nxt; + +reg [1:0] inst_sz; +wire [1:0] inst_sz_nxt; +wire irq_detect; +wire [2:0] inst_type_nxt; +wire is_const; +reg [15:0] sconst_nxt; +reg [3:0] e_state_nxt; + +// CPU on/off through the debug interface or cpu_en port +wire cpu_halt_cmd = dbg_halt_cmd | ~cpu_en_s; + +// States Transitions +always @(i_state or inst_sz or inst_sz_nxt or pc_sw_wr or exec_done or + irq_detect or cpuoff or cpu_halt_cmd or e_state) + case(i_state) + I_IDLE : i_state_nxt = (irq_detect & ~cpu_halt_cmd) ? I_IRQ_FETCH : + (~cpuoff & ~cpu_halt_cmd) ? I_DEC : I_IDLE; + I_IRQ_FETCH: i_state_nxt = I_IRQ_DONE; + I_IRQ_DONE : i_state_nxt = I_DEC; + I_DEC : i_state_nxt = irq_detect ? I_IRQ_FETCH : + (cpuoff | cpu_halt_cmd) & exec_done ? I_IDLE : + cpu_halt_cmd & (e_state==E_IDLE) ? I_IDLE : + pc_sw_wr ? I_DEC : + ~exec_done & ~(e_state==E_IDLE) ? I_DEC : // Wait in decode state + (inst_sz_nxt!=2'b00) ? I_EXT1 : I_DEC; // until execution is completed + I_EXT1 : i_state_nxt = pc_sw_wr ? I_DEC : + (inst_sz!=2'b01) ? I_EXT2 : I_DEC; + I_EXT2 : i_state_nxt = I_DEC; + // pragma coverage off + default : i_state_nxt = I_IRQ_FETCH; + // pragma coverage on + endcase + +// State machine +always @(posedge mclk or posedge puc_rst) + if (puc_rst) i_state <= I_IRQ_FETCH; + else i_state <= i_state_nxt; + +// Utility signals +wire decode_noirq = ((i_state==I_DEC) & (exec_done | (e_state==E_IDLE))); +wire decode = decode_noirq | irq_detect; +wire fetch = ~((i_state==I_DEC) & ~(exec_done | (e_state==E_IDLE))) & ~(e_state_nxt==E_IDLE); + +// Debug interface cpu status +reg dbg_halt_st; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) dbg_halt_st <= 1'b0; + else dbg_halt_st <= cpu_halt_cmd & (i_state_nxt==I_IDLE); + + +//============================================================================= +// 4) INTERRUPT HANDLING & SYSTEM WAKEUP +//============================================================================= + +// +// 4.1) INTERRUPT HANDLING +//----------------------------------------- + +// Detect reset interrupt +reg inst_irq_rst; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) inst_irq_rst <= 1'b1; + else if (exec_done) inst_irq_rst <= 1'b0; + +// Detect other interrupts +assign irq_detect = (nmi_pnd | ((|irq | wdt_irq) & gie)) & ~cpu_halt_cmd & ~dbg_halt_st & (exec_done | (i_state==I_IDLE)); + +`ifdef CLOCK_GATING +wire mclk_irq_num; +omsp_clock_gate clock_gate_irq_num (.gclk(mclk_irq_num), + .clk (mclk), .enable(irq_detect), .scan_enable(scan_enable)); +`else +wire mclk_irq_num = mclk; +`endif + +// Select interrupt vector +reg [3:0] irq_num; +always @(posedge mclk_irq_num or posedge puc_rst) + if (puc_rst) irq_num <= 4'hf; +`ifdef CLOCK_GATING + else irq_num <= nmi_pnd ? 4'he : +`else + else if (irq_detect) irq_num <= nmi_pnd ? 4'he : +`endif + irq[13] ? 4'hd : + irq[12] ? 4'hc : + irq[11] ? 4'hb : + (irq[10] | wdt_irq) ? 4'ha : + irq[9] ? 4'h9 : + irq[8] ? 4'h8 : + irq[7] ? 4'h7 : + irq[6] ? 4'h6 : + irq[5] ? 4'h5 : + irq[4] ? 4'h4 : + irq[3] ? 4'h3 : + irq[2] ? 4'h2 : + irq[1] ? 4'h1 : + irq[0] ? 4'h0 : 4'hf; + +wire [15:0] irq_addr = {11'h7ff, irq_num, 1'b0}; + +// Interrupt request accepted +wire [15:0] irq_acc_all = one_hot16(irq_num) & {16{(i_state==I_IRQ_FETCH)}}; +wire [13:0] irq_acc = irq_acc_all[13:0]; +wire nmi_acc = irq_acc_all[14]; + +// +// 4.2) SYSTEM WAKEUP +//----------------------------------------- +`ifdef CPUOFF_EN + +// Generate the main system clock enable signal + // Keep the clock running if: +wire mclk_enable = inst_irq_rst ? cpu_en_s : // - the RESET interrupt is currently executing + // and if the CPU is enabled + // otherwise if: + ~((cpuoff | ~cpu_en_s) & // - the CPUOFF flag, cpu_en command, instruction + (i_state==I_IDLE) & // and execution state machines are all two + (e_state==E_IDLE)); // not idle. + + +// Wakeup condition from maskable interrupts +wire mirq_wkup; +omsp_and_gate and_mirq_wkup (.y(mirq_wkup), .a(wkup | wdt_wkup), .b(gie)); + +// Combined asynchronous wakeup detection from nmi & irq (masked if the cpu is disabled) +omsp_and_gate and_mclk_wkup (.y(mclk_wkup), .a(nmi_wkup | mirq_wkup), .b(cpu_en_s)); + +`else + +// In the CPUOFF feature is disabled, the wake-up and enable signals are always 1 +assign mclk_wkup = 1'b1; +assign mclk_enable = 1'b1; +`endif + +//============================================================================= +// 5) FETCH INSTRUCTION +//============================================================================= + +// +// 5.1) PROGRAM COUNTER & MEMORY INTERFACE +//----------------------------------------- + +// Program counter +reg [15:0] pc; + +// Compute next PC value +wire [15:0] pc_incr = pc + {14'h0000, fetch, 1'b0}; +wire [15:0] pc_nxt = pc_sw_wr ? pc_sw : + (i_state==I_IRQ_FETCH) ? irq_addr : + (i_state==I_IRQ_DONE) ? mdb_in : pc_incr; + +`ifdef CLOCK_GATING +wire pc_en = fetch | + pc_sw_wr | + (i_state==I_IRQ_FETCH) | + (i_state==I_IRQ_DONE); +wire mclk_pc; +omsp_clock_gate clock_gate_pc (.gclk(mclk_pc), + .clk (mclk), .enable(pc_en), .scan_enable(scan_enable)); +`else +wire mclk_pc = mclk; +`endif + +always @(posedge mclk_pc or posedge puc_rst) + if (puc_rst) pc <= 16'h0000; + else pc <= pc_nxt; + +// Check if ROM has been busy in order to retry ROM access +reg pmem_busy; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) pmem_busy <= 1'b0; + else pmem_busy <= fe_pmem_wait; + +// Memory interface +wire [15:0] mab = pc_nxt; +wire mb_en = fetch | pc_sw_wr | (i_state==I_IRQ_FETCH) | pmem_busy | (dbg_halt_st & ~cpu_halt_cmd); + + +// +// 5.2) INSTRUCTION REGISTER +//-------------------------------- + +// Instruction register +wire [15:0] ir = mdb_in; + +// Detect if source extension word is required +wire is_sext = (inst_as[`IDX] | inst_as[`SYMB] | inst_as[`ABS] | inst_as[`IMM]); + +// For the Symbolic addressing mode, add -2 to the extension word in order +// to make up for the PC address +wire [15:0] ext_incr = ((i_state==I_EXT1) & inst_as[`SYMB]) | + ((i_state==I_EXT2) & inst_ad[`SYMB]) | + ((i_state==I_EXT1) & ~inst_as[`SYMB] & + ~(i_state_nxt==I_EXT2) & inst_ad[`SYMB]) ? 16'hfffe : 16'h0000; + +wire [15:0] ext_nxt = ir + ext_incr; + +// Store source extension word +reg [15:0] inst_sext; + +`ifdef CLOCK_GATING +wire inst_sext_en = (decode & is_const) | + (decode & inst_type_nxt[`INST_JMP]) | + ((i_state==I_EXT1) & is_sext); +wire mclk_inst_sext; +omsp_clock_gate clock_gate_inst_sext (.gclk(mclk_inst_sext), + .clk (mclk), .enable(inst_sext_en), .scan_enable(scan_enable)); +`else +wire mclk_inst_sext = mclk; +`endif + +always @(posedge mclk_inst_sext or posedge puc_rst) + if (puc_rst) inst_sext <= 16'h0000; + else if (decode & is_const) inst_sext <= sconst_nxt; + else if (decode & inst_type_nxt[`INST_JMP]) inst_sext <= {{5{ir[9]}},ir[9:0],1'b0}; +`ifdef CLOCK_GATING + else inst_sext <= ext_nxt; +`else + else if ((i_state==I_EXT1) & is_sext) inst_sext <= ext_nxt; +`endif + +// Source extension word is ready +wire inst_sext_rdy = (i_state==I_EXT1) & is_sext; + + +// Store destination extension word +reg [15:0] inst_dext; + +`ifdef CLOCK_GATING +wire inst_dext_en = ((i_state==I_EXT1) & ~is_sext) | + (i_state==I_EXT2); +wire mclk_inst_dext; +omsp_clock_gate clock_gate_inst_dext (.gclk(mclk_inst_dext), + .clk (mclk), .enable(inst_dext_en), .scan_enable(scan_enable)); +`else +wire mclk_inst_dext = mclk; +`endif + +always @(posedge mclk_inst_dext or posedge puc_rst) + if (puc_rst) inst_dext <= 16'h0000; + else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt; +`ifdef CLOCK_GATING + else inst_dext <= ext_nxt; +`else + else if (i_state==I_EXT2) inst_dext <= ext_nxt; +`endif + +// Destination extension word is ready +wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2)); + + +//============================================================================= +// 6) DECODE INSTRUCTION +//============================================================================= + +`ifdef CLOCK_GATING +wire mclk_decode; +omsp_clock_gate clock_gate_decode (.gclk(mclk_decode), + .clk (mclk), .enable(decode), .scan_enable(scan_enable)); +`else +wire mclk_decode = mclk; +`endif + +// +// 6.1) OPCODE: INSTRUCTION TYPE +//---------------------------------------- +// Instructions type is encoded in a one hot fashion as following: +// +// 3'b001: Single-operand arithmetic +// 3'b010: Conditional jump +// 3'b100: Two-operand arithmetic + +reg [2:0] inst_type; +assign inst_type_nxt = {(ir[15:14]!=2'b00), + (ir[15:13]==3'b001), + (ir[15:13]==3'b000)} & {3{~irq_detect}}; + +always @(posedge mclk_decode or posedge puc_rst) + if (puc_rst) inst_type <= 3'b000; +`ifdef CLOCK_GATING + else inst_type <= inst_type_nxt; +`else + else if (decode) inst_type <= inst_type_nxt; +`endif + +// +// 6.2) OPCODE: SINGLE-OPERAND ARITHMETIC +//---------------------------------------- +// Instructions are encoded in a one hot fashion as following: +// +// 8'b00000001: RRC +// 8'b00000010: SWPB +// 8'b00000100: RRA +// 8'b00001000: SXT +// 8'b00010000: PUSH +// 8'b00100000: CALL +// 8'b01000000: RETI +// 8'b10000000: IRQ + +reg [7:0] inst_so; +wire [7:0] inst_so_nxt = irq_detect ? 8'h80 : (one_hot8(ir[9:7]) & {8{inst_type_nxt[`INST_SO]}}); + +always @(posedge mclk_decode or posedge puc_rst) + if (puc_rst) inst_so <= 8'h00; +`ifdef CLOCK_GATING + else inst_so <= inst_so_nxt; +`else + else if (decode) inst_so <= inst_so_nxt; +`endif + +// +// 6.3) OPCODE: CONDITIONAL JUMP +//-------------------------------- +// Instructions are encoded in a one hot fashion as following: +// +// 8'b00000001: JNE/JNZ +// 8'b00000010: JEQ/JZ +// 8'b00000100: JNC/JLO +// 8'b00001000: JC/JHS +// 8'b00010000: JN +// 8'b00100000: JGE +// 8'b01000000: JL +// 8'b10000000: JMP + +reg [2:0] inst_jmp_bin; +always @(posedge mclk_decode or posedge puc_rst) + if (puc_rst) inst_jmp_bin <= 3'h0; +`ifdef CLOCK_GATING + else inst_jmp_bin <= ir[12:10]; +`else + else if (decode) inst_jmp_bin <= ir[12:10]; +`endif + +wire [7:0] inst_jmp = one_hot8(inst_jmp_bin) & {8{inst_type[`INST_JMP]}}; + + +// +// 6.4) OPCODE: TWO-OPERAND ARITHMETIC +//------------------------------------- +// Instructions are encoded in a one hot fashion as following: +// +// 12'b000000000001: MOV +// 12'b000000000010: ADD +// 12'b000000000100: ADDC +// 12'b000000001000: SUBC +// 12'b000000010000: SUB +// 12'b000000100000: CMP +// 12'b000001000000: DADD +// 12'b000010000000: BIT +// 12'b000100000000: BIC +// 12'b001000000000: BIS +// 12'b010000000000: XOR +// 12'b100000000000: AND + +wire [15:0] inst_to_1hot = one_hot16(ir[15:12]) & {16{inst_type_nxt[`INST_TO]}}; +wire [11:0] inst_to_nxt = inst_to_1hot[15:4]; + +reg inst_mov; +always @(posedge mclk_decode or posedge puc_rst) + if (puc_rst) inst_mov <= 1'b0; +`ifdef CLOCK_GATING + else inst_mov <= inst_to_nxt[`MOV]; +`else + else if (decode) inst_mov <= inst_to_nxt[`MOV]; +`endif + + +// +// 6.5) SOURCE AND DESTINATION REGISTERS +//--------------------------------------- + +// Destination register +reg [3:0] inst_dest_bin; +always @(posedge mclk_decode or posedge puc_rst) + if (puc_rst) inst_dest_bin <= 4'h0; +`ifdef CLOCK_GATING + else inst_dest_bin <= ir[3:0]; +`else + else if (decode) inst_dest_bin <= ir[3:0]; +`endif + +wire [15:0] inst_dest = dbg_halt_st ? one_hot16(dbg_reg_sel) : + inst_type[`INST_JMP] ? 16'h0001 : + inst_so[`IRQ] | + inst_so[`PUSH] | + inst_so[`CALL] ? 16'h0002 : + one_hot16(inst_dest_bin); + + +// Source register +reg [3:0] inst_src_bin; +always @(posedge mclk_decode or posedge puc_rst) + if (puc_rst) inst_src_bin <= 4'h0; +`ifdef CLOCK_GATING + else inst_src_bin <= ir[11:8]; +`else + else if (decode) inst_src_bin <= ir[11:8]; +`endif + +wire [15:0] inst_src = inst_type[`INST_TO] ? one_hot16(inst_src_bin) : + inst_so[`RETI] ? 16'h0002 : + inst_so[`IRQ] ? 16'h0001 : + inst_type[`INST_SO] ? one_hot16(inst_dest_bin) : 16'h0000; + + +// +// 6.6) SOURCE ADDRESSING MODES +//-------------------------------- +// Source addressing modes are encoded in a one hot fashion as following: +// +// 13'b0000000000001: Register direct. +// 13'b0000000000010: Register indexed. +// 13'b0000000000100: Register indirect. +// 13'b0000000001000: Register indirect autoincrement. +// 13'b0000000010000: Symbolic (operand is in memory at address PC+x). +// 13'b0000000100000: Immediate (operand is next word in the instruction stream). +// 13'b0000001000000: Absolute (operand is in memory at address x). +// 13'b0000010000000: Constant 4. +// 13'b0000100000000: Constant 8. +// 13'b0001000000000: Constant 0. +// 13'b0010000000000: Constant 1. +// 13'b0100000000000: Constant 2. +// 13'b1000000000000: Constant -1. + +reg [12:0] inst_as_nxt; + +wire [3:0] src_reg = inst_type_nxt[`INST_SO] ? ir[3:0] : ir[11:8]; + +always @(src_reg or ir or inst_type_nxt) + begin + if (inst_type_nxt[`INST_JMP]) + inst_as_nxt = 13'b0000000000001; + else if (src_reg==4'h3) // Addressing mode using R3 + case (ir[5:4]) + 2'b11 : inst_as_nxt = 13'b1000000000000; + 2'b10 : inst_as_nxt = 13'b0100000000000; + 2'b01 : inst_as_nxt = 13'b0010000000000; + default: inst_as_nxt = 13'b0001000000000; + endcase + else if (src_reg==4'h2) // Addressing mode using R2 + case (ir[5:4]) + 2'b11 : inst_as_nxt = 13'b0000100000000; + 2'b10 : inst_as_nxt = 13'b0000010000000; + 2'b01 : inst_as_nxt = 13'b0000001000000; + default: inst_as_nxt = 13'b0000000000001; + endcase + else if (src_reg==4'h0) // Addressing mode using R0 + case (ir[5:4]) + 2'b11 : inst_as_nxt = 13'b0000000100000; + 2'b10 : inst_as_nxt = 13'b0000000000100; + 2'b01 : inst_as_nxt = 13'b0000000010000; + default: inst_as_nxt = 13'b0000000000001; + endcase + else // General Addressing mode + case (ir[5:4]) + 2'b11 : inst_as_nxt = 13'b0000000001000; + 2'b10 : inst_as_nxt = 13'b0000000000100; + 2'b01 : inst_as_nxt = 13'b0000000000010; + default: inst_as_nxt = 13'b0000000000001; + endcase + end +assign is_const = |inst_as_nxt[12:7]; + +reg [7:0] inst_as; +always @(posedge mclk_decode or posedge puc_rst) + if (puc_rst) inst_as <= 8'h00; +`ifdef CLOCK_GATING + else inst_as <= {is_const, inst_as_nxt[6:0]}; +`else + else if (decode) inst_as <= {is_const, inst_as_nxt[6:0]}; +`endif + + +// 13'b0000010000000: Constant 4. +// 13'b0000100000000: Constant 8. +// 13'b0001000000000: Constant 0. +// 13'b0010000000000: Constant 1. +// 13'b0100000000000: Constant 2. +// 13'b1000000000000: Constant -1. +always @(inst_as_nxt) + begin + if (inst_as_nxt[7]) sconst_nxt = 16'h0004; + else if (inst_as_nxt[8]) sconst_nxt = 16'h0008; + else if (inst_as_nxt[9]) sconst_nxt = 16'h0000; + else if (inst_as_nxt[10]) sconst_nxt = 16'h0001; + else if (inst_as_nxt[11]) sconst_nxt = 16'h0002; + else if (inst_as_nxt[12]) sconst_nxt = 16'hffff; + else sconst_nxt = 16'h0000; + end + + +// +// 6.7) DESTINATION ADDRESSING MODES +//----------------------------------- +// Destination addressing modes are encoded in a one hot fashion as following: +// +// 8'b00000001: Register direct. +// 8'b00000010: Register indexed. +// 8'b00010000: Symbolic (operand is in memory at address PC+x). +// 8'b01000000: Absolute (operand is in memory at address x). + +reg [7:0] inst_ad_nxt; + +wire [3:0] dest_reg = ir[3:0]; + +always @(dest_reg or ir or inst_type_nxt) + begin + if (~inst_type_nxt[`INST_TO]) + inst_ad_nxt = 8'b00000000; + else if (dest_reg==4'h2) // Addressing mode using R2 + case (ir[7]) + 1'b1 : inst_ad_nxt = 8'b01000000; + default: inst_ad_nxt = 8'b00000001; + endcase + else if (dest_reg==4'h0) // Addressing mode using R0 + case (ir[7]) + 1'b1 : inst_ad_nxt = 8'b00010000; + default: inst_ad_nxt = 8'b00000001; + endcase + else // General Addressing mode + case (ir[7]) + 1'b1 : inst_ad_nxt = 8'b00000010; + default: inst_ad_nxt = 8'b00000001; + endcase + end + +reg [7:0] inst_ad; +always @(posedge mclk_decode or posedge puc_rst) + if (puc_rst) inst_ad <= 8'h00; +`ifdef CLOCK_GATING + else inst_ad <= inst_ad_nxt; +`else + else if (decode) inst_ad <= inst_ad_nxt; +`endif + + +// +// 6.8) REMAINING INSTRUCTION DECODING +//------------------------------------- + +// Operation size +reg inst_bw; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) inst_bw <= 1'b0; + else if (decode) inst_bw <= ir[6] & ~inst_type_nxt[`INST_JMP] & ~irq_detect & ~cpu_halt_cmd; + +// Extended instruction size +assign inst_sz_nxt = {1'b0, (inst_as_nxt[`IDX] | inst_as_nxt[`SYMB] | inst_as_nxt[`ABS] | inst_as_nxt[`IMM])} + + {1'b0, ((inst_ad_nxt[`IDX] | inst_ad_nxt[`SYMB] | inst_ad_nxt[`ABS]) & ~inst_type_nxt[`INST_SO])}; +always @(posedge mclk_decode or posedge puc_rst) + if (puc_rst) inst_sz <= 2'b00; +`ifdef CLOCK_GATING + else inst_sz <= inst_sz_nxt; +`else + else if (decode) inst_sz <= inst_sz_nxt; +`endif + + +//============================================================================= +// 7) EXECUTION-UNIT STATE MACHINE +//============================================================================= + +// State machine registers +reg [3:0] e_state; + + +// State machine control signals +//-------------------------------- + +wire src_acalc_pre = inst_as_nxt[`IDX] | inst_as_nxt[`SYMB] | inst_as_nxt[`ABS]; +wire src_rd_pre = inst_as_nxt[`INDIR] | inst_as_nxt[`INDIR_I] | inst_as_nxt[`IMM] | inst_so_nxt[`RETI]; +wire dst_acalc_pre = inst_ad_nxt[`IDX] | inst_ad_nxt[`SYMB] | inst_ad_nxt[`ABS]; +wire dst_acalc = inst_ad[`IDX] | inst_ad[`SYMB] | inst_ad[`ABS]; +wire dst_rd_pre = inst_ad_nxt[`IDX] | inst_so_nxt[`PUSH] | inst_so_nxt[`CALL] | inst_so_nxt[`RETI]; +wire dst_rd = inst_ad[`IDX] | inst_so[`PUSH] | inst_so[`CALL] | inst_so[`RETI]; + +wire inst_branch = (inst_ad_nxt[`DIR] & (ir[3:0]==4'h0)) | inst_type_nxt[`INST_JMP] | inst_so_nxt[`RETI]; + +reg exec_jmp; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) exec_jmp <= 1'b0; + else if (inst_branch & decode) exec_jmp <= 1'b1; + else if (e_state==E_JUMP) exec_jmp <= 1'b0; + +reg exec_dst_wr; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) exec_dst_wr <= 1'b0; + else if (e_state==E_DST_RD) exec_dst_wr <= 1'b1; + else if (e_state==E_DST_WR) exec_dst_wr <= 1'b0; + +reg exec_src_wr; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) exec_src_wr <= 1'b0; + else if (inst_type[`INST_SO] & (e_state==E_SRC_RD)) exec_src_wr <= 1'b1; + else if ((e_state==E_SRC_WR) || (e_state==E_DST_WR)) exec_src_wr <= 1'b0; + +reg exec_dext_rdy; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) exec_dext_rdy <= 1'b0; + else if (e_state==E_DST_RD) exec_dext_rdy <= 1'b0; + else if (inst_dext_rdy) exec_dext_rdy <= 1'b1; + +// Execution first state +wire [3:0] e_first_state = ~dbg_halt_st & inst_so_nxt[`IRQ] ? E_IRQ_0 : + cpu_halt_cmd | (i_state==I_IDLE) ? E_IDLE : + cpuoff ? E_IDLE : + src_acalc_pre ? E_SRC_AD : + src_rd_pre ? E_SRC_RD : + dst_acalc_pre ? E_DST_AD : + dst_rd_pre ? E_DST_RD : E_EXEC; + + +// State machine +//-------------------------------- + +// States Transitions +always @(e_state or dst_acalc or dst_rd or inst_sext_rdy or + inst_dext_rdy or exec_dext_rdy or exec_jmp or exec_dst_wr or + e_first_state or exec_src_wr) + case(e_state) + E_IDLE : e_state_nxt = e_first_state; + E_IRQ_0 : e_state_nxt = E_IRQ_1; + E_IRQ_1 : e_state_nxt = E_IRQ_2; + E_IRQ_2 : e_state_nxt = E_IRQ_3; + E_IRQ_3 : e_state_nxt = E_IRQ_4; + E_IRQ_4 : e_state_nxt = E_EXEC; + + E_SRC_AD : e_state_nxt = inst_sext_rdy ? E_SRC_RD : E_SRC_AD; + + E_SRC_RD : e_state_nxt = dst_acalc ? E_DST_AD : + dst_rd ? E_DST_RD : E_EXEC; + + E_DST_AD : e_state_nxt = (inst_dext_rdy | + exec_dext_rdy) ? E_DST_RD : E_DST_AD; + + E_DST_RD : e_state_nxt = E_EXEC; + + E_EXEC : e_state_nxt = exec_dst_wr ? E_DST_WR : + exec_jmp ? E_JUMP : + exec_src_wr ? E_SRC_WR : e_first_state; + + E_JUMP : e_state_nxt = e_first_state; + E_DST_WR : e_state_nxt = exec_jmp ? E_JUMP : e_first_state; + E_SRC_WR : e_state_nxt = e_first_state; + // pragma coverage off + default : e_state_nxt = E_IRQ_0; + // pragma coverage on + endcase + +// State machine +always @(posedge mclk or posedge puc_rst) + if (puc_rst) e_state <= E_IRQ_1; + else e_state <= e_state_nxt; + + +// Frontend State machine control signals +//---------------------------------------- + +wire exec_done = exec_jmp ? (e_state==E_JUMP) : + exec_dst_wr ? (e_state==E_DST_WR) : + exec_src_wr ? (e_state==E_SRC_WR) : (e_state==E_EXEC); + + +//============================================================================= +// 8) EXECUTION-UNIT STATE CONTROL +//============================================================================= + +// +// 8.1) ALU CONTROL SIGNALS +//------------------------------------- +// +// 12'b000000000001: Enable ALU source inverter +// 12'b000000000010: Enable Incrementer +// 12'b000000000100: Enable Incrementer on carry bit +// 12'b000000001000: Select Adder +// 12'b000000010000: Select AND +// 12'b000000100000: Select OR +// 12'b000001000000: Select XOR +// 12'b000010000000: Select DADD +// 12'b000100000000: Update N, Z & C (C=~Z) +// 12'b001000000000: Update all status bits +// 12'b010000000000: Update status bit for XOR instruction +// 12'b100000000000: Don't write to destination + +reg [11:0] inst_alu; + +wire alu_src_inv = inst_to_nxt[`SUB] | inst_to_nxt[`SUBC] | + inst_to_nxt[`CMP] | inst_to_nxt[`BIC] ; + +wire alu_inc = inst_to_nxt[`SUB] | inst_to_nxt[`CMP]; + +wire alu_inc_c = inst_to_nxt[`ADDC] | inst_to_nxt[`DADD] | + inst_to_nxt[`SUBC]; + +wire alu_add = inst_to_nxt[`ADD] | inst_to_nxt[`ADDC] | + inst_to_nxt[`SUB] | inst_to_nxt[`SUBC] | + inst_to_nxt[`CMP] | inst_type_nxt[`INST_JMP] | + inst_so_nxt[`RETI]; + + +wire alu_and = inst_to_nxt[`AND] | inst_to_nxt[`BIC] | + inst_to_nxt[`BIT]; + +wire alu_or = inst_to_nxt[`BIS]; + +wire alu_xor = inst_to_nxt[`XOR]; + +wire alu_dadd = inst_to_nxt[`DADD]; + +wire alu_stat_7 = inst_to_nxt[`BIT] | inst_to_nxt[`AND] | + inst_so_nxt[`SXT]; + +wire alu_stat_f = inst_to_nxt[`ADD] | inst_to_nxt[`ADDC] | + inst_to_nxt[`SUB] | inst_to_nxt[`SUBC] | + inst_to_nxt[`CMP] | inst_to_nxt[`DADD] | + inst_to_nxt[`BIT] | inst_to_nxt[`XOR] | + inst_to_nxt[`AND] | + inst_so_nxt[`RRC] | inst_so_nxt[`RRA] | + inst_so_nxt[`SXT]; + +wire alu_shift = inst_so_nxt[`RRC] | inst_so_nxt[`RRA]; + +wire exec_no_wr = inst_to_nxt[`CMP] | inst_to_nxt[`BIT]; + +wire [11:0] inst_alu_nxt = {exec_no_wr, + alu_shift, + alu_stat_f, + alu_stat_7, + alu_dadd, + alu_xor, + alu_or, + alu_and, + alu_add, + alu_inc_c, + alu_inc, + alu_src_inv}; + +always @(posedge mclk_decode or posedge puc_rst) + if (puc_rst) inst_alu <= 12'h000; +`ifdef CLOCK_GATING + else inst_alu <= inst_alu_nxt; +`else + else if (decode) inst_alu <= inst_alu_nxt; +`endif + + +endmodule // omsp_frontend + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif diff --git a/tests/openmsp430/rtl/omsp_mem_backbone.v b/tests/openmsp430/rtl/omsp_mem_backbone.v new file mode 100644 index 00000000..299cbff8 --- /dev/null +++ b/tests/openmsp430/rtl/omsp_mem_backbone.v @@ -0,0 +1,275 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_mem_backbone.v +// +// *Module Description: +// Memory interface backbone (decoder + arbiter) +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 151 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2012-07-23 00:24:11 +0200 (Mon, 23 Jul 2012) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module omsp_mem_backbone ( + +// OUTPUTs + dbg_mem_din, // Debug unit Memory data input + dmem_addr, // Data Memory address + dmem_cen, // Data Memory chip enable (low active) + dmem_din, // Data Memory data input + dmem_wen, // Data Memory write enable (low active) + eu_mdb_in, // Execution Unit Memory data bus input + fe_mdb_in, // Frontend Memory data bus input + fe_pmem_wait, // Frontend wait for Instruction fetch + per_addr, // Peripheral address + per_din, // Peripheral data input + per_we, // Peripheral write enable (high active) + per_en, // Peripheral enable (high active) + pmem_addr, // Program Memory address + pmem_cen, // Program Memory chip enable (low active) + pmem_din, // Program Memory data input (optional) + pmem_wen, // Program Memory write enable (low active) (optional) + +// INPUTs + dbg_halt_st, // Halt/Run status from CPU + dbg_mem_addr, // Debug address for rd/wr access + dbg_mem_dout, // Debug unit data output + dbg_mem_en, // Debug unit memory enable + dbg_mem_wr, // Debug unit memory write + dmem_dout, // Data Memory data output + eu_mab, // Execution Unit Memory address bus + eu_mb_en, // Execution Unit Memory bus enable + eu_mb_wr, // Execution Unit Memory bus write transfer + eu_mdb_out, // Execution Unit Memory data bus output + fe_mab, // Frontend Memory address bus + fe_mb_en, // Frontend Memory bus enable + mclk, // Main system clock + per_dout, // Peripheral data output + pmem_dout, // Program Memory data output + puc_rst, // Main system reset + scan_enable // Scan enable (active during scan shifting) +); + +// OUTPUTs +//========= +output [15:0] dbg_mem_din; // Debug unit Memory data input +output [`DMEM_MSB:0] dmem_addr; // Data Memory address +output dmem_cen; // Data Memory chip enable (low active) +output [15:0] dmem_din; // Data Memory data input +output [1:0] dmem_wen; // Data Memory write enable (low active) +output [15:0] eu_mdb_in; // Execution Unit Memory data bus input +output [15:0] fe_mdb_in; // Frontend Memory data bus input +output fe_pmem_wait; // Frontend wait for Instruction fetch +output [13:0] per_addr; // Peripheral address +output [15:0] per_din; // Peripheral data input +output [1:0] per_we; // Peripheral write enable (high active) +output per_en; // Peripheral enable (high active) +output [`PMEM_MSB:0] pmem_addr; // Program Memory address +output pmem_cen; // Program Memory chip enable (low active) +output [15:0] pmem_din; // Program Memory data input (optional) +output [1:0] pmem_wen; // Program Memory write enable (low active) (optional) + +// INPUTs +//========= +input dbg_halt_st; // Halt/Run status from CPU +input [15:0] dbg_mem_addr; // Debug address for rd/wr access +input [15:0] dbg_mem_dout; // Debug unit data output +input dbg_mem_en; // Debug unit memory enable +input [1:0] dbg_mem_wr; // Debug unit memory write +input [15:0] dmem_dout; // Data Memory data output +input [14:0] eu_mab; // Execution Unit Memory address bus +input eu_mb_en; // Execution Unit Memory bus enable +input [1:0] eu_mb_wr; // Execution Unit Memory bus write transfer +input [15:0] eu_mdb_out; // Execution Unit Memory data bus output +input [14:0] fe_mab; // Frontend Memory address bus +input fe_mb_en; // Frontend Memory bus enable +input mclk; // Main system clock +input [15:0] per_dout; // Peripheral data output +input [15:0] pmem_dout; // Program Memory data output +input puc_rst; // Main system reset +input scan_enable; // Scan enable (active during scan shifting) + + +//============================================================================= +// 1) DECODER +//============================================================================= + +// RAM Interface +//------------------ + +// Execution unit access +wire eu_dmem_cen = ~(eu_mb_en & (eu_mab>=(`DMEM_BASE>>1)) & + (eu_mab<((`DMEM_BASE+`DMEM_SIZE)>>1))); +wire [15:0] eu_dmem_addr = {1'b0, eu_mab}-(`DMEM_BASE>>1); + +// Debug interface access +wire dbg_dmem_cen = ~(dbg_mem_en & (dbg_mem_addr[15:1]>=(`DMEM_BASE>>1)) & + (dbg_mem_addr[15:1]<((`DMEM_BASE+`DMEM_SIZE)>>1))); +wire [15:0] dbg_dmem_addr = {1'b0, dbg_mem_addr[15:1]}-(`DMEM_BASE>>1); + + +// RAM Interface +wire [`DMEM_MSB:0] dmem_addr = ~dbg_dmem_cen ? dbg_dmem_addr[`DMEM_MSB:0] : eu_dmem_addr[`DMEM_MSB:0]; +wire dmem_cen = dbg_dmem_cen & eu_dmem_cen; +wire [1:0] dmem_wen = ~(dbg_mem_wr | eu_mb_wr); +wire [15:0] dmem_din = ~dbg_dmem_cen ? dbg_mem_dout : eu_mdb_out; + + +// ROM Interface +//------------------ +parameter PMEM_OFFSET = (16'hFFFF-`PMEM_SIZE+1); + +// Execution unit access (only read access are accepted) +wire eu_pmem_cen = ~(eu_mb_en & ~|eu_mb_wr & (eu_mab>=(PMEM_OFFSET>>1))); +wire [15:0] eu_pmem_addr = eu_mab-(PMEM_OFFSET>>1); + +// Front-end access +wire fe_pmem_cen = ~(fe_mb_en & (fe_mab>=(PMEM_OFFSET>>1))); +wire [15:0] fe_pmem_addr = fe_mab-(PMEM_OFFSET>>1); + +// Debug interface access +wire dbg_pmem_cen = ~(dbg_mem_en & (dbg_mem_addr[15:1]>=(PMEM_OFFSET>>1))); +wire [15:0] dbg_pmem_addr = {1'b0, dbg_mem_addr[15:1]}-(PMEM_OFFSET>>1); + + +// ROM Interface (Execution unit has priority) +wire [`PMEM_MSB:0] pmem_addr = ~dbg_pmem_cen ? dbg_pmem_addr[`PMEM_MSB:0] : + ~eu_pmem_cen ? eu_pmem_addr[`PMEM_MSB:0] : fe_pmem_addr[`PMEM_MSB:0]; +wire pmem_cen = fe_pmem_cen & eu_pmem_cen & dbg_pmem_cen; +wire [1:0] pmem_wen = ~dbg_mem_wr; +wire [15:0] pmem_din = dbg_mem_dout; + +wire fe_pmem_wait = (~fe_pmem_cen & ~eu_pmem_cen); + + +// Peripherals +//-------------------- +wire dbg_per_en = dbg_mem_en & (dbg_mem_addr[15:1]<(`PER_SIZE>>1)); +wire eu_per_en = eu_mb_en & (eu_mab<(`PER_SIZE>>1)); + +wire [15:0] per_din = dbg_mem_en ? dbg_mem_dout : eu_mdb_out; +wire [1:0] per_we = dbg_mem_en ? dbg_mem_wr : eu_mb_wr; +wire per_en = dbg_mem_en ? dbg_per_en : eu_per_en; +wire [`PER_MSB:0] per_addr_mux = dbg_mem_en ? dbg_mem_addr[`PER_MSB+1:1] : eu_mab[`PER_MSB:0]; +wire [14:0] per_addr_ful = {{15-`PER_AWIDTH{1'b0}}, per_addr_mux}; +wire [13:0] per_addr = per_addr_ful[13:0]; + +reg [15:0] per_dout_val; +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) per_dout_val <= 16'h0000; + else per_dout_val <= per_dout; + + +// Frontend data Mux +//--------------------------------- +// Whenever the frontend doesn't access the ROM, backup the data + +// Detect whenever the data should be backuped and restored +reg fe_pmem_cen_dly; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) fe_pmem_cen_dly <= 1'b0; + else fe_pmem_cen_dly <= fe_pmem_cen; + +wire fe_pmem_save = ( fe_pmem_cen & ~fe_pmem_cen_dly) & ~dbg_halt_st; +wire fe_pmem_restore = (~fe_pmem_cen & fe_pmem_cen_dly) | dbg_halt_st; + +`ifdef CLOCK_GATING +wire mclk_bckup; +omsp_clock_gate clock_gate_bckup (.gclk(mclk_bckup), + .clk (mclk), .enable(fe_pmem_save), .scan_enable(scan_enable)); +`else +wire mclk_bckup = mclk; +`endif + +reg [15:0] pmem_dout_bckup; +always @(posedge mclk_bckup or posedge puc_rst) + if (puc_rst) pmem_dout_bckup <= 16'h0000; +`ifdef CLOCK_GATING + else pmem_dout_bckup <= pmem_dout; +`else + else if (fe_pmem_save) pmem_dout_bckup <= pmem_dout; +`endif + +// Mux between the ROM data and the backup +reg pmem_dout_bckup_sel; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) pmem_dout_bckup_sel <= 1'b0; + else if (fe_pmem_save) pmem_dout_bckup_sel <= 1'b1; + else if (fe_pmem_restore) pmem_dout_bckup_sel <= 1'b0; + +assign fe_mdb_in = pmem_dout_bckup_sel ? pmem_dout_bckup : pmem_dout; + + +// Execution-Unit data Mux +//--------------------------------- + +// Select between peripherals, RAM and ROM +reg [1:0] eu_mdb_in_sel; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) eu_mdb_in_sel <= 2'b00; + else eu_mdb_in_sel <= {~eu_pmem_cen, per_en}; + +// Mux +assign eu_mdb_in = eu_mdb_in_sel[1] ? pmem_dout : + eu_mdb_in_sel[0] ? per_dout_val : dmem_dout; + +// Debug interface data Mux +//--------------------------------- + +// Select between peripherals, RAM and ROM +`ifdef DBG_EN +reg [1:0] dbg_mem_din_sel; +always @(posedge mclk or posedge puc_rst) + if (puc_rst) dbg_mem_din_sel <= 2'b00; + else dbg_mem_din_sel <= {~dbg_pmem_cen, dbg_per_en}; + +`else +wire [1:0] dbg_mem_din_sel = 2'b00; +`endif + +// Mux +assign dbg_mem_din = dbg_mem_din_sel[1] ? pmem_dout : + dbg_mem_din_sel[0] ? per_dout_val : dmem_dout; + + +endmodule // omsp_mem_backbone + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif diff --git a/tests/openmsp430/rtl/omsp_multiplier.v b/tests/openmsp430/rtl/omsp_multiplier.v new file mode 100644 index 00000000..4f7b04ca --- /dev/null +++ b/tests/openmsp430/rtl/omsp_multiplier.v @@ -0,0 +1,420 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_multiplier.v +// +// *Module Description: +// 16x16 Hardware multiplier. +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 23 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2009-08-30 18:39:26 +0200 (Sun, 30 Aug 2009) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module omsp_multiplier ( + +// OUTPUTs + per_dout, // Peripheral data output + +// INPUTs + mclk, // Main system clock + per_addr, // Peripheral address + per_din, // Peripheral data input + per_en, // Peripheral enable (high active) + per_we, // Peripheral write enable (high active) + puc_rst, // Main system reset + scan_enable // Scan enable (active during scan shifting) +); + +// OUTPUTs +//========= +output [15:0] per_dout; // Peripheral data output + +// INPUTs +//========= +input mclk; // Main system clock +input [13:0] per_addr; // Peripheral address +input [15:0] per_din; // Peripheral data input +input per_en; // Peripheral enable (high active) +input [1:0] per_we; // Peripheral write enable (high active) +input puc_rst; // Main system reset +input scan_enable; // Scan enable (active during scan shifting) + + +//============================================================================= +// 1) PARAMETER/REGISTERS & WIRE DECLARATION +//============================================================================= + +// Register base address (must be aligned to decoder bit width) +parameter [14:0] BASE_ADDR = 15'h0130; + +// Decoder bit width (defines how many bits are considered for address decoding) +parameter DEC_WD = 4; + +// Register addresses offset +parameter [DEC_WD-1:0] OP1_MPY = 'h0, + OP1_MPYS = 'h2, + OP1_MAC = 'h4, + OP1_MACS = 'h6, + OP2 = 'h8, + RESLO = 'hA, + RESHI = 'hC, + SUMEXT = 'hE; + +// Register one-hot decoder utilities +parameter DEC_SZ = (1 << DEC_WD); +parameter [DEC_SZ-1:0] BASE_REG = {{DEC_SZ-1{1'b0}}, 1'b1}; + +// Register one-hot decoder +parameter [DEC_SZ-1:0] OP1_MPY_D = (BASE_REG << OP1_MPY), + OP1_MPYS_D = (BASE_REG << OP1_MPYS), + OP1_MAC_D = (BASE_REG << OP1_MAC), + OP1_MACS_D = (BASE_REG << OP1_MACS), + OP2_D = (BASE_REG << OP2), + RESLO_D = (BASE_REG << RESLO), + RESHI_D = (BASE_REG << RESHI), + SUMEXT_D = (BASE_REG << SUMEXT); + + +// Wire pre-declarations +wire result_wr; +wire result_clr; +wire early_read; + + +//============================================================================ +// 2) REGISTER DECODER +//============================================================================ + +// Local register selection +wire reg_sel = per_en & (per_addr[13:DEC_WD-1]==BASE_ADDR[14:DEC_WD]); + +// Register local address +wire [DEC_WD-1:0] reg_addr = {per_addr[DEC_WD-2:0], 1'b0}; + +// Register address decode +wire [DEC_SZ-1:0] reg_dec = (OP1_MPY_D & {DEC_SZ{(reg_addr == OP1_MPY )}}) | + (OP1_MPYS_D & {DEC_SZ{(reg_addr == OP1_MPYS )}}) | + (OP1_MAC_D & {DEC_SZ{(reg_addr == OP1_MAC )}}) | + (OP1_MACS_D & {DEC_SZ{(reg_addr == OP1_MACS )}}) | + (OP2_D & {DEC_SZ{(reg_addr == OP2 )}}) | + (RESLO_D & {DEC_SZ{(reg_addr == RESLO )}}) | + (RESHI_D & {DEC_SZ{(reg_addr == RESHI )}}) | + (SUMEXT_D & {DEC_SZ{(reg_addr == SUMEXT )}}); + +// Read/Write probes +wire reg_write = |per_we & reg_sel; +wire reg_read = ~|per_we & reg_sel; + +// Read/Write vectors +wire [DEC_SZ-1:0] reg_wr = reg_dec & {DEC_SZ{reg_write}}; +wire [DEC_SZ-1:0] reg_rd = reg_dec & {DEC_SZ{reg_read}}; + + +//============================================================================ +// 3) REGISTERS +//============================================================================ + +// OP1 Register +//----------------- +reg [15:0] op1; + +wire op1_wr = reg_wr[OP1_MPY] | + reg_wr[OP1_MPYS] | + reg_wr[OP1_MAC] | + reg_wr[OP1_MACS]; + +`ifdef CLOCK_GATING +wire mclk_op1; +omsp_clock_gate clock_gate_op1 (.gclk(mclk_op1), + .clk (mclk), .enable(op1_wr), .scan_enable(scan_enable)); +`else +wire mclk_op1 = mclk; +`endif + +always @ (posedge mclk_op1 or posedge puc_rst) + if (puc_rst) op1 <= 16'h0000; +`ifdef CLOCK_GATING + else op1 <= per_din; +`else + else if (op1_wr) op1 <= per_din; +`endif + +wire [15:0] op1_rd = op1; + + +// OP2 Register +//----------------- +reg [15:0] op2; + +wire op2_wr = reg_wr[OP2]; + +`ifdef CLOCK_GATING +wire mclk_op2; +omsp_clock_gate clock_gate_op2 (.gclk(mclk_op2), + .clk (mclk), .enable(op2_wr), .scan_enable(scan_enable)); +`else +wire mclk_op2 = mclk; +`endif + +always @ (posedge mclk_op2 or posedge puc_rst) + if (puc_rst) op2 <= 16'h0000; +`ifdef CLOCK_GATING + else op2 <= per_din; +`else + else if (op2_wr) op2 <= per_din; +`endif + +wire [15:0] op2_rd = op2; + + +// RESLO Register +//----------------- +reg [15:0] reslo; + +wire [15:0] reslo_nxt; +wire reslo_wr = reg_wr[RESLO]; + +`ifdef CLOCK_GATING +wire reslo_en = reslo_wr | result_clr | result_wr; +wire mclk_reslo; +omsp_clock_gate clock_gate_reslo (.gclk(mclk_reslo), + .clk (mclk), .enable(reslo_en), .scan_enable(scan_enable)); +`else +wire mclk_reslo = mclk; +`endif + +always @ (posedge mclk_reslo or posedge puc_rst) + if (puc_rst) reslo <= 16'h0000; + else if (reslo_wr) reslo <= per_din; + else if (result_clr) reslo <= 16'h0000; +`ifdef CLOCK_GATING + else reslo <= reslo_nxt; +`else + else if (result_wr) reslo <= reslo_nxt; +`endif + +wire [15:0] reslo_rd = early_read ? reslo_nxt : reslo; + + +// RESHI Register +//----------------- +reg [15:0] reshi; + +wire [15:0] reshi_nxt; +wire reshi_wr = reg_wr[RESHI]; + +`ifdef CLOCK_GATING +wire reshi_en = reshi_wr | result_clr | result_wr; +wire mclk_reshi; +omsp_clock_gate clock_gate_reshi (.gclk(mclk_reshi), + .clk (mclk), .enable(reshi_en), .scan_enable(scan_enable)); +`else +wire mclk_reshi = mclk; +`endif + +always @ (posedge mclk_reshi or posedge puc_rst) + if (puc_rst) reshi <= 16'h0000; + else if (reshi_wr) reshi <= per_din; + else if (result_clr) reshi <= 16'h0000; +`ifdef CLOCK_GATING + else reshi <= reshi_nxt; +`else + else if (result_wr) reshi <= reshi_nxt; +`endif + +wire [15:0] reshi_rd = early_read ? reshi_nxt : reshi; + + +// SUMEXT Register +//----------------- +reg [1:0] sumext_s; + +wire [1:0] sumext_s_nxt; + +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) sumext_s <= 2'b00; + else if (op2_wr) sumext_s <= 2'b00; + else if (result_wr) sumext_s <= sumext_s_nxt; + +wire [15:0] sumext_nxt = {{14{sumext_s_nxt[1]}}, sumext_s_nxt}; +wire [15:0] sumext = {{14{sumext_s[1]}}, sumext_s}; +wire [15:0] sumext_rd = early_read ? sumext_nxt : sumext; + + +//============================================================================ +// 4) DATA OUTPUT GENERATION +//============================================================================ + +// Data output mux +wire [15:0] op1_mux = op1_rd & {16{reg_rd[OP1_MPY] | + reg_rd[OP1_MPYS] | + reg_rd[OP1_MAC] | + reg_rd[OP1_MACS]}}; +wire [15:0] op2_mux = op2_rd & {16{reg_rd[OP2]}}; +wire [15:0] reslo_mux = reslo_rd & {16{reg_rd[RESLO]}}; +wire [15:0] reshi_mux = reshi_rd & {16{reg_rd[RESHI]}}; +wire [15:0] sumext_mux = sumext_rd & {16{reg_rd[SUMEXT]}}; + +wire [15:0] per_dout = op1_mux | + op2_mux | + reslo_mux | + reshi_mux | + sumext_mux; + + +//============================================================================ +// 5) HARDWARE MULTIPLIER FUNCTIONAL LOGIC +//============================================================================ + +// Multiplier configuration +//-------------------------- + +// Detect signed mode +reg sign_sel; +always @ (posedge mclk_op1 or posedge puc_rst) + if (puc_rst) sign_sel <= 1'b0; +`ifdef CLOCK_GATING + else sign_sel <= reg_wr[OP1_MPYS] | reg_wr[OP1_MACS]; +`else + else if (op1_wr) sign_sel <= reg_wr[OP1_MPYS] | reg_wr[OP1_MACS]; +`endif + + +// Detect accumulate mode +reg acc_sel; +always @ (posedge mclk_op1 or posedge puc_rst) + if (puc_rst) acc_sel <= 1'b0; +`ifdef CLOCK_GATING + else acc_sel <= reg_wr[OP1_MAC] | reg_wr[OP1_MACS]; +`else + else if (op1_wr) acc_sel <= reg_wr[OP1_MAC] | reg_wr[OP1_MACS]; +`endif + + +// Detect whenever the RESHI and RESLO registers should be cleared +assign result_clr = op2_wr & ~acc_sel; + +// Combine RESHI & RESLO +wire [31:0] result = {reshi, reslo}; + + +// 16x16 Multiplier (result computed in 1 clock cycle) +//----------------------------------------------------- +`ifdef MPY_16x16 + +// Detect start of a multiplication +reg cycle; +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) cycle <= 1'b0; + else cycle <= op2_wr; + +assign result_wr = cycle; + +// Expand the operands to support signed & unsigned operations +wire signed [16:0] op1_xp = {sign_sel & op1[15], op1}; +wire signed [16:0] op2_xp = {sign_sel & op2[15], op2}; + + +// 17x17 signed multiplication +wire signed [33:0] product = op1_xp * op2_xp; + +// Accumulate +wire [32:0] result_nxt = {1'b0, result} + {1'b0, product[31:0]}; + + +// Next register values +assign reslo_nxt = result_nxt[15:0]; +assign reshi_nxt = result_nxt[31:16]; +assign sumext_s_nxt = sign_sel ? {2{result_nxt[31]}} : + {1'b0, result_nxt[32]}; + + +// Since the MAC is completed within 1 clock cycle, +// an early read can't happen. +assign early_read = 1'b0; + + +// 16x8 Multiplier (result computed in 2 clock cycles) +//----------------------------------------------------- +`else + +// Detect start of a multiplication +reg [1:0] cycle; +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) cycle <= 2'b00; + else cycle <= {cycle[0], op2_wr}; + +assign result_wr = |cycle; + + +// Expand the operands to support signed & unsigned operations +wire signed [16:0] op1_xp = {sign_sel & op1[15], op1}; +wire signed [8:0] op2_hi_xp = {sign_sel & op2[15], op2[15:8]}; +wire signed [8:0] op2_lo_xp = { 1'b0, op2[7:0]}; +wire signed [8:0] op2_xp = cycle[0] ? op2_hi_xp : op2_lo_xp; + + +// 17x9 signed multiplication +wire signed [25:0] product = op1_xp * op2_xp; + +wire [31:0] product_xp = cycle[0] ? {product[23:0], 8'h00} : + {{8{sign_sel & product[23]}}, product[23:0]}; + +// Accumulate +wire [32:0] result_nxt = {1'b0, result} + {1'b0, product_xp[31:0]}; + + +// Next register values +assign reslo_nxt = result_nxt[15:0]; +assign reshi_nxt = result_nxt[31:16]; +assign sumext_s_nxt = sign_sel ? {2{result_nxt[31]}} : + {1'b0, result_nxt[32] | sumext_s[0]}; + +// Since the MAC is completed within 2 clock cycle, +// an early read can happen during the second cycle. +assign early_read = cycle[1]; + +`endif + + +endmodule // omsp_multiplier + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif diff --git a/tests/openmsp430/rtl/omsp_register_file.v b/tests/openmsp430/rtl/omsp_register_file.v new file mode 100644 index 00000000..2ccd2499 --- /dev/null +++ b/tests/openmsp430/rtl/omsp_register_file.v @@ -0,0 +1,618 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_register_file.v +// +// *Module Description: +// openMSP430 Register files +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 134 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2012-03-22 21:31:06 +0100 (Thu, 22 Mar 2012) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module omsp_register_file ( + +// OUTPUTs + cpuoff, // Turns off the CPU + gie, // General interrupt enable + oscoff, // Turns off LFXT1 clock input + pc_sw, // Program counter software value + pc_sw_wr, // Program counter software write + reg_dest, // Selected register destination content + reg_src, // Selected register source content + scg0, // System clock generator 1. Turns off the DCO + scg1, // System clock generator 1. Turns off the SMCLK + status, // R2 Status {V,N,Z,C} + +// INPUTs + alu_stat, // ALU Status {V,N,Z,C} + alu_stat_wr, // ALU Status write {V,N,Z,C} + inst_bw, // Decoded Inst: byte width + inst_dest, // Register destination selection + inst_src, // Register source selection + mclk, // Main system clock + pc, // Program counter + puc_rst, // Main system reset + reg_dest_val, // Selected register destination value + reg_dest_wr, // Write selected register destination + reg_pc_call, // Trigger PC update for a CALL instruction + reg_sp_val, // Stack Pointer next value + reg_sp_wr, // Stack Pointer write + reg_sr_wr, // Status register update for RETI instruction + reg_sr_clr, // Status register clear for interrupts + reg_incr, // Increment source register + scan_enable // Scan enable (active during scan shifting) +); + +// OUTPUTs +//========= +output cpuoff; // Turns off the CPU +output gie; // General interrupt enable +output oscoff; // Turns off LFXT1 clock input +output [15:0] pc_sw; // Program counter software value +output pc_sw_wr; // Program counter software write +output [15:0] reg_dest; // Selected register destination content +output [15:0] reg_src; // Selected register source content +output scg0; // System clock generator 1. Turns off the DCO +output scg1; // System clock generator 1. Turns off the SMCLK +output [3:0] status; // R2 Status {V,N,Z,C} + +// INPUTs +//========= +input [3:0] alu_stat; // ALU Status {V,N,Z,C} +input [3:0] alu_stat_wr; // ALU Status write {V,N,Z,C} +input inst_bw; // Decoded Inst: byte width +input [15:0] inst_dest; // Register destination selection +input [15:0] inst_src; // Register source selection +input mclk; // Main system clock +input [15:0] pc; // Program counter +input puc_rst; // Main system reset +input [15:0] reg_dest_val; // Selected register destination value +input reg_dest_wr; // Write selected register destination +input reg_pc_call; // Trigger PC update for a CALL instruction +input [15:0] reg_sp_val; // Stack Pointer next value +input reg_sp_wr; // Stack Pointer write +input reg_sr_wr; // Status register update for RETI instruction +input reg_sr_clr; // Status register clear for interrupts +input reg_incr; // Increment source register +input scan_enable; // Scan enable (active during scan shifting) + + +//============================================================================= +// 1) AUTOINCREMENT UNIT +//============================================================================= + +wire [15:0] inst_src_in; +wire [15:0] incr_op = (inst_bw & ~inst_src_in[1]) ? 16'h0001 : 16'h0002; +wire [15:0] reg_incr_val = reg_src+incr_op; + +wire [15:0] reg_dest_val_in = inst_bw ? {8'h00,reg_dest_val[7:0]} : reg_dest_val; + + +//============================================================================= +// 2) SPECIAL REGISTERS (R1/R2/R3) +//============================================================================= + +// Source input selection mask (for interrupt support) +//----------------------------------------------------- + +assign inst_src_in = reg_sr_clr ? 16'h0004 : inst_src; + + +// R0: Program counter +//--------------------- + +wire [15:0] r0 = pc; + +wire [15:0] pc_sw = reg_dest_val_in; +wire pc_sw_wr = (inst_dest[0] & reg_dest_wr) | reg_pc_call; + + +// R1: Stack pointer +//------------------- +reg [15:0] r1; +wire r1_wr = inst_dest[1] & reg_dest_wr; +wire r1_inc = inst_src_in[1] & reg_incr; + +`ifdef CLOCK_GATING +wire r1_en = r1_wr | reg_sp_wr | r1_inc; +wire mclk_r1; +omsp_clock_gate clock_gate_r1 (.gclk(mclk_r1), + .clk (mclk), .enable(r1_en), .scan_enable(scan_enable)); +`else +wire mclk_r1 = mclk; +`endif + +always @(posedge mclk_r1 or posedge puc_rst) + if (puc_rst) r1 <= 16'h0000; + else if (r1_wr) r1 <= reg_dest_val_in & 16'hfffe; + else if (reg_sp_wr) r1 <= reg_sp_val & 16'hfffe; +`ifdef CLOCK_GATING + else r1 <= reg_incr_val & 16'hfffe; +`else + else if (r1_inc) r1 <= reg_incr_val & 16'hfffe; +`endif + + +// R2: Status register +//--------------------- +reg [15:0] r2; +wire r2_wr = (inst_dest[2] & reg_dest_wr) | reg_sr_wr; + +`ifdef CLOCK_GATING // -- WITH CLOCK GATING -- +wire r2_c = alu_stat_wr[0] ? alu_stat[0] : reg_dest_val_in[0]; // C + +wire r2_z = alu_stat_wr[1] ? alu_stat[1] : reg_dest_val_in[1]; // Z + +wire r2_n = alu_stat_wr[2] ? alu_stat[2] : reg_dest_val_in[2]; // N + +wire [7:3] r2_nxt = r2_wr ? reg_dest_val_in[7:3] : r2[7:3]; + +wire r2_v = alu_stat_wr[3] ? alu_stat[3] : reg_dest_val_in[8]; // V + +wire r2_en = |alu_stat_wr | r2_wr | reg_sr_clr; +wire mclk_r2; +omsp_clock_gate clock_gate_r2 (.gclk(mclk_r2), + .clk (mclk), .enable(r2_en), .scan_enable(scan_enable)); + +`else // -- WITHOUT CLOCK GATING -- +wire r2_c = alu_stat_wr[0] ? alu_stat[0] : + r2_wr ? reg_dest_val_in[0] : r2[0]; // C + +wire r2_z = alu_stat_wr[1] ? alu_stat[1] : + r2_wr ? reg_dest_val_in[1] : r2[1]; // Z + +wire r2_n = alu_stat_wr[2] ? alu_stat[2] : + r2_wr ? reg_dest_val_in[2] : r2[2]; // N + +wire [7:3] r2_nxt = r2_wr ? reg_dest_val_in[7:3] : r2[7:3]; + +wire r2_v = alu_stat_wr[3] ? alu_stat[3] : + r2_wr ? reg_dest_val_in[8] : r2[8]; // V + + +wire mclk_r2 = mclk; +`endif + +`ifdef ASIC + `ifdef CPUOFF_EN + wire [15:0] cpuoff_mask = 16'h0010; + `else + wire [15:0] cpuoff_mask = 16'h0000; + `endif + `ifdef OSCOFF_EN + wire [15:0] oscoff_mask = 16'h0020; + `else + wire [15:0] oscoff_mask = 16'h0000; + `endif + `ifdef SCG0_EN + wire [15:0] scg0_mask = 16'h0040; + `else + wire [15:0] scg0_mask = 16'h0000; + `endif + `ifdef SCG1_EN + wire [15:0] scg1_mask = 16'h0080; + `else + wire [15:0] scg1_mask = 16'h0000; + `endif +`else + wire [15:0] cpuoff_mask = 16'h0010; // For the FPGA version: - the CPUOFF mode is emulated + wire [15:0] oscoff_mask = 16'h0020; // - the SCG1 mode is emulated + wire [15:0] scg0_mask = 16'h0000; // - the SCG0 is not supported + wire [15:0] scg1_mask = 16'h0080; // - the SCG1 mode is emulated +`endif + + wire [15:0] r2_mask = cpuoff_mask | oscoff_mask | scg0_mask | scg1_mask | 16'h010f; + +always @(posedge mclk_r2 or posedge puc_rst) + if (puc_rst) r2 <= 16'h0000; + else if (reg_sr_clr) r2 <= 16'h0000; + else r2 <= {7'h00, r2_v, r2_nxt, r2_n, r2_z, r2_c} & r2_mask; + +assign status = {r2[8], r2[2:0]}; +assign gie = r2[3]; +assign cpuoff = r2[4] | (r2_nxt[4] & r2_wr & cpuoff_mask[4]); +assign oscoff = r2[5]; +assign scg0 = r2[6]; +assign scg1 = r2[7]; + + +// R3: Constant generator +//------------------------------------------------------------- +// Note: the auto-increment feature is not implemented for R3 +// because the @R3+ addressing mode is used for constant +// generation (#-1). +reg [15:0] r3; +wire r3_wr = inst_dest[3] & reg_dest_wr; + +`ifdef CLOCK_GATING +wire r3_en = r3_wr; +wire mclk_r3; +omsp_clock_gate clock_gate_r3 (.gclk(mclk_r3), + .clk (mclk), .enable(r3_en), .scan_enable(scan_enable)); +`else +wire mclk_r3 = mclk; +`endif + +always @(posedge mclk_r3 or posedge puc_rst) + if (puc_rst) r3 <= 16'h0000; +`ifdef CLOCK_GATING + else r3 <= reg_dest_val_in; +`else + else if (r3_wr) r3 <= reg_dest_val_in; +`endif + + +//============================================================================= +// 4) GENERAL PURPOSE REGISTERS (R4...R15) +//============================================================================= + +// R4 +//------------ +reg [15:0] r4; +wire r4_wr = inst_dest[4] & reg_dest_wr; +wire r4_inc = inst_src_in[4] & reg_incr; + +`ifdef CLOCK_GATING +wire r4_en = r4_wr | r4_inc; +wire mclk_r4; +omsp_clock_gate clock_gate_r4 (.gclk(mclk_r4), + .clk (mclk), .enable(r4_en), .scan_enable(scan_enable)); +`else +wire mclk_r4 = mclk; +`endif + +always @(posedge mclk_r4 or posedge puc_rst) + if (puc_rst) r4 <= 16'h0000; + else if (r4_wr) r4 <= reg_dest_val_in; +`ifdef CLOCK_GATING + else r4 <= reg_incr_val; +`else + else if (r4_inc) r4 <= reg_incr_val; +`endif + +// R5 +//------------ +reg [15:0] r5; +wire r5_wr = inst_dest[5] & reg_dest_wr; +wire r5_inc = inst_src_in[5] & reg_incr; + +`ifdef CLOCK_GATING +wire r5_en = r5_wr | r5_inc; +wire mclk_r5; +omsp_clock_gate clock_gate_r5 (.gclk(mclk_r5), + .clk (mclk), .enable(r5_en), .scan_enable(scan_enable)); +`else +wire mclk_r5 = mclk; +`endif + +always @(posedge mclk_r5 or posedge puc_rst) + if (puc_rst) r5 <= 16'h0000; + else if (r5_wr) r5 <= reg_dest_val_in; +`ifdef CLOCK_GATING + else r5 <= reg_incr_val; +`else + else if (r5_inc) r5 <= reg_incr_val; +`endif + +// R6 +//------------ +reg [15:0] r6; +wire r6_wr = inst_dest[6] & reg_dest_wr; +wire r6_inc = inst_src_in[6] & reg_incr; + +`ifdef CLOCK_GATING +wire r6_en = r6_wr | r6_inc; +wire mclk_r6; +omsp_clock_gate clock_gate_r6 (.gclk(mclk_r6), + .clk (mclk), .enable(r6_en), .scan_enable(scan_enable)); +`else +wire mclk_r6 = mclk; +`endif + +always @(posedge mclk_r6 or posedge puc_rst) + if (puc_rst) r6 <= 16'h0000; + else if (r6_wr) r6 <= reg_dest_val_in; +`ifdef CLOCK_GATING + else r6 <= reg_incr_val; +`else + else if (r6_inc) r6 <= reg_incr_val; +`endif + +// R7 +//------------ +reg [15:0] r7; +wire r7_wr = inst_dest[7] & reg_dest_wr; +wire r7_inc = inst_src_in[7] & reg_incr; + +`ifdef CLOCK_GATING +wire r7_en = r7_wr | r7_inc; +wire mclk_r7; +omsp_clock_gate clock_gate_r7 (.gclk(mclk_r7), + .clk (mclk), .enable(r7_en), .scan_enable(scan_enable)); +`else +wire mclk_r7 = mclk; +`endif + +always @(posedge mclk_r7 or posedge puc_rst) + if (puc_rst) r7 <= 16'h0000; + else if (r7_wr) r7 <= reg_dest_val_in; +`ifdef CLOCK_GATING + else r7 <= reg_incr_val; +`else + else if (r7_inc) r7 <= reg_incr_val; +`endif + +// R8 +//------------ +reg [15:0] r8; +wire r8_wr = inst_dest[8] & reg_dest_wr; +wire r8_inc = inst_src_in[8] & reg_incr; + +`ifdef CLOCK_GATING +wire r8_en = r8_wr | r8_inc; +wire mclk_r8; +omsp_clock_gate clock_gate_r8 (.gclk(mclk_r8), + .clk (mclk), .enable(r8_en), .scan_enable(scan_enable)); +`else +wire mclk_r8 = mclk; +`endif + +always @(posedge mclk_r8 or posedge puc_rst) + if (puc_rst) r8 <= 16'h0000; + else if (r8_wr) r8 <= reg_dest_val_in; +`ifdef CLOCK_GATING + else r8 <= reg_incr_val; +`else + else if (r8_inc) r8 <= reg_incr_val; +`endif + +// R9 +//------------ +reg [15:0] r9; +wire r9_wr = inst_dest[9] & reg_dest_wr; +wire r9_inc = inst_src_in[9] & reg_incr; + +`ifdef CLOCK_GATING +wire r9_en = r9_wr | r9_inc; +wire mclk_r9; +omsp_clock_gate clock_gate_r9 (.gclk(mclk_r9), + .clk (mclk), .enable(r9_en), .scan_enable(scan_enable)); +`else +wire mclk_r9 = mclk; +`endif + +always @(posedge mclk_r9 or posedge puc_rst) + if (puc_rst) r9 <= 16'h0000; + else if (r9_wr) r9 <= reg_dest_val_in; +`ifdef CLOCK_GATING + else r9 <= reg_incr_val; +`else + else if (r9_inc) r9 <= reg_incr_val; +`endif + +// R10 +//------------ +reg [15:0] r10; +wire r10_wr = inst_dest[10] & reg_dest_wr; +wire r10_inc = inst_src_in[10] & reg_incr; + +`ifdef CLOCK_GATING +wire r10_en = r10_wr | r10_inc; +wire mclk_r10; +omsp_clock_gate clock_gate_r10 (.gclk(mclk_r10), + .clk (mclk), .enable(r10_en), .scan_enable(scan_enable)); +`else +wire mclk_r10 = mclk; +`endif + +always @(posedge mclk_r10 or posedge puc_rst) + if (puc_rst) r10 <= 16'h0000; + else if (r10_wr) r10 <= reg_dest_val_in; +`ifdef CLOCK_GATING + else r10 <= reg_incr_val; +`else + else if (r10_inc) r10 <= reg_incr_val; +`endif + +// R11 +//------------ +reg [15:0] r11; +wire r11_wr = inst_dest[11] & reg_dest_wr; +wire r11_inc = inst_src_in[11] & reg_incr; + +`ifdef CLOCK_GATING +wire r11_en = r11_wr | r11_inc; +wire mclk_r11; +omsp_clock_gate clock_gate_r11 (.gclk(mclk_r11), + .clk (mclk), .enable(r11_en), .scan_enable(scan_enable)); +`else +wire mclk_r11 = mclk; +`endif + +always @(posedge mclk_r11 or posedge puc_rst) + if (puc_rst) r11 <= 16'h0000; + else if (r11_wr) r11 <= reg_dest_val_in; +`ifdef CLOCK_GATING + else r11 <= reg_incr_val; +`else + else if (r11_inc) r11 <= reg_incr_val; +`endif + +// R12 +//------------ +reg [15:0] r12; +wire r12_wr = inst_dest[12] & reg_dest_wr; +wire r12_inc = inst_src_in[12] & reg_incr; + +`ifdef CLOCK_GATING +wire r12_en = r12_wr | r12_inc; +wire mclk_r12; +omsp_clock_gate clock_gate_r12 (.gclk(mclk_r12), + .clk (mclk), .enable(r12_en), .scan_enable(scan_enable)); +`else +wire mclk_r12 = mclk; +`endif + +always @(posedge mclk_r12 or posedge puc_rst) + if (puc_rst) r12 <= 16'h0000; + else if (r12_wr) r12 <= reg_dest_val_in; +`ifdef CLOCK_GATING + else r12 <= reg_incr_val; +`else + else if (r12_inc) r12 <= reg_incr_val; +`endif + +// R13 +//------------ +reg [15:0] r13; +wire r13_wr = inst_dest[13] & reg_dest_wr; +wire r13_inc = inst_src_in[13] & reg_incr; + +`ifdef CLOCK_GATING +wire r13_en = r13_wr | r13_inc; +wire mclk_r13; +omsp_clock_gate clock_gate_r13 (.gclk(mclk_r13), + .clk (mclk), .enable(r13_en), .scan_enable(scan_enable)); +`else +wire mclk_r13 = mclk; +`endif + +always @(posedge mclk_r13 or posedge puc_rst) + if (puc_rst) r13 <= 16'h0000; + else if (r13_wr) r13 <= reg_dest_val_in; +`ifdef CLOCK_GATING + else r13 <= reg_incr_val; +`else + else if (r13_inc) r13 <= reg_incr_val; +`endif + +// R14 +//------------ +reg [15:0] r14; +wire r14_wr = inst_dest[14] & reg_dest_wr; +wire r14_inc = inst_src_in[14] & reg_incr; + +`ifdef CLOCK_GATING +wire r14_en = r14_wr | r14_inc; +wire mclk_r14; +omsp_clock_gate clock_gate_r14 (.gclk(mclk_r14), + .clk (mclk), .enable(r14_en), .scan_enable(scan_enable)); +`else +wire mclk_r14 = mclk; +`endif + +always @(posedge mclk_r14 or posedge puc_rst) + if (puc_rst) r14 <= 16'h0000; + else if (r14_wr) r14 <= reg_dest_val_in; +`ifdef CLOCK_GATING + else r14 <= reg_incr_val; +`else + else if (r14_inc) r14 <= reg_incr_val; +`endif + +// R15 +//------------ +reg [15:0] r15; +wire r15_wr = inst_dest[15] & reg_dest_wr; +wire r15_inc = inst_src_in[15] & reg_incr; + +`ifdef CLOCK_GATING +wire r15_en = r15_wr | r15_inc; +wire mclk_r15; +omsp_clock_gate clock_gate_r15 (.gclk(mclk_r15), + .clk (mclk), .enable(r15_en), .scan_enable(scan_enable)); +`else +wire mclk_r15 = mclk; +`endif + +always @(posedge mclk_r15 or posedge puc_rst) + if (puc_rst) r15 <= 16'h0000; + else if (r15_wr) r15 <= reg_dest_val_in; + `ifdef CLOCK_GATING + else r15 <= reg_incr_val; +`else + else if (r15_inc) r15 <= reg_incr_val; +`endif + + +//============================================================================= +// 5) READ MUX +//============================================================================= + +assign reg_src = (r0 & {16{inst_src_in[0]}}) | + (r1 & {16{inst_src_in[1]}}) | + (r2 & {16{inst_src_in[2]}}) | + (r3 & {16{inst_src_in[3]}}) | + (r4 & {16{inst_src_in[4]}}) | + (r5 & {16{inst_src_in[5]}}) | + (r6 & {16{inst_src_in[6]}}) | + (r7 & {16{inst_src_in[7]}}) | + (r8 & {16{inst_src_in[8]}}) | + (r9 & {16{inst_src_in[9]}}) | + (r10 & {16{inst_src_in[10]}}) | + (r11 & {16{inst_src_in[11]}}) | + (r12 & {16{inst_src_in[12]}}) | + (r13 & {16{inst_src_in[13]}}) | + (r14 & {16{inst_src_in[14]}}) | + (r15 & {16{inst_src_in[15]}}); + +assign reg_dest = (r0 & {16{inst_dest[0]}}) | + (r1 & {16{inst_dest[1]}}) | + (r2 & {16{inst_dest[2]}}) | + (r3 & {16{inst_dest[3]}}) | + (r4 & {16{inst_dest[4]}}) | + (r5 & {16{inst_dest[5]}}) | + (r6 & {16{inst_dest[6]}}) | + (r7 & {16{inst_dest[7]}}) | + (r8 & {16{inst_dest[8]}}) | + (r9 & {16{inst_dest[9]}}) | + (r10 & {16{inst_dest[10]}}) | + (r11 & {16{inst_dest[11]}}) | + (r12 & {16{inst_dest[12]}}) | + (r13 & {16{inst_dest[13]}}) | + (r14 & {16{inst_dest[14]}}) | + (r15 & {16{inst_dest[15]}}); + + +endmodule // omsp_register_file + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif diff --git a/tests/openmsp430/rtl/omsp_scan_mux.v b/tests/openmsp430/rtl/omsp_scan_mux.v new file mode 100644 index 00000000..9a906474 --- /dev/null +++ b/tests/openmsp430/rtl/omsp_scan_mux.v @@ -0,0 +1,75 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_scan_mux.v +// +// *Module Description: +// Generic mux for scan mode +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 103 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $ +//---------------------------------------------------------------------------- + +module omsp_scan_mux ( + +// OUTPUTs + data_out, // Scan mux data output + +// INPUTs + data_in_scan, // Selected data input for scan mode + data_in_func, // Selected data input for functional mode + scan_mode // Scan mode +); + +// OUTPUTs +//========= +output data_out; // Scan mux data output + +// INPUTs +//========= +input data_in_scan; // Selected data input for scan mode +input data_in_func; // Selected data input for functional mode +input scan_mode; // Scan mode + + +//============================================================================= +// 1) SCAN MUX +//============================================================================= + +assign data_out = scan_mode ? data_in_scan : data_in_func; + + +endmodule // omsp_scan_mux + + diff --git a/tests/openmsp430/rtl/omsp_sfr.v b/tests/openmsp430/rtl/omsp_sfr.v new file mode 100644 index 00000000..bc8c11a5 --- /dev/null +++ b/tests/openmsp430/rtl/omsp_sfr.v @@ -0,0 +1,353 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_sfr.v +// +// *Module Description: +// Processor Special function register +// Non-Maskable Interrupt generation +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 134 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2012-03-22 21:31:06 +0100 (Thu, 22 Mar 2012) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module omsp_sfr ( + +// OUTPUTs + cpu_id, // CPU ID + nmi_pnd, // NMI Pending + nmi_wkup, // NMI Wakeup + per_dout, // Peripheral data output + wdtie, // Watchdog-timer interrupt enable + wdtifg_sw_clr, // Watchdog-timer interrupt flag software clear + wdtifg_sw_set, // Watchdog-timer interrupt flag software set + +// INPUTs + mclk, // Main system clock + nmi, // Non-maskable interrupt (asynchronous) + nmi_acc, // Non-Maskable interrupt request accepted + per_addr, // Peripheral address + per_din, // Peripheral data input + per_en, // Peripheral enable (high active) + per_we, // Peripheral write enable (high active) + puc_rst, // Main system reset + scan_mode, // Scan mode + wdtifg, // Watchdog-timer interrupt flag + wdtnmies // Watchdog-timer NMI edge selection +); + +// OUTPUTs +//========= +output [31:0] cpu_id; // CPU ID +output nmi_pnd; // NMI Pending +output nmi_wkup; // NMI Wakeup +output [15:0] per_dout; // Peripheral data output +output wdtie; // Watchdog-timer interrupt enable +output wdtifg_sw_clr;// Watchdog-timer interrupt flag software clear +output wdtifg_sw_set;// Watchdog-timer interrupt flag software set + +// INPUTs +//========= +input mclk; // Main system clock +input nmi; // Non-maskable interrupt (asynchronous) +input nmi_acc; // Non-Maskable interrupt request accepted +input [13:0] per_addr; // Peripheral address +input [15:0] per_din; // Peripheral data input +input per_en; // Peripheral enable (high active) +input [1:0] per_we; // Peripheral write enable (high active) +input puc_rst; // Main system reset +input scan_mode; // Scan mode +input wdtifg; // Watchdog-timer interrupt flag +input wdtnmies; // Watchdog-timer NMI edge selection + + +//============================================================================= +// 1) PARAMETER DECLARATION +//============================================================================= + +// Register base address (must be aligned to decoder bit width) +parameter [14:0] BASE_ADDR = 15'h0000; + +// Decoder bit width (defines how many bits are considered for address decoding) +parameter DEC_WD = 3; + +// Register addresses offset +parameter [DEC_WD-1:0] IE1 = 'h0, + IFG1 = 'h2, + CPU_ID_LO = 'h4, + CPU_ID_HI = 'h6; + +// Register one-hot decoder utilities +parameter DEC_SZ = (1 << DEC_WD); +parameter [DEC_SZ-1:0] BASE_REG = {{DEC_SZ-1{1'b0}}, 1'b1}; + +// Register one-hot decoder +parameter [DEC_SZ-1:0] IE1_D = (BASE_REG << IE1), + IFG1_D = (BASE_REG << IFG1), + CPU_ID_LO_D = (BASE_REG << CPU_ID_LO), + CPU_ID_HI_D = (BASE_REG << CPU_ID_HI); + + +//============================================================================ +// 2) REGISTER DECODER +//============================================================================ + +// Local register selection +wire reg_sel = per_en & (per_addr[13:DEC_WD-1]==BASE_ADDR[14:DEC_WD]); + +// Register local address +wire [DEC_WD-1:0] reg_addr = {1'b0, per_addr[DEC_WD-2:0]}; + +// Register address decode +wire [DEC_SZ-1:0] reg_dec = (IE1_D & {DEC_SZ{(reg_addr==(IE1 >>1))}}) | + (IFG1_D & {DEC_SZ{(reg_addr==(IFG1 >>1))}}) | + (CPU_ID_LO_D & {DEC_SZ{(reg_addr==(CPU_ID_LO >>1))}}) | + (CPU_ID_HI_D & {DEC_SZ{(reg_addr==(CPU_ID_HI >>1))}}); + +// Read/Write probes +wire reg_lo_write = per_we[0] & reg_sel; +wire reg_hi_write = per_we[1] & reg_sel; +wire reg_read = ~|per_we & reg_sel; + +// Read/Write vectors +wire [DEC_SZ-1:0] reg_hi_wr = reg_dec & {DEC_SZ{reg_hi_write}}; +wire [DEC_SZ-1:0] reg_lo_wr = reg_dec & {DEC_SZ{reg_lo_write}}; +wire [DEC_SZ-1:0] reg_rd = reg_dec & {DEC_SZ{reg_read}}; + + +//============================================================================ +// 3) REGISTERS +//============================================================================ + +// IE1 Register +//-------------- +wire [7:0] ie1; +wire ie1_wr = IE1[0] ? reg_hi_wr[IE1] : reg_lo_wr[IE1]; +wire [7:0] ie1_nxt = IE1[0] ? per_din[15:8] : per_din[7:0]; + +`ifdef NMI +reg nmie; +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) nmie <= 1'b0; + else if (nmi_acc) nmie <= 1'b0; + else if (ie1_wr) nmie <= ie1_nxt[4]; +`else +wire nmie = 1'b0; +`endif + +`ifdef WATCHDOG +reg wdtie; +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) wdtie <= 1'b0; + else if (ie1_wr) wdtie <= ie1_nxt[0]; +`else +wire wdtie = 1'b0; +`endif + +assign ie1 = {3'b000, nmie, 3'b000, wdtie}; + + +// IFG1 Register +//--------------- +wire [7:0] ifg1; + +wire ifg1_wr = IFG1[0] ? reg_hi_wr[IFG1] : reg_lo_wr[IFG1]; +wire [7:0] ifg1_nxt = IFG1[0] ? per_din[15:8] : per_din[7:0]; + +`ifdef NMI +reg nmiifg; +wire nmi_edge; +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) nmiifg <= 1'b0; + else if (nmi_edge) nmiifg <= 1'b1; + else if (ifg1_wr) nmiifg <= ifg1_nxt[4]; +`else +wire nmiifg = 1'b0; +`endif + +`ifdef WATCHDOG +assign wdtifg_sw_clr = ifg1_wr & ~ifg1_nxt[0]; +assign wdtifg_sw_set = ifg1_wr & ifg1_nxt[0]; +`else +assign wdtifg_sw_clr = 1'b0; +assign wdtifg_sw_set = 1'b0; +`endif + +assign ifg1 = {3'b000, nmiifg, 3'b000, wdtifg}; + + +// CPU_ID Register (READ ONLY) +//----------------------------- +// ------------------------------------------------------------------- +// CPU_ID_LO: | 15 14 13 12 11 10 9 | 8 7 6 5 4 | 3 | 2 1 0 | +// |----------------------------+-----------------+------+-------------| +// | PER_SPACE | USER_VERSION | ASIC | CPU_VERSION | +// -------------------------------------------------------------------- +// CPU_ID_HI: | 15 14 13 12 11 10 | 9 8 7 6 5 4 3 2 1 | 0 | +// |----------------------------+-------------------------------+------| +// | PMEM_SIZE | DMEM_SIZE | MPY | +// ------------------------------------------------------------------- + +wire [2:0] cpu_version = `CPU_VERSION; +`ifdef ASIC +wire cpu_asic = 1'b1; +`else +wire cpu_asic = 1'b0; +`endif +wire [4:0] user_version = `USER_VERSION; +wire [6:0] per_space = (`PER_SIZE >> 9); // cpu_id_per * 512 = peripheral space size +`ifdef MULTIPLIER +wire mpy_info = 1'b1; +`else +wire mpy_info = 1'b0; +`endif +wire [8:0] dmem_size = (`DMEM_SIZE >> 7); // cpu_id_dmem * 128 = data memory size +wire [5:0] pmem_size = (`PMEM_SIZE >> 10); // cpu_id_pmem * 1024 = program memory size + +assign cpu_id = {pmem_size, + dmem_size, + mpy_info, + per_space, + user_version, + cpu_asic, + cpu_version}; + + +//============================================================================ +// 4) DATA OUTPUT GENERATION +//============================================================================ + +// Data output mux +wire [15:0] ie1_rd = {8'h00, (ie1 & {8{reg_rd[IE1]}})} << (8 & {4{IE1[0]}}); +wire [15:0] ifg1_rd = {8'h00, (ifg1 & {8{reg_rd[IFG1]}})} << (8 & {4{IFG1[0]}}); +wire [15:0] cpu_id_lo_rd = cpu_id[15:0] & {16{reg_rd[CPU_ID_LO]}}; +wire [15:0] cpu_id_hi_rd = cpu_id[31:16] & {16{reg_rd[CPU_ID_HI]}}; + +wire [15:0] per_dout = ie1_rd | + ifg1_rd | + cpu_id_lo_rd | + cpu_id_hi_rd; + + +//============================================================================= +// 5) NMI GENERATION +//============================================================================= +// NOTE THAT THE NMI INPUT IS ASSUMED TO BE NON-GLITCHY +`ifdef NMI + +//----------------------------------- +// Edge selection +//----------------------------------- +wire nmi_pol = nmi ^ wdtnmies; + +//----------------------------------- +// Pulse capture and synchronization +//----------------------------------- +`ifdef SYNC_NMI + `ifdef ASIC + // Glitch free reset for the event capture + reg nmi_capture_rst; + always @(posedge mclk or posedge puc_rst) + if (puc_rst) nmi_capture_rst <= 1'b1; + else nmi_capture_rst <= ifg1_wr & ~ifg1_nxt[4]; + + // NMI event capture + wire nmi_capture; + omsp_wakeup_cell wakeup_cell_nmi ( + .wkup_out (nmi_capture), // Wakup signal (asynchronous) + .scan_clk (mclk), // Scan clock + .scan_mode (scan_mode), // Scan mode + .scan_rst (puc_rst), // Scan reset + .wkup_clear (nmi_capture_rst), // Glitch free wakeup event clear + .wkup_event (nmi_pol) // Glitch free asynchronous wakeup event + ); + `else + wire nmi_capture = nmi_pol; + `endif + + // Synchronization + wire nmi_s; + omsp_sync_cell sync_cell_nmi ( + .data_out (nmi_s), + .data_in (nmi_capture), + .clk (mclk), + .rst (puc_rst) + ); + +`else + wire nmi_capture = nmi_pol; + wire nmi_s = nmi_pol; +`endif + +//----------------------------------- +// NMI Pending flag +//----------------------------------- + +// Delay +reg nmi_dly; +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) nmi_dly <= 1'b0; + else nmi_dly <= nmi_s; + +// Edge detection +assign nmi_edge = ~nmi_dly & nmi_s; + +// NMI pending +wire nmi_pnd = nmiifg & nmie; + +// NMI wakeup +`ifdef ASIC +wire nmi_wkup; +omsp_and_gate and_nmi_wkup (.y(nmi_wkup), .a(nmi_capture ^ nmi_dly), .b(nmie)); +`else +wire nmi_wkup = 1'b0; +`endif + +`else + +wire nmi_pnd = 1'b0; +wire nmi_wkup = 1'b0; + +`endif + +endmodule // omsp_sfr + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif diff --git a/tests/openmsp430/rtl/omsp_sync_cell.v b/tests/openmsp430/rtl/omsp_sync_cell.v new file mode 100644 index 00000000..ece0682a --- /dev/null +++ b/tests/openmsp430/rtl/omsp_sync_cell.v @@ -0,0 +1,80 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_sync_cell.v +// +// *Module Description: +// Generic synchronizer for the openMSP430 +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 103 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $ +//---------------------------------------------------------------------------- + +module omsp_sync_cell ( + +// OUTPUTs + data_out, // Synchronized data output + +// INPUTs + clk, // Receiving clock + data_in, // Asynchronous data input + rst // Receiving reset (active high) +); + +// OUTPUTs +//========= +output data_out; // Synchronized data output + +// INPUTs +//========= +input clk; // Receiving clock +input data_in; // Asynchronous data input +input rst; // Receiving reset (active high) + + +//============================================================================= +// 1) SYNCHRONIZER +//============================================================================= + +reg [1:0] data_sync; + +always @(posedge clk or posedge rst) + if (rst) data_sync <= 2'b00; + else data_sync <= {data_sync[0], data_in}; + +assign data_out = data_sync[1]; + + +endmodule // omsp_sync_cell + diff --git a/tests/openmsp430/rtl/omsp_sync_reset.v b/tests/openmsp430/rtl/omsp_sync_reset.v new file mode 100644 index 00000000..15a158b4 --- /dev/null +++ b/tests/openmsp430/rtl/omsp_sync_reset.v @@ -0,0 +1,78 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_sync_reset.v +// +// *Module Description: +// Generic reset synchronizer for the openMSP430 +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 103 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $ +//---------------------------------------------------------------------------- + +module omsp_sync_reset ( + +// OUTPUTs + rst_s, // Synchronized reset + +// INPUTs + clk, // Receiving clock + rst_a // Asynchronous reset +); + +// OUTPUTs +//========= +output rst_s; // Synchronized reset + +// INPUTs +//========= +input clk; // Receiving clock +input rst_a; // Asynchronous reset + + +//============================================================================= +// 1) SYNCHRONIZER +//============================================================================= + +reg [1:0] data_sync; + +always @(posedge clk or posedge rst_a) + if (rst_a) data_sync <= 2'b11; + else data_sync <= {data_sync[0], 1'b0}; + +assign rst_s = data_sync[1]; + + +endmodule // omsp_sync_reset + diff --git a/tests/openmsp430/rtl/omsp_wakeup_cell.v b/tests/openmsp430/rtl/omsp_wakeup_cell.v new file mode 100644 index 00000000..6e5fcd88 --- /dev/null +++ b/tests/openmsp430/rtl/omsp_wakeup_cell.v @@ -0,0 +1,108 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_wakeup_cell.v +// +// *Module Description: +// Generic Wakeup cell +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 103 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $ +//---------------------------------------------------------------------------- + +module omsp_wakeup_cell ( + +// OUTPUTs + wkup_out, // Wakup signal (asynchronous) + +// INPUTs + scan_clk, // Scan clock + scan_mode, // Scan mode + scan_rst, // Scan reset + wkup_clear, // Glitch free wakeup event clear + wkup_event // Glitch free asynchronous wakeup event +); + +// OUTPUTs +//========= +output wkup_out; // Wakup signal (asynchronous) + +// INPUTs +//========= +input scan_clk; // Scan clock +input scan_mode; // Scan mode +input scan_rst; // Scan reset +input wkup_clear; // Glitch free wakeup event clear +input wkup_event; // Glitch free asynchronous wakeup event + + +//============================================================================= +// 1) AND GATE +//============================================================================= + +// Scan stuff for the ASIC mode +`ifdef ASIC + wire wkup_rst; + omsp_scan_mux scan_mux_rst ( + .scan_mode (scan_mode), + .data_in_scan (scan_rst), + .data_in_func (wkup_clear), + .data_out (wkup_rst) + ); + + wire wkup_clk; + omsp_scan_mux scan_mux_clk ( + .scan_mode (scan_mode), + .data_in_scan (scan_clk), + .data_in_func (wkup_event), + .data_out (wkup_clk) + ); + +`else + wire wkup_rst = wkup_clear; + wire wkup_clk = wkup_event; +`endif + +// Wakeup capture +reg wkup_out; +always @(posedge wkup_clk or posedge wkup_rst) + if (wkup_rst) wkup_out <= 1'b0; + else wkup_out <= 1'b1; + + +endmodule // omsp_wakeup_cell + + + + diff --git a/tests/openmsp430/rtl/omsp_watchdog.v b/tests/openmsp430/rtl/omsp_watchdog.v new file mode 100644 index 00000000..f7cedda0 --- /dev/null +++ b/tests/openmsp430/rtl/omsp_watchdog.v @@ -0,0 +1,556 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_watchdog.v +// +// *Module Description: +// Watchdog Timer +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 134 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2012-03-22 21:31:06 +0100 (Thu, 22 Mar 2012) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module omsp_watchdog ( + +// OUTPUTs + per_dout, // Peripheral data output + wdt_irq, // Watchdog-timer interrupt + wdt_reset, // Watchdog-timer reset + wdt_wkup, // Watchdog Wakeup + wdtifg, // Watchdog-timer interrupt flag + wdtnmies, // Watchdog-timer NMI edge selection + +// INPUTs + aclk, // ACLK + aclk_en, // ACLK enable + dbg_freeze, // Freeze Watchdog counter + mclk, // Main system clock + per_addr, // Peripheral address + per_din, // Peripheral data input + per_en, // Peripheral enable (high active) + per_we, // Peripheral write enable (high active) + por, // Power-on reset + puc_rst, // Main system reset + scan_enable, // Scan enable (active during scan shifting) + scan_mode, // Scan mode + smclk, // SMCLK + smclk_en, // SMCLK enable + wdtie, // Watchdog timer interrupt enable + wdtifg_irq_clr, // Watchdog-timer interrupt flag irq accepted clear + wdtifg_sw_clr, // Watchdog-timer interrupt flag software clear + wdtifg_sw_set // Watchdog-timer interrupt flag software set +); + +// OUTPUTs +//========= +output [15:0] per_dout; // Peripheral data output +output wdt_irq; // Watchdog-timer interrupt +output wdt_reset; // Watchdog-timer reset +output wdt_wkup; // Watchdog Wakeup +output wdtifg; // Watchdog-timer interrupt flag +output wdtnmies; // Watchdog-timer NMI edge selection + +// INPUTs +//========= +input aclk; // ACLK +input aclk_en; // ACLK enable +input dbg_freeze; // Freeze Watchdog counter +input mclk; // Main system clock +input [13:0] per_addr; // Peripheral address +input [15:0] per_din; // Peripheral data input +input per_en; // Peripheral enable (high active) +input [1:0] per_we; // Peripheral write enable (high active) +input por; // Power-on reset +input puc_rst; // Main system reset +input scan_enable; // Scan enable (active during scan shifting) +input scan_mode; // Scan mode +input smclk; // SMCLK +input smclk_en; // SMCLK enable +input wdtie; // Watchdog timer interrupt enable +input wdtifg_irq_clr; // Clear Watchdog-timer interrupt flag +input wdtifg_sw_clr; // Watchdog-timer interrupt flag software clear +input wdtifg_sw_set; // Watchdog-timer interrupt flag software set + + +//============================================================================= +// 1) PARAMETER DECLARATION +//============================================================================= + +// Register base address (must be aligned to decoder bit width) +parameter [14:0] BASE_ADDR = 15'h0120; + +// Decoder bit width (defines how many bits are considered for address decoding) +parameter DEC_WD = 2; + +// Register addresses offset +parameter [DEC_WD-1:0] WDTCTL = 'h0; + +// Register one-hot decoder utilities +parameter DEC_SZ = (1 << DEC_WD); +parameter [DEC_SZ-1:0] BASE_REG = {{DEC_SZ-1{1'b0}}, 1'b1}; + +// Register one-hot decoder +parameter [DEC_SZ-1:0] WDTCTL_D = (BASE_REG << WDTCTL); + + +//============================================================================ +// 2) REGISTER DECODER +//============================================================================ + +// Local register selection +wire reg_sel = per_en & (per_addr[13:DEC_WD-1]==BASE_ADDR[14:DEC_WD]); + +// Register local address +wire [DEC_WD-1:0] reg_addr = {per_addr[DEC_WD-2:0], 1'b0}; + +// Register address decode +wire [DEC_SZ-1:0] reg_dec = (WDTCTL_D & {DEC_SZ{(reg_addr==WDTCTL)}}); + +// Read/Write probes +wire reg_write = |per_we & reg_sel; +wire reg_read = ~|per_we & reg_sel; + +// Read/Write vectors +wire [DEC_SZ-1:0] reg_wr = reg_dec & {DEC_SZ{reg_write}}; +wire [DEC_SZ-1:0] reg_rd = reg_dec & {DEC_SZ{reg_read}}; + + +//============================================================================ +// 3) REGISTERS +//============================================================================ + +// WDTCTL Register +//----------------- +// WDTNMI is not implemented and therefore masked + +reg [7:0] wdtctl; + +wire wdtctl_wr = reg_wr[WDTCTL]; + +`ifdef CLOCK_GATING +wire mclk_wdtctl; +omsp_clock_gate clock_gate_wdtctl (.gclk(mclk_wdtctl), + .clk (mclk), .enable(wdtctl_wr), .scan_enable(scan_enable)); +`else +wire mclk_wdtctl = mclk; +`endif + +`ifdef NMI +parameter [7:0] WDTNMIES_MASK = 8'h40; +`else +parameter [7:0] WDTNMIES_MASK = 8'h00; +`endif + +`ifdef ASIC + `ifdef WATCHDOG_MUX +parameter [7:0] WDTSSEL_MASK = 8'h04; + `else +parameter [7:0] WDTSSEL_MASK = 8'h00; + `endif +`else +parameter [7:0] WDTSSEL_MASK = 8'h04; +`endif + +parameter [7:0] WDTCTL_MASK = (8'b1001_0011 | WDTSSEL_MASK | WDTNMIES_MASK); + +always @ (posedge mclk_wdtctl or posedge puc_rst) + if (puc_rst) wdtctl <= 8'h00; +`ifdef CLOCK_GATING + else wdtctl <= per_din[7:0] & WDTCTL_MASK; +`else + else if (wdtctl_wr) wdtctl <= per_din[7:0] & WDTCTL_MASK; +`endif + +wire wdtpw_error = wdtctl_wr & (per_din[15:8]!=8'h5a); +wire wdttmsel = wdtctl[4]; +wire wdtnmies = wdtctl[6]; + + +//============================================================================ +// 4) DATA OUTPUT GENERATION +//============================================================================ + +`ifdef NMI +parameter [7:0] WDTNMI_RD_MASK = 8'h20; +`else +parameter [7:0] WDTNMI_RD_MASK = 8'h00; +`endif +`ifdef WATCHDOG_MUX +parameter [7:0] WDTSSEL_RD_MASK = 8'h00; +`else + `ifdef WATCHDOG_NOMUX_ACLK +parameter [7:0] WDTSSEL_RD_MASK = 8'h04; + `else +parameter [7:0] WDTSSEL_RD_MASK = 8'h00; + `endif +`endif +parameter [7:0] WDTCTL_RD_MASK = WDTNMI_RD_MASK | WDTSSEL_RD_MASK; + +// Data output mux +wire [15:0] wdtctl_rd = {8'h69, wdtctl | WDTCTL_RD_MASK} & {16{reg_rd[WDTCTL]}}; +wire [15:0] per_dout = wdtctl_rd; + + +//============================================================================= +// 5) WATCHDOG TIMER (ASIC IMPLEMENTATION) +//============================================================================= +`ifdef ASIC + +// Watchdog clock source selection +//--------------------------------- +wire wdt_clk; + +`ifdef WATCHDOG_MUX +omsp_clock_mux clock_mux_watchdog ( + .clk_out (wdt_clk), + .clk_in0 (smclk), + .clk_in1 (aclk), + .reset (puc_rst), + .scan_mode (scan_mode), + .select (wdtctl[2]) +); +`else + `ifdef WATCHDOG_NOMUX_ACLK + assign wdt_clk = aclk; + `else + assign wdt_clk = smclk; + `endif +`endif + +// Reset synchronizer for the watchdog local clock domain +//-------------------------------------------------------- + +wire wdt_rst_noscan; +wire wdt_rst; + +// Reset Synchronizer +omsp_sync_reset sync_reset_por ( + .rst_s (wdt_rst_noscan), + .clk (wdt_clk), + .rst_a (puc_rst) +); + +// Scan Reset Mux +omsp_scan_mux scan_mux_wdt_rst ( + .scan_mode (scan_mode), + .data_in_scan (puc_rst), + .data_in_func (wdt_rst_noscan), + .data_out (wdt_rst) +); + + +// Watchog counter clear (synchronization) +//----------------------------------------- + +// Toggle bit whenever the watchog needs to be cleared +reg wdtcnt_clr_toggle; +wire wdtcnt_clr_detect = (wdtctl_wr & per_din[3]); +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) wdtcnt_clr_toggle <= 1'b0; + else if (wdtcnt_clr_detect) wdtcnt_clr_toggle <= ~wdtcnt_clr_toggle; + +// Synchronization +wire wdtcnt_clr_sync; +omsp_sync_cell sync_cell_wdtcnt_clr ( + .data_out (wdtcnt_clr_sync), + .data_in (wdtcnt_clr_toggle), + .clk (wdt_clk), + .rst (wdt_rst) +); + +// Edge detection +reg wdtcnt_clr_sync_dly; +always @ (posedge wdt_clk or posedge wdt_rst) + if (wdt_rst) wdtcnt_clr_sync_dly <= 1'b0; + else wdtcnt_clr_sync_dly <= wdtcnt_clr_sync; + +wire wdtqn_edge; +wire wdtcnt_clr = (wdtcnt_clr_sync ^ wdtcnt_clr_sync_dly) | wdtqn_edge; + + +// Watchog counter increment (synchronization) +//---------------------------------------------- +wire wdtcnt_incr; + +omsp_sync_cell sync_cell_wdtcnt_incr ( + .data_out (wdtcnt_incr), + .data_in (~wdtctl[7] & ~dbg_freeze), + .clk (wdt_clk), + .rst (wdt_rst) +); + + +// Watchdog 16 bit counter +//-------------------------- +reg [15:0] wdtcnt; + +wire [15:0] wdtcnt_nxt = wdtcnt+16'h0001; + +`ifdef CLOCK_GATING +wire wdtcnt_en = wdtcnt_clr | wdtcnt_incr; +wire wdt_clk_cnt; +omsp_clock_gate clock_gate_wdtcnt (.gclk(wdt_clk_cnt), + .clk (wdt_clk), .enable(wdtcnt_en), .scan_enable(scan_enable)); +`else +wire wdt_clk_cnt = wdt_clk; +`endif + +always @ (posedge wdt_clk_cnt or posedge wdt_rst) + if (wdt_rst) wdtcnt <= 16'h0000; + else if (wdtcnt_clr) wdtcnt <= 16'h0000; +`ifdef CLOCK_GATING + else wdtcnt <= wdtcnt_nxt; +`else + else if (wdtcnt_incr) wdtcnt <= wdtcnt_nxt; +`endif + + +// Local synchronizer for the wdtctl.WDTISx +// configuration (note that we can live with +// a full bus synchronizer as it won't hurt +// if we get a wrong WDTISx value for a +// single clock cycle) +//-------------------------------------------- +reg [1:0] wdtisx_s; +reg [1:0] wdtisx_ss; +always @ (posedge wdt_clk_cnt or posedge wdt_rst) + if (wdt_rst) + begin + wdtisx_s <= 2'h0; + wdtisx_ss <= 2'h0; + end + else + begin + wdtisx_s <= wdtctl[1:0]; + wdtisx_ss <= wdtisx_s; + end + + +// Interval selection mux +//-------------------------- +reg wdtqn; + +always @(wdtisx_ss or wdtcnt_nxt) + case(wdtisx_ss) + 2'b00 : wdtqn = wdtcnt_nxt[15]; + 2'b01 : wdtqn = wdtcnt_nxt[13]; + 2'b10 : wdtqn = wdtcnt_nxt[9]; + default: wdtqn = wdtcnt_nxt[6]; + endcase + + +// Watchdog event detection +//----------------------------- + +// Interval end detection +assign wdtqn_edge = (wdtqn & wdtcnt_incr); + +// Toggle bit for the transmition to the MCLK domain +reg wdt_evt_toggle; +always @ (posedge wdt_clk_cnt or posedge wdt_rst) + if (wdt_rst) wdt_evt_toggle <= 1'b0; + else if (wdtqn_edge) wdt_evt_toggle <= ~wdt_evt_toggle; + +// Synchronize in the MCLK domain +wire wdt_evt_toggle_sync; +omsp_sync_cell sync_cell_wdt_evt ( + .data_out (wdt_evt_toggle_sync), + .data_in (wdt_evt_toggle), + .clk (mclk), + .rst (puc_rst) +); + +// Delay for edge detection of the toggle bit +reg wdt_evt_toggle_sync_dly; +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) wdt_evt_toggle_sync_dly <= 1'b0; + else wdt_evt_toggle_sync_dly <= wdt_evt_toggle_sync; + +wire wdtifg_evt = (wdt_evt_toggle_sync_dly ^ wdt_evt_toggle_sync) | wdtpw_error; + + +// Watchdog wakeup generation +//------------------------------------------------------------- + +// Clear wakeup when the watchdog flag is cleared (glitch free) +reg wdtifg_clr_reg; +wire wdtifg_clr; +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) wdtifg_clr_reg <= 1'b1; + else wdtifg_clr_reg <= wdtifg_clr; + +// Set wakeup when the watchdog event is detected (glitch free) +reg wdtqn_edge_reg; +always @ (posedge wdt_clk_cnt or posedge wdt_rst) + if (wdt_rst) wdtqn_edge_reg <= 1'b0; + else wdtqn_edge_reg <= wdtqn_edge; + +// Watchdog wakeup cell +wire wdt_wkup_pre; +omsp_wakeup_cell wakeup_cell_wdog ( + .wkup_out (wdt_wkup_pre), // Wakup signal (asynchronous) + .scan_clk (mclk), // Scan clock + .scan_mode (scan_mode), // Scan mode + .scan_rst (puc_rst), // Scan reset + .wkup_clear (wdtifg_clr_reg), // Glitch free wakeup event clear + .wkup_event (wdtqn_edge_reg) // Glitch free asynchronous wakeup event +); + +// When not in HOLD, the watchdog can generate a wakeup when: +// - in interval mode (if interrupts are enabled) +// - in reset mode (always) +reg wdt_wkup_en; +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) wdt_wkup_en <= 1'b0; + else wdt_wkup_en <= ~wdtctl[7] & (~wdttmsel | (wdttmsel & wdtie)); + +// Make wakeup when not enabled +wire wdt_wkup; +omsp_and_gate and_wdt_wkup (.y(wdt_wkup), .a(wdt_wkup_pre), .b(wdt_wkup_en)); + + +// Watchdog interrupt flag +//------------------------------ +reg wdtifg; + +wire wdtifg_set = wdtifg_evt | wdtifg_sw_set; +assign wdtifg_clr = (wdtifg_irq_clr & wdttmsel) | wdtifg_sw_clr; + +always @ (posedge mclk or posedge por) + if (por) wdtifg <= 1'b0; + else if (wdtifg_set) wdtifg <= 1'b1; + else if (wdtifg_clr) wdtifg <= 1'b0; + + +// Watchdog interrupt generation +//--------------------------------- +wire wdt_irq = wdttmsel & wdtifg & wdtie; + + +// Watchdog reset generation +//----------------------------- +reg wdt_reset; + +always @ (posedge mclk or posedge por) + if (por) wdt_reset <= 1'b0; + else wdt_reset <= wdtpw_error | (wdtifg_set & ~wdttmsel); + + + +//============================================================================= +// 6) WATCHDOG TIMER (FPGA IMPLEMENTATION) +//============================================================================= +`else + +// Watchdog clock source selection +//--------------------------------- +wire clk_src_en = wdtctl[2] ? aclk_en : smclk_en; + + +// Watchdog 16 bit counter +//-------------------------- +reg [15:0] wdtcnt; + +wire wdtifg_evt; +wire wdtcnt_clr = (wdtctl_wr & per_din[3]) | wdtifg_evt; +wire wdtcnt_incr = ~wdtctl[7] & clk_src_en & ~dbg_freeze; + +wire [15:0] wdtcnt_nxt = wdtcnt+16'h0001; + +always @ (posedge mclk or posedge puc_rst) + if (puc_rst) wdtcnt <= 16'h0000; + else if (wdtcnt_clr) wdtcnt <= 16'h0000; + else if (wdtcnt_incr) wdtcnt <= wdtcnt_nxt; + + +// Interval selection mux +//-------------------------- +reg wdtqn; + +always @(wdtctl or wdtcnt_nxt) + case(wdtctl[1:0]) + 2'b00 : wdtqn = wdtcnt_nxt[15]; + 2'b01 : wdtqn = wdtcnt_nxt[13]; + 2'b10 : wdtqn = wdtcnt_nxt[9]; + default: wdtqn = wdtcnt_nxt[6]; + endcase + + +// Watchdog event detection +//----------------------------- + +assign wdtifg_evt = (wdtqn & wdtcnt_incr) | wdtpw_error; + + +// Watchdog interrupt flag +//------------------------------ +reg wdtifg; + +wire wdtifg_set = wdtifg_evt | wdtifg_sw_set; +wire wdtifg_clr = (wdtifg_irq_clr & wdttmsel) | wdtifg_sw_clr; + +always @ (posedge mclk or posedge por) + if (por) wdtifg <= 1'b0; + else if (wdtifg_set) wdtifg <= 1'b1; + else if (wdtifg_clr) wdtifg <= 1'b0; + + +// Watchdog interrupt generation +//--------------------------------- +wire wdt_irq = wdttmsel & wdtifg & wdtie; +wire wdt_wkup = 1'b0; + + +// Watchdog reset generation +//----------------------------- +reg wdt_reset; + +always @ (posedge mclk or posedge por) + if (por) wdt_reset <= 1'b0; + else wdt_reset <= wdtpw_error | (wdtifg_set & ~wdttmsel); + + +`endif + + +endmodule // omsp_watchdog + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif diff --git a/tests/openmsp430/rtl/openMSP430.v b/tests/openmsp430/rtl/openMSP430.v new file mode 100644 index 00000000..938548aa --- /dev/null +++ b/tests/openmsp430/rtl/openMSP430.v @@ -0,0 +1,584 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: openMSP430.v +// +// *Module Description: +// openMSP430 Top level file +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 134 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2012-03-22 21:31:06 +0100 (Thu, 22 Mar 2012) $ +//---------------------------------------------------------------------------- +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_defines.v" +`endif + +module openMSP430 ( + +// OUTPUTs + aclk, // ASIC ONLY: ACLK + aclk_en, // FPGA ONLY: ACLK enable + dbg_freeze, // Freeze peripherals + dbg_uart_txd, // Debug interface: UART TXD + dco_enable, // ASIC ONLY: Fast oscillator enable + dco_wkup, // ASIC ONLY: Fast oscillator wake-up (asynchronous) + dmem_addr, // Data Memory address + dmem_cen, // Data Memory chip enable (low active) + dmem_din, // Data Memory data input + dmem_wen, // Data Memory write enable (low active) + irq_acc, // Interrupt request accepted (one-hot signal) + lfxt_enable, // ASIC ONLY: Low frequency oscillator enable + lfxt_wkup, // ASIC ONLY: Low frequency oscillator wake-up (asynchronous) + mclk, // Main system clock + per_addr, // Peripheral address + per_din, // Peripheral data input + per_we, // Peripheral write enable (high active) + per_en, // Peripheral enable (high active) + pmem_addr, // Program Memory address + pmem_cen, // Program Memory chip enable (low active) + pmem_din, // Program Memory data input (optional) + pmem_wen, // Program Memory write enable (low active) (optional) + puc_rst, // Main system reset + smclk, // ASIC ONLY: SMCLK + smclk_en, // FPGA ONLY: SMCLK enable + +// INPUTs + cpu_en, // Enable CPU code execution (asynchronous and non-glitchy) + dbg_en, // Debug interface enable (asynchronous and non-glitchy) + dbg_uart_rxd, // Debug interface: UART RXD (asynchronous) + dco_clk, // Fast oscillator (fast clock) + dmem_dout, // Data Memory data output + irq, // Maskable interrupts + lfxt_clk, // Low frequency oscillator (typ 32kHz) + nmi, // Non-maskable interrupt (asynchronous) + per_dout, // Peripheral data output + pmem_dout, // Program Memory data output + reset_n, // Reset Pin (low active, asynchronous and non-glitchy) + scan_enable, // ASIC ONLY: Scan enable (active during scan shifting) + scan_mode, // ASIC ONLY: Scan mode + wkup // ASIC ONLY: System Wake-up (asynchronous and non-glitchy) +); + +// OUTPUTs +//========= +output aclk; // ASIC ONLY: ACLK +output aclk_en; // FPGA ONLY: ACLK enable +output dbg_freeze; // Freeze peripherals +output dbg_uart_txd; // Debug interface: UART TXD +output dco_enable; // ASIC ONLY: Fast oscillator enable +output dco_wkup; // ASIC ONLY: Fast oscillator wake-up (asynchronous) +output [`DMEM_MSB:0] dmem_addr; // Data Memory address +output dmem_cen; // Data Memory chip enable (low active) +output [15:0] dmem_din; // Data Memory data input +output [1:0] dmem_wen; // Data Memory write enable (low active) +output [13:0] irq_acc; // Interrupt request accepted (one-hot signal) +output lfxt_enable; // ASIC ONLY: Low frequency oscillator enable +output lfxt_wkup; // ASIC ONLY: Low frequency oscillator wake-up (asynchronous) +output mclk; // Main system clock +output [13:0] per_addr; // Peripheral address +output [15:0] per_din; // Peripheral data input +output [1:0] per_we; // Peripheral write enable (high active) +output per_en; // Peripheral enable (high active) +output [`PMEM_MSB:0] pmem_addr; // Program Memory address +output pmem_cen; // Program Memory chip enable (low active) +output [15:0] pmem_din; // Program Memory data input (optional) +output [1:0] pmem_wen; // Program Memory write enable (low active) (optional) +output puc_rst; // Main system reset +output smclk; // ASIC ONLY: SMCLK +output smclk_en; // FPGA ONLY: SMCLK enable + + +// INPUTs +//========= +input cpu_en; // Enable CPU code execution (asynchronous and non-glitchy) +input dbg_en; // Debug interface enable (asynchronous and non-glitchy) +input dbg_uart_rxd; // Debug interface: UART RXD (asynchronous) +input dco_clk; // Fast oscillator (fast clock) +input [15:0] dmem_dout; // Data Memory data output +input [13:0] irq; // Maskable interrupts +input lfxt_clk; // Low frequency oscillator (typ 32kHz) +input nmi; // Non-maskable interrupt (asynchronous and non-glitchy) +input [15:0] per_dout; // Peripheral data output +input [15:0] pmem_dout; // Program Memory data output +input reset_n; // Reset Pin (active low, asynchronous and non-glitchy) +input scan_enable; // ASIC ONLY: Scan enable (active during scan shifting) +input scan_mode; // ASIC ONLY: Scan mode +input wkup; // ASIC ONLY: System Wake-up (asynchronous and non-glitchy) + + + +//============================================================================= +// 1) INTERNAL WIRES/REGISTERS/PARAMETERS DECLARATION +//============================================================================= + +wire [7:0] inst_ad; +wire [7:0] inst_as; +wire [11:0] inst_alu; +wire inst_bw; +wire inst_irq_rst; +wire inst_mov; +wire [15:0] inst_dest; +wire [15:0] inst_dext; +wire [15:0] inst_sext; +wire [7:0] inst_so; +wire [15:0] inst_src; +wire [2:0] inst_type; +wire [7:0] inst_jmp; +wire [3:0] e_state; +wire exec_done; +wire decode_noirq; +wire cpu_en_s; +wire cpuoff; +wire oscoff; +wire scg0; +wire scg1; +wire por; +wire gie; +wire mclk_enable; +wire mclk_wkup; +wire [31:0] cpu_id; + +wire [15:0] eu_mab; +wire [15:0] eu_mdb_in; +wire [15:0] eu_mdb_out; +wire [1:0] eu_mb_wr; +wire eu_mb_en; +wire [15:0] fe_mab; +wire [15:0] fe_mdb_in; +wire fe_mb_en; +wire fe_pmem_wait; + +wire pc_sw_wr; +wire [15:0] pc_sw; +wire [15:0] pc; +wire [15:0] pc_nxt; + +wire nmi_acc; +wire nmi_pnd; +wire nmi_wkup; + +wire wdtie; +wire wdtnmies; +wire wdtifg; +wire wdt_irq; +wire wdt_wkup; +wire wdt_reset; +wire wdtifg_sw_clr; +wire wdtifg_sw_set; + +wire dbg_clk; +wire dbg_rst; +wire dbg_en_s; +wire dbg_halt_st; +wire dbg_halt_cmd; +wire dbg_mem_en; +wire dbg_reg_wr; +wire dbg_cpu_reset; +wire [15:0] dbg_mem_addr; +wire [15:0] dbg_mem_dout; +wire [15:0] dbg_mem_din; +wire [15:0] dbg_reg_din; +wire [1:0] dbg_mem_wr; +wire puc_pnd_set; + +wire [15:0] per_dout_or; +wire [15:0] per_dout_sfr; +wire [15:0] per_dout_wdog; +wire [15:0] per_dout_mpy; +wire [15:0] per_dout_clk; + + +//============================================================================= +// 2) GLOBAL CLOCK & RESET MANAGEMENT +//============================================================================= + +omsp_clock_module clock_module_0 ( + +// OUTPUTs + .aclk (aclk), // ACLK + .aclk_en (aclk_en), // ACLK enablex + .cpu_en_s (cpu_en_s), // Enable CPU code execution (synchronous) + .dbg_clk (dbg_clk), // Debug unit clock + .dbg_en_s (dbg_en_s), // Debug interface enable (synchronous) + .dbg_rst (dbg_rst), // Debug unit reset + .dco_enable (dco_enable), // Fast oscillator enable + .dco_wkup (dco_wkup), // Fast oscillator wake-up (asynchronous) + .lfxt_enable (lfxt_enable), // Low frequency oscillator enable + .lfxt_wkup (lfxt_wkup), // Low frequency oscillator wake-up (asynchronous) + .mclk (mclk), // Main system clock + .per_dout (per_dout_clk), // Peripheral data output + .por (por), // Power-on reset + .puc_pnd_set (puc_pnd_set), // PUC pending set for the serial debug interface + .puc_rst (puc_rst), // Main system reset + .smclk (smclk), // SMCLK + .smclk_en (smclk_en), // SMCLK enable + +// INPUTs + .cpu_en (cpu_en), // Enable CPU code execution (asynchronous) + .cpuoff (cpuoff), // Turns off the CPU + .dbg_cpu_reset(dbg_cpu_reset), // Reset CPU from debug interface + .dbg_en (dbg_en), // Debug interface enable (asynchronous) + .dco_clk (dco_clk), // Fast oscillator (fast clock) + .lfxt_clk (lfxt_clk), // Low frequency oscillator (typ 32kHz) + .mclk_enable (mclk_enable), // Main System Clock enable + .mclk_wkup (mclk_wkup), // Main System Clock wake-up (asynchronous) + .oscoff (oscoff), // Turns off LFXT1 clock input + .per_addr (per_addr), // Peripheral address + .per_din (per_din), // Peripheral data input + .per_en (per_en), // Peripheral enable (high active) + .per_we (per_we), // Peripheral write enable (high active) + .reset_n (reset_n), // Reset Pin (low active, asynchronous) + .scan_enable (scan_enable), // Scan enable (active during scan shifting) + .scan_mode (scan_mode), // Scan mode + .scg0 (scg0), // System clock generator 1. Turns off the DCO + .scg1 (scg1), // System clock generator 1. Turns off the SMCLK + .wdt_reset (wdt_reset) // Watchdog-timer reset +); + + +//============================================================================= +// 3) FRONTEND (<=> FETCH & DECODE) +//============================================================================= + +omsp_frontend frontend_0 ( + +// OUTPUTs + .dbg_halt_st (dbg_halt_st), // Halt/Run status from CPU + .decode_noirq (decode_noirq), // Frontend decode instruction + .e_state (e_state), // Execution state + .exec_done (exec_done), // Execution completed + .inst_ad (inst_ad), // Decoded Inst: destination addressing mode + .inst_as (inst_as), // Decoded Inst: source addressing mode + .inst_alu (inst_alu), // ALU control signals + .inst_bw (inst_bw), // Decoded Inst: byte width + .inst_dest (inst_dest), // Decoded Inst: destination (one hot) + .inst_dext (inst_dext), // Decoded Inst: destination extended instruction word + .inst_irq_rst (inst_irq_rst), // Decoded Inst: Reset interrupt + .inst_jmp (inst_jmp), // Decoded Inst: Conditional jump + .inst_mov (inst_mov), // Decoded Inst: mov instruction + .inst_sext (inst_sext), // Decoded Inst: source extended instruction word + .inst_so (inst_so), // Decoded Inst: Single-operand arithmetic + .inst_src (inst_src), // Decoded Inst: source (one hot) + .inst_type (inst_type), // Decoded Instruction type + .irq_acc (irq_acc), // Interrupt request accepted + .mab (fe_mab), // Frontend Memory address bus + .mb_en (fe_mb_en), // Frontend Memory bus enable + .mclk_enable (mclk_enable), // Main System Clock enable + .mclk_wkup (mclk_wkup), // Main System Clock wake-up (asynchronous) + .nmi_acc (nmi_acc), // Non-Maskable interrupt request accepted + .pc (pc), // Program counter + .pc_nxt (pc_nxt), // Next PC value (for CALL & IRQ) + +// INPUTs + .cpu_en_s (cpu_en_s), // Enable CPU code execution (synchronous) + .cpuoff (cpuoff), // Turns off the CPU + .dbg_halt_cmd (dbg_halt_cmd), // Halt CPU command + .dbg_reg_sel (dbg_mem_addr[3:0]), // Debug selected register for rd/wr access + .fe_pmem_wait (fe_pmem_wait), // Frontend wait for Instruction fetch + .gie (gie), // General interrupt enable + .irq (irq), // Maskable interrupts + .mclk (mclk), // Main system clock + .mdb_in (fe_mdb_in), // Frontend Memory data bus input + .nmi_pnd (nmi_pnd), // Non-maskable interrupt pending + .nmi_wkup (nmi_wkup), // NMI Wakeup + .pc_sw (pc_sw), // Program counter software value + .pc_sw_wr (pc_sw_wr), // Program counter software write + .puc_rst (puc_rst), // Main system reset + .scan_enable (scan_enable), // Scan enable (active during scan shifting) + .wdt_irq (wdt_irq), // Watchdog-timer interrupt + .wdt_wkup (wdt_wkup), // Watchdog Wakeup + .wkup (wkup) // System Wake-up (asynchronous) +); + + +//============================================================================= +// 4) EXECUTION UNIT +//============================================================================= + +omsp_execution_unit execution_unit_0 ( + +// OUTPUTs + .cpuoff (cpuoff), // Turns off the CPU + .dbg_reg_din (dbg_reg_din), // Debug unit CPU register data input + .mab (eu_mab), // Memory address bus + .mb_en (eu_mb_en), // Memory bus enable + .mb_wr (eu_mb_wr), // Memory bus write transfer + .mdb_out (eu_mdb_out), // Memory data bus output + .oscoff (oscoff), // Turns off LFXT1 clock input + .pc_sw (pc_sw), // Program counter software value + .pc_sw_wr (pc_sw_wr), // Program counter software write + .scg0 (scg0), // System clock generator 1. Turns off the DCO + .scg1 (scg1), // System clock generator 1. Turns off the SMCLK + +// INPUTs + .dbg_halt_st (dbg_halt_st), // Halt/Run status from CPU + .dbg_mem_dout (dbg_mem_dout), // Debug unit data output + .dbg_reg_wr (dbg_reg_wr), // Debug unit CPU register write + .e_state (e_state), // Execution state + .exec_done (exec_done), // Execution completed + .gie (gie), // General interrupt enable + .inst_ad (inst_ad), // Decoded Inst: destination addressing mode + .inst_as (inst_as), // Decoded Inst: source addressing mode + .inst_alu (inst_alu), // ALU control signals + .inst_bw (inst_bw), // Decoded Inst: byte width + .inst_dest (inst_dest), // Decoded Inst: destination (one hot) + .inst_dext (inst_dext), // Decoded Inst: destination extended instruction word + .inst_irq_rst (inst_irq_rst), // Decoded Inst: reset interrupt + .inst_jmp (inst_jmp), // Decoded Inst: Conditional jump + .inst_mov (inst_mov), // Decoded Inst: mov instruction + .inst_sext (inst_sext), // Decoded Inst: source extended instruction word + .inst_so (inst_so), // Decoded Inst: Single-operand arithmetic + .inst_src (inst_src), // Decoded Inst: source (one hot) + .inst_type (inst_type), // Decoded Instruction type + .mclk (mclk), // Main system clock + .mdb_in (eu_mdb_in), // Memory data bus input + .pc (pc), // Program counter + .pc_nxt (pc_nxt), // Next PC value (for CALL & IRQ) + .puc_rst (puc_rst), // Main system reset + .scan_enable (scan_enable) // Scan enable (active during scan shifting) +); + + +//============================================================================= +// 5) MEMORY BACKBONE +//============================================================================= + +omsp_mem_backbone mem_backbone_0 ( + +// OUTPUTs + .dbg_mem_din (dbg_mem_din), // Debug unit Memory data input + .dmem_addr (dmem_addr), // Data Memory address + .dmem_cen (dmem_cen), // Data Memory chip enable (low active) + .dmem_din (dmem_din), // Data Memory data input + .dmem_wen (dmem_wen), // Data Memory write enable (low active) + .eu_mdb_in (eu_mdb_in), // Execution Unit Memory data bus input + .fe_mdb_in (fe_mdb_in), // Frontend Memory data bus input + .fe_pmem_wait (fe_pmem_wait), // Frontend wait for Instruction fetch + .per_addr (per_addr), // Peripheral address + .per_din (per_din), // Peripheral data input + .per_we (per_we), // Peripheral write enable (high active) + .per_en (per_en), // Peripheral enable (high active) + .pmem_addr (pmem_addr), // Program Memory address + .pmem_cen (pmem_cen), // Program Memory chip enable (low active) + .pmem_din (pmem_din), // Program Memory data input (optional) + .pmem_wen (pmem_wen), // Program Memory write enable (low active) (optional) + +// INPUTs + .dbg_halt_st (dbg_halt_st), // Halt/Run status from CPU + .dbg_mem_addr (dbg_mem_addr), // Debug address for rd/wr access + .dbg_mem_dout (dbg_mem_dout), // Debug unit data output + .dbg_mem_en (dbg_mem_en), // Debug unit memory enable + .dbg_mem_wr (dbg_mem_wr), // Debug unit memory write + .dmem_dout (dmem_dout), // Data Memory data output + .eu_mab (eu_mab[15:1]), // Execution Unit Memory address bus + .eu_mb_en (eu_mb_en), // Execution Unit Memory bus enable + .eu_mb_wr (eu_mb_wr), // Execution Unit Memory bus write transfer + .eu_mdb_out (eu_mdb_out), // Execution Unit Memory data bus output + .fe_mab (fe_mab[15:1]), // Frontend Memory address bus + .fe_mb_en (fe_mb_en), // Frontend Memory bus enable + .mclk (mclk), // Main system clock + .per_dout (per_dout_or), // Peripheral data output + .pmem_dout (pmem_dout), // Program Memory data output + .puc_rst (puc_rst), // Main system reset + .scan_enable (scan_enable) // Scan enable (active during scan shifting) +); + + +//============================================================================= +// 6) SPECIAL FUNCTION REGISTERS +//============================================================================= +omsp_sfr sfr_0 ( + +// OUTPUTs + .cpu_id (cpu_id), // CPU ID + .nmi_pnd (nmi_pnd), // NMI Pending + .nmi_wkup (nmi_wkup), // NMI Wakeup + .per_dout (per_dout_sfr), // Peripheral data output + .wdtie (wdtie), // Watchdog-timer interrupt enable + .wdtifg_sw_clr(wdtifg_sw_clr), // Watchdog-timer interrupt flag software clear + .wdtifg_sw_set(wdtifg_sw_set), // Watchdog-timer interrupt flag software set + +// INPUTs + .mclk (mclk), // Main system clock + .nmi (nmi), // Non-maskable interrupt (asynchronous) + .nmi_acc (nmi_acc), // Non-Maskable interrupt request accepted + .per_addr (per_addr), // Peripheral address + .per_din (per_din), // Peripheral data input + .per_en (per_en), // Peripheral enable (high active) + .per_we (per_we), // Peripheral write enable (high active) + .puc_rst (puc_rst), // Main system reset + .scan_mode (scan_mode), // Scan mode + .wdtifg (wdtifg), // Watchdog-timer interrupt flag + .wdtnmies (wdtnmies) // Watchdog-timer NMI edge selection +); + + +//============================================================================= +// 7) WATCHDOG TIMER +//============================================================================= +`ifdef WATCHDOG +omsp_watchdog watchdog_0 ( + +// OUTPUTs + .per_dout (per_dout_wdog), // Peripheral data output + .wdt_irq (wdt_irq), // Watchdog-timer interrupt + .wdt_reset (wdt_reset), // Watchdog-timer reset + .wdt_wkup (wdt_wkup), // Watchdog Wakeup + .wdtifg (wdtifg), // Watchdog-timer interrupt flag + .wdtnmies (wdtnmies), // Watchdog-timer NMI edge selection + +// INPUTs + .aclk (aclk), // ACLK + .aclk_en (aclk_en), // ACLK enable + .dbg_freeze (dbg_freeze), // Freeze Watchdog counter + .mclk (mclk), // Main system clock + .per_addr (per_addr), // Peripheral address + .per_din (per_din), // Peripheral data input + .per_en (per_en), // Peripheral enable (high active) + .per_we (per_we), // Peripheral write enable (high active) + .por (por), // Power-on reset + .puc_rst (puc_rst), // Main system reset + .scan_enable (scan_enable), // Scan enable (active during scan shifting) + .scan_mode (scan_mode), // Scan mode + .smclk (smclk), // SMCLK + .smclk_en (smclk_en), // SMCLK enable + .wdtie (wdtie), // Watchdog-timer interrupt enable + .wdtifg_irq_clr (irq_acc[10]), // Clear Watchdog-timer interrupt flag + .wdtifg_sw_clr (wdtifg_sw_clr), // Watchdog-timer interrupt flag software clear + .wdtifg_sw_set (wdtifg_sw_set) // Watchdog-timer interrupt flag software set +); +`else +assign per_dout_wdog = 16'h0000; +assign wdt_irq = 1'b0; +assign wdt_reset = 1'b0; +assign wdt_wkup = 1'b0; +assign wdtifg = 1'b0; +assign wdtnmies = 1'b0; +`endif + + +//============================================================================= +// 8) HARDWARE MULTIPLIER +//============================================================================= +`ifdef MULTIPLIER +omsp_multiplier multiplier_0 ( + +// OUTPUTs + .per_dout (per_dout_mpy), // Peripheral data output + +// INPUTs + .mclk (mclk), // Main system clock + .per_addr (per_addr), // Peripheral address + .per_din (per_din), // Peripheral data input + .per_en (per_en), // Peripheral enable (high active) + .per_we (per_we), // Peripheral write enable (high active) + .puc_rst (puc_rst), // Main system reset + .scan_enable (scan_enable) // Scan enable (active during scan shifting) +); +`else +assign per_dout_mpy = 16'h0000; +`endif + +//============================================================================= +// 9) PERIPHERALS' OUTPUT BUS +//============================================================================= + +assign per_dout_or = per_dout | + per_dout_clk | + per_dout_sfr | + per_dout_wdog | + per_dout_mpy; + + +//============================================================================= +// 10) DEBUG INTERFACE +//============================================================================= + +`ifdef DBG_EN +omsp_dbg dbg_0 ( + +// OUTPUTs + .dbg_freeze (dbg_freeze), // Freeze peripherals + .dbg_halt_cmd (dbg_halt_cmd), // Halt CPU command + .dbg_mem_addr (dbg_mem_addr), // Debug address for rd/wr access + .dbg_mem_dout (dbg_mem_dout), // Debug unit data output + .dbg_mem_en (dbg_mem_en), // Debug unit memory enable + .dbg_mem_wr (dbg_mem_wr), // Debug unit memory write + .dbg_reg_wr (dbg_reg_wr), // Debug unit CPU register write + .dbg_cpu_reset(dbg_cpu_reset), // Reset CPU from debug interface + .dbg_uart_txd (dbg_uart_txd), // Debug interface: UART TXD + +// INPUTs + .cpu_en_s (cpu_en_s), // Enable CPU code execution (synchronous) + .cpu_id (cpu_id), // CPU ID + .dbg_clk (dbg_clk), // Debug unit clock + .dbg_en_s (dbg_en_s), // Debug interface enable (synchronous) + .dbg_halt_st (dbg_halt_st), // Halt/Run status from CPU + .dbg_mem_din (dbg_mem_din), // Debug unit Memory data input + .dbg_reg_din (dbg_reg_din), // Debug unit CPU register data input + .dbg_rst (dbg_rst), // Debug unit reset + .dbg_uart_rxd (dbg_uart_rxd), // Debug interface: UART RXD (asynchronous) + .decode_noirq (decode_noirq), // Frontend decode instruction + .eu_mab (eu_mab), // Execution-Unit Memory address bus + .eu_mb_en (eu_mb_en), // Execution-Unit Memory bus enable + .eu_mb_wr (eu_mb_wr), // Execution-Unit Memory bus write transfer + .eu_mdb_in (eu_mdb_in), // Memory data bus input + .eu_mdb_out (eu_mdb_out), // Memory data bus output + .exec_done (exec_done), // Execution completed + .fe_mb_en (fe_mb_en), // Frontend Memory bus enable + .fe_mdb_in (fe_mdb_in), // Frontend Memory data bus input + .pc (pc), // Program counter + .puc_pnd_set (puc_pnd_set) // PUC pending set for the serial debug interface +); + +`else +assign dbg_freeze = ~cpu_en_s; +assign dbg_halt_cmd = 1'b0; +assign dbg_mem_addr = 16'h0000; +assign dbg_mem_dout = 16'h0000; +assign dbg_mem_en = 1'b0; +assign dbg_mem_wr = 2'b00; +assign dbg_reg_wr = 1'b0; +assign dbg_cpu_reset = 1'b0; +assign dbg_uart_txd = 1'b0; +`endif + + +endmodule // openMSP430 + +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif diff --git a/tests/openmsp430/rtl/openMSP430_defines.v b/tests/openmsp430/rtl/openMSP430_defines.v new file mode 100644 index 00000000..368f7a5b --- /dev/null +++ b/tests/openmsp430/rtl/openMSP430_defines.v @@ -0,0 +1,843 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: openMSP430_defines.v +// +// *Module Description: +// openMSP430 Configuration file +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 151 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2012-07-23 00:24:11 +0200 (Mon, 23 Jul 2012) $ +//---------------------------------------------------------------------------- +//`define OMSP_NO_INCLUDE +`ifdef OMSP_NO_INCLUDE +`else +`include "openMSP430_undefines.v" +`endif + +//============================================================================ +//============================================================================ +// BASIC SYSTEM CONFIGURATION +//============================================================================ +//============================================================================ +// +// Note: the sum of program, data and peripheral memory spaces must not +// exceed 64 kB +// + +// Program Memory Size: +// Uncomment the required memory size +//------------------------------------------------------- +//`define PMEM_SIZE_CUSTOM +//`define PMEM_SIZE_59_KB +//`define PMEM_SIZE_55_KB +//`define PMEM_SIZE_54_KB +//`define PMEM_SIZE_51_KB +//`define PMEM_SIZE_48_KB +//`define PMEM_SIZE_41_KB +//`define PMEM_SIZE_32_KB +//`define PMEM_SIZE_24_KB +//`define PMEM_SIZE_16_KB +//`define PMEM_SIZE_12_KB +//`define PMEM_SIZE_8_KB +//`define PMEM_SIZE_4_KB +`define PMEM_SIZE_2_KB +//`define PMEM_SIZE_1_KB + + +// Data Memory Size: +// Uncomment the required memory size +//------------------------------------------------------- +//`define DMEM_SIZE_CUSTOM +//`define DMEM_SIZE_32_KB +//`define DMEM_SIZE_24_KB +//`define DMEM_SIZE_16_KB +//`define DMEM_SIZE_10_KB +//`define DMEM_SIZE_8_KB +//`define DMEM_SIZE_5_KB +//`define DMEM_SIZE_4_KB +//`define DMEM_SIZE_2p5_KB +//`define DMEM_SIZE_2_KB +//`define DMEM_SIZE_1_KB +//`define DMEM_SIZE_512_B +//`define DMEM_SIZE_256_B +`define DMEM_SIZE_128_B + + +// Include/Exclude Hardware Multiplier +`define MULTIPLIER + + +// Include/Exclude Serial Debug interface +`define DBG_EN + + +//============================================================================ +//============================================================================ +// ADVANCED SYSTEM CONFIGURATION (FOR EXPERIENCED USERS) +//============================================================================ +//============================================================================ + +//------------------------------------------------------- +// Custom user version number +//------------------------------------------------------- +// This 5 bit field can be freely used in order to allow +// custom identification of the system through the debug +// interface. +// (see CPU_ID.USER_VERSION field in the documentation) +//------------------------------------------------------- +`define USER_VERSION 5'b00000 + + +//------------------------------------------------------- +// Include/Exclude Watchdog timer +//------------------------------------------------------- +// When excluded, the following functionality will be +// lost: +// - Watchog (both interval and watchdog modes) +// - NMI interrupt edge selection +// - Possibility to generate a software PUC reset +//------------------------------------------------------- +`define WATCHDOG + + +///------------------------------------------------------- +// Include/Exclude Non-Maskable-Interrupt support +//------------------------------------------------------- +`define NMI + + +//------------------------------------------------------- +// Input synchronizers +//------------------------------------------------------- +// In some cases, the asynchronous input ports might +// already be synchronized externally. +// If an extensive CDC design review showed that this +// is really the case, the individual synchronizers +// can be disabled with the following defines. +// +// Notes: +// - all three signals are all sampled in the MCLK domain +// +// - the dbg_en signal reset the debug interface +// when 0. Therefore make sure it is glitch free. +// +//------------------------------------------------------- +`define SYNC_NMI +//`define SYNC_CPU_EN +//`define SYNC_DBG_EN + + +//------------------------------------------------------- +// Peripheral Memory Space: +//------------------------------------------------------- +// The original MSP430 architecture map the peripherals +// from 0x0000 to 0x01FF (i.e. 512B of the memory space). +// The following defines allow you to expand this space +// up to 32 kB (i.e. from 0x0000 to 0x7fff). +// As a consequence, the data memory mapping will be +// shifted up and a custom linker script will therefore +// be required by the GCC compiler. +//------------------------------------------------------- +//`define PER_SIZE_CUSTOM +//`define PER_SIZE_32_KB +//`define PER_SIZE_16_KB +//`define PER_SIZE_8_KB +//`define PER_SIZE_4_KB +//`define PER_SIZE_2_KB +//`define PER_SIZE_1_KB +`define PER_SIZE_512_B + + +//------------------------------------------------------- +// Defines the debugger CPU_CTL.RST_BRK_EN reset value +// (CPU break on PUC reset) +//------------------------------------------------------- +// When defined, the CPU will automatically break after +// a PUC occurrence by default. This is typically useful +// when the program memory can only be initialized through +// the serial debug interface. +//------------------------------------------------------- +`define DBG_RST_BRK_EN + + +//============================================================================ +//============================================================================ +// EXPERT SYSTEM CONFIGURATION ( !!!! EXPERTS ONLY !!!! ) +//============================================================================ +//============================================================================ +// +// IMPORTANT NOTE: Please update following configuration options ONLY if +// you have a good reason to do so... and if you know what +// you are doing :-P +// +//============================================================================ + +//------------------------------------------------------- +// Number of hardware breakpoint/watchpoint units +// (each unit contains two hardware addresses available +// for breakpoints or watchpoints): +// - DBG_HWBRK_0 -> Include hardware breakpoints unit 0 +// - DBG_HWBRK_1 -> Include hardware breakpoints unit 1 +// - DBG_HWBRK_2 -> Include hardware breakpoints unit 2 +// - DBG_HWBRK_3 -> Include hardware breakpoints unit 3 +//------------------------------------------------------- +// Please keep in mind that hardware breakpoints only +// make sense whenever the program memory is not an SRAM +// (i.e. Flash/OTP/ROM/...) or when you are interested +// in data breakpoints. +//------------------------------------------------------- +//`define DBG_HWBRK_0 +//`define DBG_HWBRK_1 +//`define DBG_HWBRK_2 +//`define DBG_HWBRK_3 + + +//------------------------------------------------------- +// Enable/Disable the hardware breakpoint RANGE mode +//------------------------------------------------------- +// When enabled this feature allows the hardware breakpoint +// units to stop the cpu whenever an instruction or data +// access lays within an address range. +// Note that this feature is not supported by GDB. +//------------------------------------------------------- +//`define DBG_HWBRK_RANGE + + +//------------------------------------------------------- +// Custom Program/Data and Peripheral Memory Spaces +//------------------------------------------------------- +// The following values are valid only if the +// corresponding *_SIZE_CUSTOM defines are uncommented: +// +// - *_SIZE : size of the section in bytes. +// - *_AWIDTH : address port width, this value must allow +// to address all WORDS of the section +// (i.e. the *_SIZE divided by 2) +//------------------------------------------------------- + +// Custom Program memory (enabled with PMEM_SIZE_CUSTOM) +`define PMEM_CUSTOM_AWIDTH 10 +`define PMEM_CUSTOM_SIZE 2028 + +// Custom Data memory (enabled with DMEM_SIZE_CUSTOM) +`define DMEM_CUSTOM_AWIDTH 6 +`define DMEM_CUSTOM_SIZE 128 + +// Custom Peripheral memory (enabled with PER_SIZE_CUSTOM) +`define PER_CUSTOM_AWIDTH 8 +`define PER_CUSTOM_SIZE 512 + + +//------------------------------------------------------- +// ASIC version +//------------------------------------------------------- +// When uncommented, this define will enable the +// ASIC system configuration section (see below) and +// will activate scan support for production test. +// +// WARNING: if you target an FPGA, leave this define +// commented. +//------------------------------------------------------- +//`define ASIC + + +//============================================================================ +//============================================================================ +// ASIC SYSTEM CONFIGURATION ( !!!! EXPERTS/PROFESSIONALS ONLY !!!! ) +//============================================================================ +//============================================================================ +`ifdef ASIC + +//=============================================================== +// FINE GRAINED CLOCK GATING +//=============================================================== + +//------------------------------------------------------- +// When uncommented, this define will enable the fine +// grained clock gating of all registers in the core. +//------------------------------------------------------- +`define CLOCK_GATING + + +//=============================================================== +// LFXT CLOCK DOMAIN +//=============================================================== + +//------------------------------------------------------- +// When uncommented, this define will enable the lfxt_clk +// clock domain. +// When commented out, the whole chip is clocked with dco_clk. +//------------------------------------------------------- +`define LFXT_DOMAIN + + +//=============================================================== +// CLOCK MUXES +//=============================================================== + +//------------------------------------------------------- +// MCLK: Clock Mux +//------------------------------------------------------- +// When uncommented, this define will enable the +// MCLK clock MUX allowing the selection between +// DCO_CLK and LFXT_CLK with the BCSCTL2.SELMx register. +// When commented, DCO_CLK is selected. +//------------------------------------------------------- +`define MCLK_MUX + +//------------------------------------------------------- +// SMCLK: Clock Mux +//------------------------------------------------------- +// When uncommented, this define will enable the +// SMCLK clock MUX allowing the selection between +// DCO_CLK and LFXT_CLK with the BCSCTL2.SELS register. +// When commented, DCO_CLK is selected. +//------------------------------------------------------- +`define SMCLK_MUX + +//------------------------------------------------------- +// WATCHDOG: Clock Mux +//------------------------------------------------------- +// When uncommented, this define will enable the +// Watchdog clock MUX allowing the selection between +// ACLK and SMCLK with the WDTCTL.WDTSSEL register. +// When commented out, ACLK is selected if the +// WATCHDOG_NOMUX_ACLK define is uncommented, SMCLK is +// selected otherwise. +//------------------------------------------------------- +`define WATCHDOG_MUX +//`define WATCHDOG_NOMUX_ACLK + + +//=============================================================== +// CLOCK DIVIDERS +//=============================================================== + +//------------------------------------------------------- +// MCLK: Clock divider +//------------------------------------------------------- +// When uncommented, this define will enable the +// MCLK clock divider (/1/2/4/8) +//------------------------------------------------------- +`define MCLK_DIVIDER + +//------------------------------------------------------- +// SMCLK: Clock divider (/1/2/4/8) +//------------------------------------------------------- +// When uncommented, this define will enable the +// SMCLK clock divider +//------------------------------------------------------- +`define SMCLK_DIVIDER + +//------------------------------------------------------- +// ACLK: Clock divider (/1/2/4/8) +//------------------------------------------------------- +// When uncommented, this define will enable the +// ACLK clock divider +//------------------------------------------------------- +`define ACLK_DIVIDER + + +//=============================================================== +// LOW POWER MODES +//=============================================================== + +//------------------------------------------------------- +// LOW POWER MODE: CPUOFF +//------------------------------------------------------- +// When uncommented, this define will include the +// clock gate allowing to switch off MCLK in +// all low power modes: LPM0, LPM1, LPM2, LPM3, LPM4 +//------------------------------------------------------- +`define CPUOFF_EN + +//------------------------------------------------------- +// LOW POWER MODE: SCG0 +//------------------------------------------------------- +// When uncommented, this define will enable the +// DCO_ENABLE/WKUP port control (always 1 when commented). +// This allows to switch off the DCO oscillator in the +// following low power modes: LPM1, LPM3, LPM4 +//------------------------------------------------------- +`define SCG0_EN + +//------------------------------------------------------- +// LOW POWER MODE: SCG1 +//------------------------------------------------------- +// When uncommented, this define will include the +// clock gate allowing to switch off SMCLK in +// the following low power modes: LPM2, LPM3, LPM4 +//------------------------------------------------------- +`define SCG1_EN + +//------------------------------------------------------- +// LOW POWER MODE: OSCOFF +//------------------------------------------------------- +// When uncommented, this define will include the +// LFXT_CLK clock gate and enable the LFXT_ENABLE/WKUP +// port control (always 1 when commented). +// This allows to switch off the low frequency oscillator +// in the following low power modes: LPM4 +//------------------------------------------------------- +`define OSCOFF_EN + + + +`endif + +//==========================================================================// +//==========================================================================// +//==========================================================================// +//==========================================================================// +//===== SYSTEM CONSTANTS --- !!!!!!!! DO NOT EDIT !!!!!!!! =====// +//==========================================================================// +//==========================================================================// +//==========================================================================// +//==========================================================================// + +// +// PROGRAM, DATA & PERIPHERAL MEMORY CONFIGURATION +//================================================== + +// Program Memory Size +`ifdef PMEM_SIZE_59_KB + `define PMEM_AWIDTH 15 + `define PMEM_SIZE 60416 +`endif +`ifdef PMEM_SIZE_55_KB + `define PMEM_AWIDTH 15 + `define PMEM_SIZE 56320 +`endif +`ifdef PMEM_SIZE_54_KB + `define PMEM_AWIDTH 15 + `define PMEM_SIZE 55296 +`endif +`ifdef PMEM_SIZE_51_KB + `define PMEM_AWIDTH 15 + `define PMEM_SIZE 52224 +`endif +`ifdef PMEM_SIZE_48_KB + `define PMEM_AWIDTH 15 + `define PMEM_SIZE 49152 +`endif +`ifdef PMEM_SIZE_41_KB + `define PMEM_AWIDTH 15 + `define PMEM_SIZE 41984 +`endif +`ifdef PMEM_SIZE_32_KB + `define PMEM_AWIDTH 14 + `define PMEM_SIZE 32768 +`endif +`ifdef PMEM_SIZE_24_KB + `define PMEM_AWIDTH 14 + `define PMEM_SIZE 24576 +`endif +`ifdef PMEM_SIZE_16_KB + `define PMEM_AWIDTH 13 + `define PMEM_SIZE 16384 +`endif +`ifdef PMEM_SIZE_12_KB + `define PMEM_AWIDTH 13 + `define PMEM_SIZE 12288 +`endif +`ifdef PMEM_SIZE_8_KB + `define PMEM_AWIDTH 12 + `define PMEM_SIZE 8192 +`endif +`ifdef PMEM_SIZE_4_KB + `define PMEM_AWIDTH 11 + `define PMEM_SIZE 4096 +`endif +`ifdef PMEM_SIZE_2_KB + `define PMEM_AWIDTH 10 + `define PMEM_SIZE 2048 +`endif +`ifdef PMEM_SIZE_1_KB + `define PMEM_AWIDTH 9 + `define PMEM_SIZE 1024 +`endif +`ifdef PMEM_SIZE_CUSTOM + `define PMEM_AWIDTH `PMEM_CUSTOM_AWIDTH + `define PMEM_SIZE `PMEM_CUSTOM_SIZE +`endif + +// Data Memory Size +`ifdef DMEM_SIZE_32_KB + `define DMEM_AWIDTH 14 + `define DMEM_SIZE 32768 +`endif +`ifdef DMEM_SIZE_24_KB + `define DMEM_AWIDTH 14 + `define DMEM_SIZE 24576 +`endif +`ifdef DMEM_SIZE_16_KB + `define DMEM_AWIDTH 13 + `define DMEM_SIZE 16384 +`endif +`ifdef DMEM_SIZE_10_KB + `define DMEM_AWIDTH 13 + `define DMEM_SIZE 10240 +`endif +`ifdef DMEM_SIZE_8_KB + `define DMEM_AWIDTH 12 + `define DMEM_SIZE 8192 +`endif +`ifdef DMEM_SIZE_5_KB + `define DMEM_AWIDTH 12 + `define DMEM_SIZE 5120 +`endif +`ifdef DMEM_SIZE_4_KB + `define DMEM_AWIDTH 11 + `define DMEM_SIZE 4096 +`endif +`ifdef DMEM_SIZE_2p5_KB + `define DMEM_AWIDTH 11 + `define DMEM_SIZE 2560 +`endif +`ifdef DMEM_SIZE_2_KB + `define DMEM_AWIDTH 10 + `define DMEM_SIZE 2048 +`endif +`ifdef DMEM_SIZE_1_KB + `define DMEM_AWIDTH 9 + `define DMEM_SIZE 1024 +`endif +`ifdef DMEM_SIZE_512_B + `define DMEM_AWIDTH 8 + `define DMEM_SIZE 512 +`endif +`ifdef DMEM_SIZE_256_B + `define DMEM_AWIDTH 7 + `define DMEM_SIZE 256 +`endif +`ifdef DMEM_SIZE_128_B + `define DMEM_AWIDTH 6 + `define DMEM_SIZE 128 +`endif +`ifdef DMEM_SIZE_CUSTOM + `define DMEM_AWIDTH `DMEM_CUSTOM_AWIDTH + `define DMEM_SIZE `DMEM_CUSTOM_SIZE +`endif + +// Peripheral Memory Size +`ifdef PER_SIZE_32_KB + `define PER_AWIDTH 14 + `define PER_SIZE 32768 +`endif +`ifdef PER_SIZE_16_KB + `define PER_AWIDTH 13 + `define PER_SIZE 16384 +`endif +`ifdef PER_SIZE_8_KB + `define PER_AWIDTH 12 + `define PER_SIZE 8192 +`endif +`ifdef PER_SIZE_4_KB + `define PER_AWIDTH 11 + `define PER_SIZE 4096 +`endif +`ifdef PER_SIZE_2_KB + `define PER_AWIDTH 10 + `define PER_SIZE 2048 +`endif +`ifdef PER_SIZE_1_KB + `define PER_AWIDTH 9 + `define PER_SIZE 1024 +`endif +`ifdef PER_SIZE_512_B + `define PER_AWIDTH 8 + `define PER_SIZE 512 +`endif +`ifdef PER_SIZE_CUSTOM + `define PER_AWIDTH `PER_CUSTOM_AWIDTH + `define PER_SIZE `PER_CUSTOM_SIZE +`endif + +// Data Memory Base Adresses +`define DMEM_BASE `PER_SIZE + +// Program & Data Memory most significant address bit (for 16 bit words) +`define PMEM_MSB `PMEM_AWIDTH-1 +`define DMEM_MSB `DMEM_AWIDTH-1 +`define PER_MSB `PER_AWIDTH-1 + +// +// STATES, REGISTER FIELDS, ... +//====================================== + +// Instructions type +`define INST_SO 0 +`define INST_JMP 1 +`define INST_TO 2 + +// Single-operand arithmetic +`define RRC 0 +`define SWPB 1 +`define RRA 2 +`define SXT 3 +`define PUSH 4 +`define CALL 5 +`define RETI 6 +`define IRQ 7 + +// Conditional jump +`define JNE 0 +`define JEQ 1 +`define JNC 2 +`define JC 3 +`define JN 4 +`define JGE 5 +`define JL 6 +`define JMP 7 + +// Two-operand arithmetic +`define MOV 0 +`define ADD 1 +`define ADDC 2 +`define SUBC 3 +`define SUB 4 +`define CMP 5 +`define DADD 6 +`define BIT 7 +`define BIC 8 +`define BIS 9 +`define XOR 10 +`define AND 11 + +// Addressing modes +`define DIR 0 +`define IDX 1 +`define INDIR 2 +`define INDIR_I 3 +`define SYMB 4 +`define IMM 5 +`define ABS 6 +`define CONST 7 + +// Instruction state machine +`define I_IRQ_FETCH 3'h0 +`define I_IRQ_DONE 3'h1 +`define I_DEC 3'h2 +`define I_EXT1 3'h3 +`define I_EXT2 3'h4 +`define I_IDLE 3'h5 + +// Execution state machine +// (swapped E_IRQ_0 and E_IRQ_2 values to suppress glitch generation warning from lint tool) +`define E_IRQ_0 4'h2 +`define E_IRQ_1 4'h1 +`define E_IRQ_2 4'h0 +`define E_IRQ_3 4'h3 +`define E_IRQ_4 4'h4 +`define E_SRC_AD 4'h5 +`define E_SRC_RD 4'h6 +`define E_SRC_WR 4'h7 +`define E_DST_AD 4'h8 +`define E_DST_RD 4'h9 +`define E_DST_WR 4'hA +`define E_EXEC 4'hB +`define E_JUMP 4'hC +`define E_IDLE 4'hD + +// ALU control signals +`define ALU_SRC_INV 0 +`define ALU_INC 1 +`define ALU_INC_C 2 +`define ALU_ADD 3 +`define ALU_AND 4 +`define ALU_OR 5 +`define ALU_XOR 6 +`define ALU_DADD 7 +`define ALU_STAT_7 8 +`define ALU_STAT_F 9 +`define ALU_SHIFT 10 +`define EXEC_NO_WR 11 + +// Debug interface +`define DBG_UART_WR 18 +`define DBG_UART_BW 17 +`define DBG_UART_ADDR 16:11 + +// Debug interface CPU_CTL register +`define HALT 0 +`define RUN 1 +`define ISTEP 2 +`define SW_BRK_EN 3 +`define FRZ_BRK_EN 4 +`define RST_BRK_EN 5 +`define CPU_RST 6 + +// Debug interface CPU_STAT register +`define HALT_RUN 0 +`define PUC_PND 1 +`define SWBRK_PND 3 +`define HWBRK0_PND 4 +`define HWBRK1_PND 5 + +// Debug interface BRKx_CTL register +`define BRK_MODE_RD 0 +`define BRK_MODE_WR 1 +`define BRK_MODE 1:0 +`define BRK_EN 2 +`define BRK_I_EN 3 +`define BRK_RANGE 4 + +// Basic clock module: BCSCTL1 Control Register +`define DIVAx 5:4 + +// Basic clock module: BCSCTL2 Control Register +`define SELMx 7 +`define DIVMx 5:4 +`define SELS 3 +`define DIVSx 2:1 + +// MCLK Clock gate +`ifdef CPUOFF_EN + `define MCLK_CGATE +`else +`ifdef MCLK_DIVIDER + `define MCLK_CGATE +`endif +`endif + +// SMCLK Clock gate +`ifdef SCG1_EN + `define SMCLK_CGATE +`else +`ifdef SMCLK_DIVIDER + `define SMCLK_CGATE +`endif +`endif + +// +// DEBUG INTERFACE EXTRA CONFIGURATION +//====================================== + +// Debug interface: CPU version +`define CPU_VERSION 3'h2 + +// Debug interface: Software breakpoint opcode +`define DBG_SWBRK_OP 16'h4343 + +// Debug UART interface auto data synchronization +// If the following define is commented out, then +// the DBG_UART_BAUD and DBG_DCO_FREQ need to be properly +// defined. +`define DBG_UART_AUTO_SYNC + +// Debug UART interface data rate +// In order to properly setup the UART debug interface, you +// need to specify the DCO_CLK frequency (DBG_DCO_FREQ) and +// the chosen BAUD rate from the UART interface. +// +//`define DBG_UART_BAUD 9600 +//`define DBG_UART_BAUD 19200 +//`define DBG_UART_BAUD 38400 +//`define DBG_UART_BAUD 57600 +//`define DBG_UART_BAUD 115200 +//`define DBG_UART_BAUD 230400 +//`define DBG_UART_BAUD 460800 +//`define DBG_UART_BAUD 576000 +//`define DBG_UART_BAUD 921600 +`define DBG_UART_BAUD 2000000 +`define DBG_DCO_FREQ 20000000 +`define DBG_UART_CNT ((`DBG_DCO_FREQ/`DBG_UART_BAUD)-1) + +// Debug interface selection +// `define DBG_UART -> Enable UART (8N1) debug interface +// `define DBG_JTAG -> DON'T UNCOMMENT, NOT SUPPORTED +// +`define DBG_UART +//`define DBG_JTAG + +// Debug interface input synchronizer +`define SYNC_DBG_UART_RXD + +// Enable/Disable the hardware breakpoint RANGE mode +`ifdef DBG_HWBRK_RANGE + `define HWBRK_RANGE 1'b1 +`else + `define HWBRK_RANGE 1'b0 +`endif + +// Counter width for the debug interface UART +`define DBG_UART_XFER_CNT_W 16 + +// Check configuration +`ifdef DBG_EN + `ifdef DBG_UART + `ifdef DBG_JTAG +CONFIGURATION ERROR: JTAG AND UART DEBUG INTERFACE ARE BOTH ENABLED + `endif + `else + `ifdef DBG_JTAG +CONFIGURATION ERROR: JTAG INTERFACE NOT SUPPORTED + `else +CONFIGURATION ERROR: JTAG OR UART DEBUG INTERFACE SHOULD BE ENABLED + `endif + `endif +`endif + +// +// MULTIPLIER CONFIGURATION +//====================================== + +// If uncommented, the following define selects +// the 16x16 multiplier (1 cycle) instead of the +// default 16x8 multplier (2 cycles) +//`define MPY_16x16 + +//====================================== +// CONFIGURATION CHECKS +//====================================== +`ifdef LFXT_DOMAIN +`else + `ifdef MCLK_MUX +CONFIGURATION ERROR: THE MCLK_MUX CAN ONLY BE ENABLED IF THE LFXT_DOMAIN IS ENABLED AS WELL + `endif + `ifdef SMCLK_MUX +CONFIGURATION ERROR: THE SMCLK_MUX CAN ONLY BE ENABLED IF THE LFXT_DOMAIN IS ENABLED AS WELL + `endif + `ifdef WATCHDOG_MUX +CONFIGURATION ERROR: THE WATCHDOG_MUX CAN ONLY BE ENABLED IF THE LFXT_DOMAIN IS ENABLED AS WELL + `else + `ifdef WATCHDOG_NOMUX_ACLK +CONFIGURATION ERROR: THE WATCHDOG_NOMUX_ACLK CAN ONLY BE ENABLED IF THE LFXT_DOMAIN IS ENABLED AS WELL + `endif + `endif + `ifdef OSCOFF_EN +CONFIGURATION ERROR: THE OSCOFF LOW POWER MODE CAN ONLY BE ENABLED IF THE LFXT_DOMAIN IS ENABLED AS WELL + `endif +`endif diff --git a/tests/openmsp430/rtl/openMSP430_undefines.v b/tests/openmsp430/rtl/openMSP430_undefines.v new file mode 100644 index 00000000..a399ae77 --- /dev/null +++ b/tests/openmsp430/rtl/openMSP430_undefines.v @@ -0,0 +1,732 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the authors nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 +// +//---------------------------------------------------------------------------- +// +// *File Name: openMSP430_undefines.v +// +// *Module Description: +// openMSP430 Verilog `undef file +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 23 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2009-08-30 18:39:26 +0200 (Sun, 30 Aug 2009) $ +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +// BASIC SYSTEM CONFIGURATION +//---------------------------------------------------------------------------- + +// Program Memory sizes +`ifdef PMEM_SIZE_59_KB +`undef PMEM_SIZE_59_KB +`endif +`ifdef PMEM_SIZE_55_KB +`undef PMEM_SIZE_55_KB +`endif +`ifdef PMEM_SIZE_54_KB +`undef PMEM_SIZE_54_KB +`endif +`ifdef PMEM_SIZE_51_KB +`undef PMEM_SIZE_51_KB +`endif +`ifdef PMEM_SIZE_48_KB +`undef PMEM_SIZE_48_KB +`endif +`ifdef PMEM_SIZE_41_KB +`undef PMEM_SIZE_41_KB +`endif +`ifdef PMEM_SIZE_32_KB +`undef PMEM_SIZE_32_KB +`endif +`ifdef PMEM_SIZE_24_KB +`undef PMEM_SIZE_24_KB +`endif +`ifdef PMEM_SIZE_16_KB +`undef PMEM_SIZE_16_KB +`endif +`ifdef PMEM_SIZE_12_KB +`undef PMEM_SIZE_12_KB +`endif +`ifdef PMEM_SIZE_8_KB +`undef PMEM_SIZE_8_KB +`endif +`ifdef PMEM_SIZE_4_KB +`undef PMEM_SIZE_4_KB +`endif +`ifdef PMEM_SIZE_2_KB +`undef PMEM_SIZE_2_KB +`endif +`ifdef PMEM_SIZE_1_KB +`undef PMEM_SIZE_1_KB +`endif + +// Data Memory sizes +`ifdef DMEM_SIZE_32_KB +`undef DMEM_SIZE_32_KB +`endif +`ifdef DMEM_SIZE_24_KB +`undef DMEM_SIZE_24_KB +`endif +`ifdef DMEM_SIZE_16_KB +`undef DMEM_SIZE_16_KB +`endif +`ifdef DMEM_SIZE_10_KB +`undef DMEM_SIZE_10_KB +`endif +`ifdef DMEM_SIZE_8_KB +`undef DMEM_SIZE_8_KB +`endif +`ifdef DMEM_SIZE_5_KB +`undef DMEM_SIZE_5_KB +`endif +`ifdef DMEM_SIZE_4_KB +`undef DMEM_SIZE_4_KB +`endif +`ifdef DMEM_SIZE_2p5_KB +`undef DMEM_SIZE_2p5_KB +`endif +`ifdef DMEM_SIZE_2_KB +`undef DMEM_SIZE_2_KB +`endif +`ifdef DMEM_SIZE_1_KB +`undef DMEM_SIZE_1_KB +`endif +`ifdef DMEM_SIZE_512_B +`undef DMEM_SIZE_512_B +`endif +`ifdef DMEM_SIZE_256_B +`undef DMEM_SIZE_256_B +`endif +`ifdef DMEM_SIZE_128_B +`undef DMEM_SIZE_128_B +`endif + +// Include/Exclude Hardware Multiplier +`ifdef MULTIPLIER +`undef MULTIPLIER +`endif + +// Include Debug interface +`ifdef DBG_EN +`undef DBG_EN +`endif + + +//---------------------------------------------------------------------------- +// ADVANCED SYSTEM CONFIGURATION (FOR EXPERIENCED USERS) +//---------------------------------------------------------------------------- + +// Peripheral Memory Space: +`ifdef PER_SIZE_32_KB +`undef PER_SIZE_32_KB +`endif +`ifdef PER_SIZE_16_KB +`undef PER_SIZE_16_KB +`endif +`ifdef PER_SIZE_8_KB +`undef PER_SIZE_8_KB +`endif +`ifdef PER_SIZE_4_KB +`undef PER_SIZE_4_KB +`endif +`ifdef PER_SIZE_2_KB +`undef PER_SIZE_2_KB +`endif +`ifdef PER_SIZE_1_KB +`undef PER_SIZE_1_KB +`endif +`ifdef PER_SIZE_512_B +`undef PER_SIZE_512_B +`endif + +// Let the CPU break after a PUC occurrence by default +`ifdef DBG_RST_BRK_EN +`undef DBG_RST_BRK_EN +`endif + +// Custom user version number +`ifdef USER_VERSION +`undef USER_VERSION +`endif + +// Include/Exclude Watchdog timer +`ifdef WATCHDOG +`undef WATCHDOG +`endif + +// Include/Exclude Non-Maskable-Interrupt support +`ifdef NMI +`undef NMI +`endif + +//---------------------------------------------------------------------------- +// EXPERT SYSTEM CONFIGURATION ( !!!! EXPERTS ONLY !!!! ) +//---------------------------------------------------------------------------- + +// Number of hardware breakpoint units +`ifdef DBG_HWBRK_0 +`undef DBG_HWBRK_0 +`endif +`ifdef DBG_HWBRK_1 +`undef DBG_HWBRK_1 +`endif +`ifdef DBG_HWBRK_2 +`undef DBG_HWBRK_2 +`endif +`ifdef DBG_HWBRK_3 +`undef DBG_HWBRK_3 +`endif + +// Enable/Disable the hardware breakpoint RANGE mode +`ifdef DBG_HWBRK_RANGE +`undef DBG_HWBRK_RANGE +`endif + +// Input synchronizers +`ifdef SYNC_CPU_EN +`undef SYNC_CPU_EN +`endif +`ifdef SYNC_DBG_EN +`undef SYNC_DBG_EN +`endif +`ifdef SYNC_DBG_UART_RXD +`undef SYNC_DBG_UART_RXD +`endif +`ifdef SYNC_NMI +`undef SYNC_NMI +`endif + +// ASIC version +`ifdef ASIC +`undef ASIC +`endif + + +//---------------------------------------------------------------------------- +// ASIC SYSTEM CONFIGURATION ( !!!! EXPERTS ONLY !!!! ) +//---------------------------------------------------------------------------- + +// Fine grained clock gating +`ifdef CLOCK_GATING +`undef CLOCK_GATING +`endif + +// LFXT clock domain +`ifdef LFXT_DOMAIN +`undef LFXT_DOMAIN +`endif + +// MCLK: Clock Mux +`ifdef MCLK_MUX +`undef MCLK_MUX +`endif + +// SMCLK: Clock Mux +`ifdef SMCLK_MUX +`undef SMCLK_MUX +`endif + +// WATCHDOG: Clock Mux +`ifdef WATCHDOG_MUX +`undef WATCHDOG_MUX +`endif + +// MCLK: Clock divider +`ifdef MCLK_DIVIDER +`undef MCLK_DIVIDER +`endif + +// SMCLK: Clock divider (/1/2/4/8) +`ifdef SMCLK_DIVIDER +`undef SMCLK_DIVIDER +`endif + +// ACLK: Clock divider (/1/2/4/8) +`ifdef ACLK_DIVIDER +`undef ACLK_DIVIDER +`endif + +// LOW POWER MODE: CPUOFF +`ifdef CPUOFF_EN +`undef CPUOFF_EN +`endif + +// LOW POWER MODE: OSCOFF +`ifdef OSCOFF_EN +`undef OSCOFF_EN +`endif + +// LOW POWER MODE: SCG0 +`ifdef SCG0_EN +`undef SCG0_EN +`endif + +// LOW POWER MODE: SCG1 +`ifdef SCG1_EN +`undef SCG1_EN +`endif + + +//==========================================================================// +//==========================================================================// +//==========================================================================// +//==========================================================================// +//===== SYSTEM CONSTANTS --- !!!!!!!! DO NOT EDIT !!!!!!!! =====// +//==========================================================================// +//==========================================================================// +//==========================================================================// +//==========================================================================// + +// Program Memory Size +`ifdef PMEM_AWIDTH +`undef PMEM_AWIDTH +`endif +`ifdef PMEM_SIZE +`undef PMEM_SIZE +`endif + +// Data Memory Size +`ifdef DMEM_AWIDTH +`undef DMEM_AWIDTH +`endif +`ifdef DMEM_SIZE +`undef DMEM_SIZE +`endif + +// Peripheral Memory Size +`ifdef PER_AWIDTH +`undef PER_AWIDTH +`endif +`ifdef PER_SIZE +`undef PER_SIZE +`endif + +// Data Memory Base Adresses +`ifdef DMEM_BASE +`undef DMEM_BASE +`endif + +// Program & Data Memory most significant address bit (for 16 bit words) +`ifdef PMEM_MSB +`undef PMEM_MSB +`endif +`ifdef DMEM_MSB +`undef DMEM_MSB +`endif +`ifdef PER_MSB +`undef PER_MSB +`endif + +// Instructions type +`ifdef INST_SO +`undef INST_SO +`endif +`ifdef INST_JMP +`undef INST_JMP +`endif +`ifdef INST_TO +`undef INST_TO +`endif + +// Single-operand arithmetic +`ifdef RRC +`undef RRC +`endif +`ifdef SWPB +`undef SWPB +`endif +`ifdef RRA +`undef RRA +`endif +`ifdef SXT +`undef SXT +`endif +`ifdef PUSH +`undef PUSH +`endif +`ifdef CALL +`undef CALL +`endif +`ifdef RETI +`undef RETI +`endif +`ifdef IRQ +`undef IRQ +`endif + +// Conditional jump +`ifdef JNE +`undef JNE +`endif +`ifdef JEQ +`undef JEQ +`endif +`ifdef JNC +`undef JNC +`endif +`ifdef JC +`undef JC +`endif +`ifdef JN +`undef JN +`endif +`ifdef JGE +`undef JGE +`endif +`ifdef JL +`undef JL +`endif +`ifdef JMP +`undef JMP +`endif + +// Two-operand arithmetic +`ifdef MOV +`undef MOV +`endif +`ifdef ADD +`undef ADD +`endif +`ifdef ADDC +`undef ADDC +`endif +`ifdef SUBC +`undef SUBC +`endif +`ifdef SUB +`undef SUB +`endif +`ifdef CMP +`undef CMP +`endif +`ifdef DADD +`undef DADD +`endif +`ifdef BIT +`undef BIT +`endif +`ifdef BIC +`undef BIC +`endif +`ifdef BIS +`undef BIS +`endif +`ifdef XOR +`undef XOR +`endif +`ifdef AND +`undef AND +`endif + +// Addressing modes +`ifdef DIR +`undef DIR +`endif +`ifdef IDX +`undef IDX +`endif +`ifdef INDIR +`undef INDIR +`endif +`ifdef INDIR_I +`undef INDIR_I +`endif +`ifdef SYMB +`undef SYMB +`endif +`ifdef IMM +`undef IMM +`endif +`ifdef ABS +`undef ABS +`endif +`ifdef CONST +`undef CONST +`endif + +// Instruction state machine +`ifdef I_IRQ_FETCH +`undef I_IRQ_FETCH +`endif +`ifdef I_IRQ_DONE +`undef I_IRQ_DONE +`endif +`ifdef I_DEC +`undef I_DEC +`endif +`ifdef I_EXT1 +`undef I_EXT1 +`endif +`ifdef I_EXT2 +`undef I_EXT2 +`endif +`ifdef I_IDLE +`undef I_IDLE +`endif + +// Execution state machine +`ifdef E_IRQ_0 +`undef E_IRQ_0 +`endif +`ifdef E_IRQ_1 +`undef E_IRQ_1 +`endif +`ifdef E_IRQ_2 +`undef E_IRQ_2 +`endif +`ifdef E_IRQ_3 +`undef E_IRQ_3 +`endif +`ifdef E_IRQ_4 +`undef E_IRQ_4 +`endif +`ifdef E_SRC_AD +`undef E_SRC_AD +`endif +`ifdef E_SRC_RD +`undef E_SRC_RD +`endif +`ifdef E_SRC_WR +`undef E_SRC_WR +`endif +`ifdef E_DST_AD +`undef E_DST_AD +`endif +`ifdef E_DST_RD +`undef E_DST_RD +`endif +`ifdef E_DST_WR +`undef E_DST_WR +`endif +`ifdef E_EXEC +`undef E_EXEC +`endif +`ifdef E_JUMP +`undef E_JUMP +`endif +`ifdef E_IDLE +`undef E_IDLE +`endif + +// ALU control signals +`ifdef ALU_SRC_INV +`undef ALU_SRC_INV +`endif +`ifdef ALU_INC +`undef ALU_INC +`endif +`ifdef ALU_INC_C +`undef ALU_INC_C +`endif +`ifdef ALU_ADD +`undef ALU_ADD +`endif +`ifdef ALU_AND +`undef ALU_AND +`endif +`ifdef ALU_OR +`undef ALU_OR +`endif +`ifdef ALU_XOR +`undef ALU_XOR +`endif +`ifdef ALU_DADD +`undef ALU_DADD +`endif +`ifdef ALU_STAT_7 +`undef ALU_STAT_7 +`endif +`ifdef ALU_STAT_F +`undef ALU_STAT_F +`endif +`ifdef ALU_SHIFT +`undef ALU_SHIFT +`endif +`ifdef EXEC_NO_WR +`undef EXEC_NO_WR +`endif + +// Debug interface +`ifdef DBG_UART_WR +`undef DBG_UART_WR +`endif +`ifdef DBG_UART_BW +`undef DBG_UART_BW +`endif +`ifdef DBG_UART_ADDR +`undef DBG_UART_ADDR +`endif + +// Debug interface CPU_CTL register +`ifdef HALT +`undef HALT +`endif +`ifdef RUN +`undef RUN +`endif +`ifdef ISTEP +`undef ISTEP +`endif +`ifdef SW_BRK_EN +`undef SW_BRK_EN +`endif +`ifdef FRZ_BRK_EN +`undef FRZ_BRK_EN +`endif +`ifdef RST_BRK_EN +`undef RST_BRK_EN +`endif +`ifdef CPU_RST +`undef CPU_RST +`endif + +// Debug interface CPU_STAT register +`ifdef HALT_RUN +`undef HALT_RUN +`endif +`ifdef PUC_PND +`undef PUC_PND +`endif +`ifdef SWBRK_PND +`undef SWBRK_PND +`endif +`ifdef HWBRK0_PND +`undef HWBRK0_PND +`endif +`ifdef HWBRK1_PND +`undef HWBRK1_PND +`endif + +// Debug interface BRKx_CTL register +`ifdef BRK_MODE_RD +`undef BRK_MODE_RD +`endif +`ifdef BRK_MODE_WR +`undef BRK_MODE_WR +`endif +`ifdef BRK_MODE +`undef BRK_MODE +`endif +`ifdef BRK_EN +`undef BRK_EN +`endif +`ifdef BRK_I_EN +`undef BRK_I_EN +`endif +`ifdef BRK_RANGE +`undef BRK_RANGE +`endif + +// Basic clock module: BCSCTL1 Control Register +`ifdef DIVAx +`undef DIVAx +`endif + +// Basic clock module: BCSCTL2 Control Register +`ifdef SELMx +`undef SELMx +`endif +`ifdef DIVMx +`undef DIVMx +`endif +`ifdef SELS +`undef SELS +`endif +`ifdef DIVSx +`undef DIVSx +`endif + +// MCLK Clock gate +`ifdef MCLK_CGATE +`undef MCLK_CGATE +`endif + +// SMCLK Clock gate +`ifdef SMCLK_CGATE +`undef SMCLK_CGATE +`endif + +// +// DEBUG INTERFACE EXTRA CONFIGURATION +//====================================== + +// Debug interface: CPU version +`ifdef CPU_VERSION +`undef CPU_VERSION +`endif + +// Debug interface: Software breakpoint opcode +`ifdef DBG_SWBRK_OP +`undef DBG_SWBRK_OP +`endif + +// Debug UART interface auto data synchronization +`ifdef DBG_UART_AUTO_SYNC +`undef DBG_UART_AUTO_SYNC +`endif + +// Debug UART interface data rate +`ifdef DBG_UART_BAUD +`undef DBG_UART_BAUD +`endif +`ifdef DBG_DCO_FREQ +`undef DBG_DCO_FREQ +`endif +`ifdef DBG_UART_CNT +`undef DBG_UART_CNT +`endif + +// Debug interface selection +`ifdef DBG_UART +`undef DBG_UART +`endif +`ifdef DBG_JTAG +`undef DBG_JTAG +`endif + +// Enable/Disable the hardware breakpoint RANGE mode +`ifdef HWBRK_RANGE +`undef HWBRK_RANGE +`endif + +// Counter width for the debug interface UART +`ifdef DBG_UART_XFER_CNT_W +`undef DBG_UART_XFER_CNT_W +`endif + +// +// MULTIPLIER CONFIGURATION +//====================================== + +`ifdef MPY_16x16 +`undef MPY_16x16 +`endif diff --git a/tests/openmsp430/run-fm.do b/tests/openmsp430/run-fm.do new file mode 100644 index 00000000..766d974c --- /dev/null +++ b/tests/openmsp430/run-fm.do @@ -0,0 +1,37 @@ + +set hdlin_ignore_full_case false +set hdlin_ignore_parallel_case false +set svf_ignore_unqualified_fsm_information true +set hdlin_warn_on_mismatch_message "FMR_ELAB-115 FMR_VLOG-079 FMR_VLOG-091" + +read_verilog -container r -libname WORK -01 rtl/omsp_alu.v +read_verilog -container r -libname WORK -01 rtl/omsp_and_gate.v +read_verilog -container r -libname WORK -01 rtl/omsp_clock_gate.v +read_verilog -container r -libname WORK -01 rtl/omsp_clock_module.v +read_verilog -container r -libname WORK -01 rtl/omsp_clock_mux.v +read_verilog -container r -libname WORK -01 rtl/omsp_dbg_hwbrk.v +read_verilog -container r -libname WORK -01 rtl/omsp_dbg_uart.v +read_verilog -container r -libname WORK -01 rtl/omsp_dbg.v +read_verilog -container r -libname WORK -01 rtl/omsp_execution_unit.v +read_verilog -container r -libname WORK -01 rtl/omsp_frontend.v +read_verilog -container r -libname WORK -01 rtl/omsp_mem_backbone.v +read_verilog -container r -libname WORK -01 rtl/omsp_multiplier.v +read_verilog -container r -libname WORK -01 rtl/omsp_register_file.v +read_verilog -container r -libname WORK -01 rtl/omsp_scan_mux.v +read_verilog -container r -libname WORK -01 rtl/omsp_sfr.v +read_verilog -container r -libname WORK -01 rtl/omsp_sync_cell.v +read_verilog -container r -libname WORK -01 rtl/omsp_sync_reset.v +read_verilog -container r -libname WORK -01 rtl/omsp_wakeup_cell.v +read_verilog -container r -libname WORK -01 rtl/omsp_watchdog.v +read_verilog -container r -libname WORK -01 rtl/openMSP430.v +set_top r:/WORK/openMSP430 + +read_verilog -container i -libname WORK -01 synth.v +read_verilog -container i -technology_library -libname TECH_WORK -01 ../../techlibs/stdcells_sim.v +read_verilog -container i -technology_library -libname TECH_WORK -01 sim_mul.v +set_top i:/WORK/openMSP430 + +source fsm_info.txt + +if ![verify] start_gui exit + diff --git a/tests/openmsp430/run-fm.sh b/tests/openmsp430/run-fm.sh new file mode 100644 index 00000000..5fd1c6cf --- /dev/null +++ b/tests/openmsp430/run-fm.sh @@ -0,0 +1,5 @@ +#!/bin/bash +if [ -n "$REMOTE_YOSYS_ROOT" ]; then + rsync --exclude=".svn" --exclude="*.log" -rv -e "${REMOTE_YOSYS_SSH:-ssh} -C" "$REMOTE_YOSYS_ROOT"/tests/openmsp430/. . +fi +fm_shell -64 -file run-fm.do 2>&1 | tee run-fm.log diff --git a/tests/openmsp430/run-synth.sh b/tests/openmsp430/run-synth.sh new file mode 100644 index 00000000..e4d6bc72 --- /dev/null +++ b/tests/openmsp430/run-synth.sh @@ -0,0 +1,3 @@ +#!/bin/bash +time ../../yosys -b "verilog -noexpr" -o synth.v -tl synth.log -s run-synth.ys \ + rtl/omsp_*.v rtl/openMSP430.v 2>&1 | egrep '^\[[0-9.]+\] (ERROR|-- |[0-9]+\.)' diff --git a/tests/openmsp430/run-synth.ys b/tests/openmsp430/run-synth.ys new file mode 100644 index 00000000..af39147f --- /dev/null +++ b/tests/openmsp430/run-synth.ys @@ -0,0 +1,11 @@ +hierarchy -check -top openMSP430 +proc +opt +memory +opt +fsm -fm_set_fsm_file fsm_info.txt +opt +techmap +opt +abc +opt diff --git a/tests/openmsp430/sim_mul.v b/tests/openmsp430/sim_mul.v new file mode 100644 index 00000000..8762bb25 --- /dev/null +++ b/tests/openmsp430/sim_mul.v @@ -0,0 +1,29 @@ + +module \$mul (A, B, Y); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 0; +parameter B_WIDTH = 0; +parameter Y_WIDTH = 0; + +input [A_WIDTH-1:0] A; +generate if (A_SIGNED) begin:A_BUF + wire signed [A_WIDTH-1:0] val = A; +end else begin:A_BUF + wire [A_WIDTH-1:0] val = A; +end endgenerate + +input [B_WIDTH-1:0] B; +generate if (B_SIGNED) begin:B_BUF + wire signed [B_WIDTH-1:0] val = B; +end else begin:B_BUF + wire [B_WIDTH-1:0] val = B; +end endgenerate + +output [Y_WIDTH-1:0] Y; + +assign Y = A_BUF.val * B_BUF.val; + +endmodule + diff --git a/tests/or1200/config.patch b/tests/or1200/config.patch new file mode 100644 index 00000000..7826edeb --- /dev/null +++ b/tests/or1200/config.patch @@ -0,0 +1,46 @@ +Index: or1200_defines.v +=================================================================== +--- or1200_defines.v (revision 812) ++++ or1200_defines.v (working copy) +@@ -56,7 +56,7 @@ + // + //`define OR1200_VERBOSE + +-// `define OR1200_ASIC ++`define OR1200_ASIC + //////////////////////////////////////////////////////// + // + // Typical configuration for an ASIC +@@ -69,7 +69,7 @@ + //`define OR1200_ARTISAN_SSP + //`define OR1200_ARTISAN_SDP + //`define OR1200_ARTISAN_STP +-`define OR1200_VIRTUALSILICON_SSP ++//`define OR1200_VIRTUALSILICON_SSP + //`define OR1200_VIRTUALSILICON_STP_T1 + //`define OR1200_VIRTUALSILICON_STP_T2 + +@@ -96,17 +96,17 @@ + // + // Select between ASIC optimized and generic multiplier + // +-//`define OR1200_ASIC_MULTP2_32X32 +-`define OR1200_GENERIC_MULTP2_32X32 ++`define OR1200_ASIC_MULTP2_32X32 ++//`define OR1200_GENERIC_MULTP2_32X32 + + // + // Size/type of insn/data cache if implemented + // +-// `define OR1200_IC_1W_512B ++`define OR1200_IC_1W_512B + // `define OR1200_IC_1W_4KB +-`define OR1200_IC_1W_8KB +-// `define OR1200_DC_1W_4KB +-`define OR1200_DC_1W_8KB ++// `define OR1200_IC_1W_8KB ++`define OR1200_DC_1W_4KB ++// `define OR1200_DC_1W_8KB + + `else + diff --git a/tests/or1200/run-checkout.sh b/tests/or1200/run-checkout.sh new file mode 100644 index 00000000..c9d4a102 --- /dev/null +++ b/tests/or1200/run-checkout.sh @@ -0,0 +1,4 @@ +#!/bin/bash +rm -rf rtl +svn co http://opencores.org/ocsvn/openrisc/openrisc/trunk/or1200/rtl/verilog rtl +( cd rtl; patch -p0 < ../config.patch; ) diff --git a/tests/or1200/run-fm-mods.sh b/tests/or1200/run-fm-mods.sh new file mode 100644 index 00000000..6b848773 --- /dev/null +++ b/tests/or1200/run-fm-mods.sh @@ -0,0 +1,24 @@ +#!/bin/bash +if [ -n "$REMOTE_YOSYS_ROOT" ]; then + rsync --exclude=".svn" --exclude="*.log" -rv -e "${REMOTE_YOSYS_SSH:-ssh} -C" "$REMOTE_YOSYS_ROOT"/tests/or1200/. . +fi +for mod in $( grep '^module or1200_' synth.v | awk -F '[ (]' '{ print $2; }'; ) +do + { + grep '^set ' run-fm.do + grep '^read_verilog -container r ' run-fm.do + echo "set_top r:/WORK/$mod" + grep '^read_verilog -container i ' run-fm.do + echo "set_top i:/WORK/$mod" + echo "verify" + echo "exit" + } > run-fm-${mod}.do + fm_shell -64 -file run-fm-${mod}.do 2>&1 | tee run-fm-${mod}.log + rsync -v -e "${REMOTE_YOSYS_SSH:-ssh}" run-fm-${mod}.log "$REMOTE_YOSYS_ROOT"/tests/or1200/ +done + +echo; echo +for x in run-fm-*.log; do + echo -e "${x%/*}\\t$( egrep '^Verification (SUCCEEDED|FAILED)' $x; )" +done | expand -t20 +echo; echo diff --git a/tests/or1200/run-fm.do b/tests/or1200/run-fm.do new file mode 100644 index 00000000..ed5c7228 --- /dev/null +++ b/tests/or1200/run-fm.do @@ -0,0 +1,53 @@ + +set hdlin_ignore_full_case false +set hdlin_warn_on_mismatch_message "FMR_ELAB-115 FMR_VLOG-079 FMR_VLOG-091" + +read_verilog -container r -libname WORK -01 rtl/or1200_alu.v +read_verilog -container r -libname WORK -01 rtl/or1200_amultp2_32x32.v +read_verilog -container r -libname WORK -01 rtl/or1200_cfgr.v +read_verilog -container r -libname WORK -01 rtl/or1200_cpu.v +read_verilog -container r -libname WORK -01 rtl/or1200_ctrl.v +read_verilog -container r -libname WORK -01 rtl/or1200_dc_fsm.v +read_verilog -container r -libname WORK -01 rtl/or1200_dc_ram.v +read_verilog -container r -libname WORK -01 rtl/or1200_dc_tag.v +read_verilog -container r -libname WORK -01 rtl/or1200_dc_top.v +read_verilog -container r -libname WORK -01 rtl/or1200_dmmu_tlb.v +read_verilog -container r -libname WORK -01 rtl/or1200_dmmu_top.v +read_verilog -container r -libname WORK -01 rtl/or1200_dpram.v +read_verilog -container r -libname WORK -01 rtl/or1200_du.v +read_verilog -container r -libname WORK -01 rtl/or1200_except.v +read_verilog -container r -libname WORK -01 rtl/or1200_fpu.v +read_verilog -container r -libname WORK -01 rtl/or1200_freeze.v +read_verilog -container r -libname WORK -01 rtl/or1200_genpc.v +read_verilog -container r -libname WORK -01 rtl/or1200_ic_fsm.v +read_verilog -container r -libname WORK -01 rtl/or1200_ic_ram.v +read_verilog -container r -libname WORK -01 rtl/or1200_ic_tag.v +read_verilog -container r -libname WORK -01 rtl/or1200_ic_top.v +read_verilog -container r -libname WORK -01 rtl/or1200_if.v +read_verilog -container r -libname WORK -01 rtl/or1200_immu_tlb.v +read_verilog -container r -libname WORK -01 rtl/or1200_immu_top.v +read_verilog -container r -libname WORK -01 rtl/or1200_lsu.v +read_verilog -container r -libname WORK -01 rtl/or1200_mem2reg.v +read_verilog -container r -libname WORK -01 rtl/or1200_mult_mac.v +read_verilog -container r -libname WORK -01 rtl/or1200_operandmuxes.v +read_verilog -container r -libname WORK -01 rtl/or1200_pic.v +read_verilog -container r -libname WORK -01 rtl/or1200_pm.v +read_verilog -container r -libname WORK -01 rtl/or1200_qmem_top.v +read_verilog -container r -libname WORK -01 rtl/or1200_reg2mem.v +read_verilog -container r -libname WORK -01 rtl/or1200_rf.v +read_verilog -container r -libname WORK -01 rtl/or1200_sb.v +read_verilog -container r -libname WORK -01 rtl/or1200_spram_32_bw.v +read_verilog -container r -libname WORK -01 rtl/or1200_spram.v +read_verilog -container r -libname WORK -01 rtl/or1200_sprs.v +read_verilog -container r -libname WORK -01 rtl/or1200_top.v +read_verilog -container r -libname WORK -01 rtl/or1200_tt.v +read_verilog -container r -libname WORK -01 rtl/or1200_wb_biu.v +read_verilog -container r -libname WORK -01 rtl/or1200_wbmux.v +set_top r:/WORK/or1200_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/or1200_top + +if ![verify] start_gui exit + diff --git a/tests/or1200/run-fm.sh b/tests/or1200/run-fm.sh new file mode 100644 index 00000000..3023809c --- /dev/null +++ b/tests/or1200/run-fm.sh @@ -0,0 +1,5 @@ +#!/bin/bash +if [ -n "$REMOTE_YOSYS_ROOT" ]; then + rsync --exclude=".svn" --exclude="*.log" -rv -e "${REMOTE_YOSYS_SSH:-ssh} -C" "$REMOTE_YOSYS_ROOT"/tests/or1200/. . +fi +fm_shell -64 -file run-fm.do 2>&1 | tee run-fm.log diff --git a/tests/or1200/run-synth.sh b/tests/or1200/run-synth.sh new file mode 100644 index 00000000..9f7e43fd --- /dev/null +++ b/tests/or1200/run-synth.sh @@ -0,0 +1,2 @@ +#!/bin/bash +time ../../yosys -b "verilog -noexpr" -o synth.v -tl synth.log -s run-synth.ys rtl/or1200_*.v 2>&1 | egrep '^\[[0-9.]+\] (ERROR|--|[0-9]+\.)' diff --git a/tests/or1200/run-synth.ys b/tests/or1200/run-synth.ys new file mode 100644 index 00000000..1f0d8a82 --- /dev/null +++ b/tests/or1200/run-synth.ys @@ -0,0 +1,11 @@ +hierarchy -check -top or1200_top +proc +opt +memory +opt +# fsm -norecode +# opt +techmap +opt +abc +opt diff --git a/tests/or1200/run-vg.sh b/tests/or1200/run-vg.sh new file mode 100644 index 00000000..54147cf5 --- /dev/null +++ b/tests/or1200/run-vg.sh @@ -0,0 +1,4 @@ +#!/bin/bash +time valgrind --leak-check=full --show-reachable=yes --log-file=valgrind.log \ + ../../yosys -o synth.v -tl synth.log -p "hierarchy -check -top or1200_top" \ + -p opt_const -p proc -p memory -p opt -p techmap -p opt -p abc -p opt rtl/or1200_*.v diff --git a/tests/simple/aes_kexp128.v b/tests/simple/aes_kexp128.v new file mode 100644 index 00000000..3ee03478 --- /dev/null +++ b/tests/simple/aes_kexp128.v @@ -0,0 +1,24 @@ + +// test taken from aes_core from iwls2005 + +module aes_key_expand_128(clk, kld, key, wo_0, wo_1, wo_2, wo_3); + +input clk, kld; +input [15:0] key; +output [3:0] wo_0, wo_1, wo_2, wo_3; +reg [3:0] w[3:0]; + +assign wo_0 = w[0]; +assign wo_1 = w[1]; +assign wo_2 = w[2]; +assign wo_3 = w[3]; + +always @(posedge clk) begin + w[0] <= kld ? key[15:12] : w[0]; + w[1] <= kld ? key[11: 8] : w[0]^w[1]; + w[2] <= kld ? key[ 7: 4] : w[0]^w[1]^w[2]; + w[3] <= kld ? key[ 3: 0] : w[0]^w[1]^w[2]^w[3]; +end + +endmodule + diff --git a/tests/simple/dff_different_styles.v b/tests/simple/dff_different_styles.v new file mode 100644 index 00000000..23d89b5d --- /dev/null +++ b/tests/simple/dff_different_styles.v @@ -0,0 +1,52 @@ + +module dff(clk, d, q); +input clk, d; +output reg q; +always @(posedge clk) + q <= d; +endmodule + +module dffa(clk, arst, d, q); +input clk, arst, d; +output reg q; +always @(posedge clk or posedge arst) begin + if (arst) + q <= 1; + else + q <= d; +end +endmodule + +module dffa1(clk, arst, d, q); +input clk, arst, d; +output reg q; +always @(posedge clk or negedge arst) begin + if (~arst) + q <= 0; + else + q <= d; +end +endmodule + +module dffa2(clk, arst, d, q); +input clk, arst, d; +output reg q; +always @(posedge clk or negedge arst) begin + if (!arst) + q <= 0; + else + q <= d; +end +endmodule + +module dffa3(clk, arst, d, q); +input clk, arst, d; +output reg q; +always @(posedge clk or negedge arst) begin + if (~(!arst)) + q <= d; + else + q <= 1; +end +endmodule + diff --git a/tests/simple/fiedler-cooley.v b/tests/simple/fiedler-cooley.v new file mode 100644 index 00000000..96861973 --- /dev/null +++ b/tests/simple/fiedler-cooley.v @@ -0,0 +1,33 @@ +// borrowed with some modifications from +// http://www.ee.ed.ac.uk/~gerard/Teach/Verilog/manual/Example/lrgeEx2/cooley.html +module up3down5(clock, data_in, up, down, carry_out, borrow_out, count_out, parity_out); + +input [8:0] data_in; +input clock, up, down; + +output reg [8:0] count_out; +output reg carry_out, borrow_out, parity_out; + +reg [9:0] cnt_up, cnt_dn; +reg [8:0] count_nxt; + +always @(posedge clock) +begin + cnt_dn = count_out - 3'b 101; + cnt_up = count_out + 2'b 11; + + case ({up,down}) + 2'b 00 : count_nxt = data_in; + 2'b 01 : count_nxt = cnt_dn; + 2'b 10 : count_nxt = cnt_up; + 2'b 11 : count_nxt = count_out; + default : count_nxt = 9'bX; + endcase + + parity_out <= ^count_nxt; + carry_out <= up & cnt_up[9]; + borrow_out <= down & cnt_dn[9]; + count_out <= count_nxt; +end + +endmodule diff --git a/tests/simple/fsm.v b/tests/simple/fsm.v new file mode 100644 index 00000000..79ca041d --- /dev/null +++ b/tests/simple/fsm.v @@ -0,0 +1,69 @@ + +// `define ASYNC_RESET + +module test(clk, reset, button_a, button_b, red_a, green_a, red_b, green_b); + +input clk, reset, button_a, button_b; +output reg red_a, green_a, red_b, green_b; + +(* gentb_constant = 0 *) +wire reset; + +integer state; +reg [3:0] cnt; + +`ifdef ASYNC_RESET +always @(posedge clk, posedge reset) +`else +always @(posedge clk) +`endif +begin + cnt <= 0; + red_a <= 1; + red_b <= 1; + green_a <= 0; + green_b <= 0; + + if (reset) + state <= 100; + else + case (state) + 100: begin + if (button_a && !button_b) + state <= 200; + if (!button_a && button_b) + state <= 300; + end + 200: begin + red_a <= 0; + green_a <= 1; + cnt <= cnt + 1; + if (cnt == 5) + state <= 210; + end + 210: begin + red_a <= 0; + green_a <= cnt[0]; + cnt <= cnt + 1; + if (cnt == 10) + state <= 100; + end + 300: begin + red_b <= 0; + green_b <= 1; + cnt <= cnt + 1; + if (cnt == 5) + state <= 310; + end + 310: begin + red_b <= 0; + green_b <= cnt[0]; + cnt <= cnt + 1; + if (cnt == 10) + state <= 100; + end + endcase +end + +endmodule + diff --git a/tests/simple/generate.v b/tests/simple/generate.v new file mode 100644 index 00000000..d458c076 --- /dev/null +++ b/tests/simple/generate.v @@ -0,0 +1,67 @@ + +module test1(clk, a, b, y); + +input clk; +input [7:0] a, b; +output reg [7:0] y; + +genvar i, j; +wire [15:0] tmp1; + +generate + + for (i = 0; i < 8; i = i + 1) begin:gen1 + wire and_wire, or_wire; + assign and_wire = a[i] & b[i]; + assign or_wire = a[i] | b[i]; + if (i % 2 == 0) begin:gen2true + assign tmp1[i] = and_wire; + assign tmp1[i+8] = or_wire; + end else begin:gen2false + assign tmp1[i] = or_wire; + assign tmp1[i+8] = and_wire; + end + end + + for (i = 0; i < 8; i = i + 1) begin:gen3 + wire [4:0] tmp2; + for (j = 0; j <= 4; j = j + 1) begin:gen4 + wire tmpbuf; + assign tmpbuf = tmp1[i+2*j]; + assign tmp2[j] = tmpbuf; + end + always @(posedge clk) + y[i] <= ^tmp2; + end + +endgenerate + +endmodule + +// ------------------------------------------ + +module test2(clk, a, b, y); + +input clk; +input [7:0] a, b; +output reg [8:0] y; + +integer i; +reg [8:0] carry; + +always @(posedge clk) begin + carry[0] = 0; + for (i = 0; i < 8; i = i + 1) begin + casez ({a[i], b[i], carry[i]}) + 3'b?11, 3'b1?1, 3'b11?: + carry[i+1] = 1; + default: + carry[i+1] = 0; + endcase + y[i] = a[i] ^ b[i] ^ carry[i]; + end + y[8] = carry[8]; +end + +endmodule + diff --git a/tests/simple/i2c_master_tests.v b/tests/simple/i2c_master_tests.v new file mode 100644 index 00000000..f8f56408 --- /dev/null +++ b/tests/simple/i2c_master_tests.v @@ -0,0 +1,62 @@ +// one of my early test cases was the OpenCores I2C master +// This is a collection of stripped down code snippets from +// this core that triggered bugs in early versions of yosys. + +// from i2c_master_bit_ctrl +module test01(clk, rst, nReset, al); + + input clk, rst, nReset; + output reg al; + + reg cmd_stop; + always @(posedge clk or negedge nReset) + if (~nReset) + cmd_stop <= #1 1'b0; + else if (rst) + cmd_stop <= #1 1'b0; + + always @(posedge clk or negedge nReset) + if (~nReset) + al <= #1 1'b0; + else if (rst) + al <= #1 1'b0; + else + al <= #1 ~cmd_stop; + +endmodule + +// from i2c_master_bit_ctrl +module test02(clk, slave_wait, clk_cnt, cmd, cmd_stop, cnt); + + input clk, slave_wait, clk_cnt; + input cmd; + + output reg cmd_stop; + + reg clk_en; + output reg [15:0] cnt; + + always @(posedge clk) + if (~|cnt) + 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 + + always @(posedge clk) + if (clk_en) + cmd_stop <= #1 cmd; + +endmodule + diff --git a/tests/simple/loops.v b/tests/simple/loops.v new file mode 100644 index 00000000..77cdcd8e --- /dev/null +++ b/tests/simple/loops.v @@ -0,0 +1,79 @@ + +// a simple test case extracted from systemcaes (as included in iwls2005) +// this design has latches (or logic loops) for the two temp variables. +// this latches (or logic loops) must be removed in the final synthesis results + +module aes( + // inputs + input [3:0] addroundkey_data_i, + input [3:0] addroundkey_data_reg, + input [3:0] addroundkey_round, + input [3:0] key_i, + input [3:0] keysched_new_key_o, + input [3:0] round, + input addroundkey_start_i, + input keysched_ready_o, + + // outputs + output reg [3:0] keysched_last_key_i, + output reg [3:0] keysched_round_i, + output reg [3:0] next_addroundkey_data_reg, + output reg [3:0] next_addroundkey_round, + output reg [3:0] round_data_var, + output reg keysched_start_i, + output reg next_addroundkey_ready_o +); + +// temp variables +reg [3:0] data_var; +reg [3:0] round_key_var; + +always @* +begin + keysched_start_i = 0; + keysched_round_i = addroundkey_round; + round_data_var = addroundkey_data_reg; + next_addroundkey_data_reg = addroundkey_data_reg; + next_addroundkey_ready_o = 0; + next_addroundkey_round = addroundkey_round; + + if (addroundkey_round == 1 || addroundkey_round == 0) + keysched_last_key_i = key_i; + else + keysched_last_key_i = keysched_new_key_o; + + if (round == 0 && addroundkey_start_i) + begin + 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 + +endmodule + diff --git a/tests/simple/mem2reg.v b/tests/simple/mem2reg.v new file mode 100644 index 00000000..7be32b0b --- /dev/null +++ b/tests/simple/mem2reg.v @@ -0,0 +1,17 @@ +module test1(in_addr, in_data, out_addr, out_data); + +input [1:0] in_addr, out_addr; +input [3:0] in_data; +output reg [3:0] out_data; + +reg [3:0] array [2:0]; + +always @* begin + array[0] = 0; + array[1] = 23; + array[2] = 42; + array[in_addr] = in_data; + out_data = array[out_addr]; +end + +endmodule diff --git a/tests/simple/memory.v b/tests/simple/memory.v new file mode 100644 index 00000000..c25bcd92 --- /dev/null +++ b/tests/simple/memory.v @@ -0,0 +1,19 @@ + +module test01(clk, wr_en, wr_addr, wr_value, rd_addr, rd_value); + +input clk, wr_en; +input [3:0] wr_addr, rd_addr; +input [7:0] wr_value; +output reg [7:0] rd_value; + +reg [7:0] data [15:0]; + +always @(posedge clk) + if (wr_en) + data[wr_addr] <= wr_value; + +always @(posedge clk) + rd_value <= data[rd_addr]; + +endmodule + diff --git a/tests/simple/muxtree.v b/tests/simple/muxtree.v new file mode 100644 index 00000000..6996206c --- /dev/null +++ b/tests/simple/muxtree.v @@ -0,0 +1,50 @@ + +// test case generated from IWLS 2005 usb_phy core +// (triggered a bug in opt_muxtree pass) + +module usb_tx_phy(clk, rst, DataOut_i, TxValid_i, hold_reg); + +input clk; +input rst; +input DataOut_i; +input TxValid_i; +output reg hold_reg; + +reg state, next_state; +reg ld_sop_d; +reg ld_data_d; + +always @(posedge clk) + if(ld_sop_d) + hold_reg <= 0; + else + hold_reg <= DataOut_i; + +always @(posedge clk) + if(!rst) state <= 0; + else state <= next_state; + +always @(state or TxValid_i) + begin + next_state = state; + + ld_sop_d = 1'b0; + ld_data_d = 1'b0; + + case(state) // synopsys full_case parallel_case + 0: + if(TxValid_i) + begin + ld_sop_d = 1'b1; + next_state = 1; + end + 1: + if(TxValid_i) + begin + ld_data_d = 1'b1; + next_state = 0; + end + endcase + end + +endmodule diff --git a/tests/simple/omsp_dbg_uart.v b/tests/simple/omsp_dbg_uart.v new file mode 100644 index 00000000..dc8860de --- /dev/null +++ b/tests/simple/omsp_dbg_uart.v @@ -0,0 +1,34 @@ + +module omsp_dbg_uart (dbg_clk, dbg_rst, mem_burst, cmd_valid); + +input dbg_clk; +input dbg_rst; +input mem_burst; +output cmd_valid; + +reg [2:0] uart_state; +reg [2:0] uart_state_nxt; + +wire xfer_done; + +parameter RX_SYNC = 3'h0; +parameter RX_CMD = 3'h1; +parameter RX_DATA = 3'h2; + +always @(uart_state or mem_burst) + case (uart_state) + RX_SYNC : uart_state_nxt = RX_CMD; + RX_CMD : uart_state_nxt = mem_burst ? RX_DATA : RX_SYNC; + RX_DATA : uart_state_nxt = RX_SYNC; + default : uart_state_nxt = RX_CMD; + endcase + +always @(posedge dbg_clk or posedge dbg_rst) + if (dbg_rst) uart_state <= RX_SYNC; + else if (xfer_done | mem_burst) uart_state <= uart_state_nxt; + +assign cmd_valid = (uart_state==RX_CMD) & xfer_done; +assign xfer_done = uart_state!=RX_SYNC; + +endmodule + diff --git a/tests/simple/operators.v b/tests/simple/operators.v new file mode 100644 index 00000000..b9bbc13c --- /dev/null +++ b/tests/simple/operators.v @@ -0,0 +1,97 @@ + +module test(clk, mode, u1, s1, u2, s2, y); + +input clk; +input [5:0] mode; + +input [3:0] u1, u2; +input signed [3:0] s1, s2; + +output reg [7:0] y; + +always @(posedge clk) begin + y <= 8'h42; + case (mode) + 0: y <= u1 << u2; + 1: y <= u1 << s2; + 2: y <= s1 << u2; + 3: y <= s1 << s2; + + 4: y <= u1 >> u2; + 5: y <= u1 >> s2; + 6: y <= s1 >> u2; + 7: y <= s1 >> s2; + + 8: y <= u1 <<< u2; + 9: y <= u1 <<< s2; + 10: y <= s1 <<< u2; + 11: y <= s1 <<< s2; + + 12: y <= u1 >>> u2; + 13: y <= u1 >>> s2; + 14: y <= s1 >>> u2; + 15: y <= s1 >>> s2; + + 16: y <= u1 < u2; + 17: y <= u1 < s2; + 18: y <= s1 < u2; + 19: y <= s1 < s2; + + 20: y <= u1 <= u2; + 21: y <= u1 <= s2; + 22: y <= s1 <= u2; + 23: y <= s1 <= s2; + + 24: y <= u1 == u2; + 25: y <= u1 == s2; + 26: y <= s1 == u2; + 27: y <= s1 == s2; + + 28: y <= u1 != u2; + 29: y <= u1 != s2; + 30: y <= s1 != u2; + 31: y <= s1 != s2; + + 32: y <= u1 >= u2; + 33: y <= u1 >= s2; + 34: y <= s1 >= u2; + 35: y <= s1 >= s2; + + 36: y <= u1 > u2; + 37: y <= u1 > s2; + 38: y <= s1 > u2; + 39: y <= s1 > s2; + + 40: y <= u1 + u2; + 41: y <= u1 + s2; + 42: y <= s1 + u2; + 43: y <= s1 + s2; + + 44: y <= u1 - u2; + 45: y <= u1 - s2; + 46: y <= s1 - u2; + 47: y <= s1 - s2; + + 48: y <= +u1; + 49: y <= -u1; + 50: y <= +s1; + 51: y <= -s1; + + 52: y <= { &u1, ~&u1, |u1, ~|u1, ^u1, ~^u1, ^~u1 }; + 53: y <= { &s1, ~&s1, |s1, ~|s1, ^s1, ~^s1, ^~s1 }; + 54: y <= { &u1[1:0], ~&u1[1:0], |u1[1:0], ~|u1[1:0], ^u1[1:0], ~^u1[1:0], ^~u1[1:0] }; + 55: y <= { &s1[1:0], ~&s1[1:0], |s1[1:0], ~|s1[1:0], ^s1[1:0], ~^s1[1:0], ^~s1[1:0] }; + + 56: y <= { u1[1:0] && u2[1:0], u1[1:0] && u2[1:0], !u1[1:0] }; + 57: y <= {4{u1[1:0]}}; + 58: y <= {u1, u2} ^ {s1, s2}; + 59: y <= {u1, u2} & {s1, s2}; + + 60: y <= u1[0] ? u1 : u2; + 61: y <= u1[0] ? u1 : s2; + 62: y <= u1[0] ? s1 : u2; + 63: y <= u1[0] ? s1 : s2; + endcase +end + +endmodule diff --git a/tests/simple/paramods.v b/tests/simple/paramods.v new file mode 100644 index 00000000..94fd2dfc --- /dev/null +++ b/tests/simple/paramods.v @@ -0,0 +1,37 @@ + +module test1(a, b, x, y); + +input [7:0] a, b; +output [7:0] x, y; + +inc #(.step(3)) inc_a (.in(a), .out(x)); +inc #(.width(4), .step(7)) inc_b (b, y); + +endmodule + +// ----------------------------------- + +module test2(a, b, x, y); + +input [7:0] a, b; +output [7:0] x, y; + +inc #(5) inc_a (.in(a), .out(x)); +inc #(4, 7) inc_b (b, y); + +endmodule + +// ----------------------------------- + +module inc(in, out); + +parameter width = 8; +parameter step = 1; + +input [width-1:0] in; +output [width-1:0] out; + +assign out = in + step; + +endmodule + diff --git a/tests/simple/process.v b/tests/simple/process.v new file mode 100644 index 00000000..53258664 --- /dev/null +++ b/tests/simple/process.v @@ -0,0 +1,65 @@ + +module uut(clk, arst, a, b, c, d, e, f, out1); + +input clk, arst, a, b, c, d, e, f; +output reg [3:0] out1; + +always @(posedge clk, posedge arst) begin + if (arst) + out1 = 0; + else begin + if (a) begin + case ({b, c}) + 2'b00: + out1 = out1 + 9; + 2'b01, 2'b10: + out1 = out1 + 13; + endcase + if (d) begin + out1 = out1 + 2; + out1 = out1 + 1; + end + case ({e, f}) + 2'b11: + out1 = out1 + 8; + 2'b00: + ; + default: + out1 = out1 + 10; + endcase + out1 = out1 ^ 7; + end + out1 = out1 + 14; + end +end + +endmodule + +// ------------------------------------------------------------- + +// extracted from ../asicworld/code_hdl_models_uart.v +// (triggered a bug in the proc_mux pass) +module uart (reset, txclk, ld_tx_data, tx_empty, tx_cnt); + +input reset; +input txclk; +input ld_tx_data; + +output reg tx_empty; +output reg [3:0] tx_cnt; + +always @ (posedge txclk) +if (reset) begin + tx_empty <= 1; + tx_cnt <= 0; +end else begin + if (ld_tx_data) begin + tx_empty <= 0; + end + if (!tx_empty) begin + tx_cnt <= tx_cnt + 1; + end +end + +endmodule + diff --git a/tests/simple/run-test.sh b/tests/simple/run-test.sh new file mode 100755 index 00000000..bf27d15f --- /dev/null +++ b/tests/simple/run-test.sh @@ -0,0 +1,3 @@ +#!/bin/bash +make -C ../.. || exit 1 +exec bash ../tools/autotest.sh *.v diff --git a/tests/simple/subbytes.v b/tests/simple/subbytes.v new file mode 100644 index 00000000..04269a99 --- /dev/null +++ b/tests/simple/subbytes.v @@ -0,0 +1,82 @@ + +// test taken from systemcaes from iwls2005 + +module subbytes_00(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 [31:0] data_i; +output ready_o; +output [31:0] data_o; +output [7:0] sbox_data_o; +input [7:0] sbox_data_i; +output sbox_decrypt_o; + +reg ready_o; +reg [31:0] data_o; +reg [7:0] sbox_data_o; +reg sbox_decrypt_o; + +reg [1:0] state; +reg [1:0] next_state; +reg [31:0] data_reg; +reg [31:0] next_data_reg; +reg next_ready_o; + +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 + +reg [31:0] data_i_var, data_reg_128; +reg [7:0] data_array [3:0]; +reg [7:0] data_reg_var [3: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[ 31: 24]; + data_array[1] = data_i_var[ 23: 16]; + data_array[2] = data_i_var[ 15: 8]; + data_array[3] = data_i_var[ 7: 0]; + + data_reg_var[0] = data_reg[ 31: 24]; + data_reg_var[1] = data_reg[ 23: 16]; + data_reg_var[2] = data_reg[ 15: 8]; + data_reg_var[3] = data_reg[ 7: 0]; + + sbox_decrypt_o = decrypt_i; + sbox_data_o = data_array[state]; + next_state = state; + next_data_reg = data_reg; + + next_ready_o = 0; + data_o = data_reg; + + if (state) begin + if (start_i) begin + next_state = 1; + end + end else begin + data_reg_var[state] = sbox_data_i; + data_reg_128[ 31: 24] = data_reg_var[0]; + data_reg_128[ 23: 16] = data_reg_var[1]; + data_reg_128[ 15: 8] = data_reg_var[2]; + data_reg_128[ 7: 0] = data_reg_var[3]; + next_data_reg = data_reg_128; + next_state = state + 1; + end +end + +endmodule diff --git a/tests/simple/task_func.v b/tests/simple/task_func.v new file mode 100644 index 00000000..3a09cbc3 --- /dev/null +++ b/tests/simple/task_func.v @@ -0,0 +1,35 @@ + +module test01(clk, a, b, c, x, y, z, w); + +input clk; +input [7:0] a, b, c; +output reg [7:0] x, y, z, w; + +function [7:0] sum_shift; +input [3:0] s1, s2, s3; +sum_shift = s1 + (s2 << 2) + (s3 << 4); +endfunction + +task reset_w; +w = 0; +endtask + +task add_to; +output [7:0] out; +input [7:0] in; +out = out + in; +endtask + +always @(posedge clk) begin + x = sum_shift(a, b, c); + y = sum_shift(a[7:4], b[5:2], c[3:0]); + z = sum_shift(a[0], b[5:4], c >> 5) ^ sum_shift(1, 2, 3); + + reset_w; + add_to(w, x); + add_to(w, y); + add_to(w, z); +end + +endmodule + diff --git a/tests/simple/usb_phy_tetsts.v b/tests/simple/usb_phy_tetsts.v new file mode 100644 index 00000000..2375183d --- /dev/null +++ b/tests/simple/usb_phy_tetsts.v @@ -0,0 +1,36 @@ + +// from usb_rx_phy +module test01(clk, rst, rx_en, fs_ce); + +input clk, rst; +input rx_en; +output reg fs_ce; +reg [1:0] dpll_next_state; +reg [1:0] dpll_state; + +always @(posedge clk) + dpll_state <= rst ? 0 : dpll_next_state; + +always @* + begin + fs_ce = 1'b0; + case(dpll_state) + 2'h0: + if(rx_en) dpll_next_state = 2'h0; + else dpll_next_state = 2'h1; + 2'h1:begin + fs_ce = 1'b1; + if(rx_en) dpll_next_state = 2'h3; + else dpll_next_state = 2'h2; + end + 2'h2: + if(rx_en) dpll_next_state = 2'h0; + else dpll_next_state = 2'h3; + 2'h3: + if(rx_en) dpll_next_state = 2'h0; + else dpll_next_state = 2'h0; + endcase + end + +endmodule + diff --git a/tests/simple/values.v b/tests/simple/values.v new file mode 100644 index 00000000..9fae4da9 --- /dev/null +++ b/tests/simple/values.v @@ -0,0 +1,44 @@ + +module test_signed(a, b, c, d, y); + +input [3:0] a, b, c; +input signed [3:0] d; +output reg [7:0] y; + +always @* begin + if (a && b) + y = c; + else + y = d; +end + +endmodule + +module test_const(a, y); + +input [3:0] a; +output reg [28:0] y; + +always @* + case (a) + 4'b0000: y = 0; + 4'b0001: y = 11; + 4'b0010: y = 222; + 4'b0011: y = 3456; + 4'b0100: y = 'b10010010; + 4'b0101: y = 'h123abc; + 4'b0110: y = 'o1234567; + 4'b0111: y = 'd3456789; + 4'b1000: y = 16'b10010010; + 4'b1001: y = 16'h123abc; + 4'b1010: y = 16'o1234567; + 4'b1011: y = 16'd3456789; + 4'b1100: y = "foobar"; + 4'b1101: y = "foobarfoobarfoobar"; + 4'b1110: y = 16'h1; + 4'b1111: y = a; + default: y = 'bx; + endcase + +endmodule + diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh new file mode 100755 index 00000000..6b22f902 --- /dev/null +++ b/tests/tools/autotest.sh @@ -0,0 +1,164 @@ +#!/bin/bash + +libs="" +genvcd=false +use_isim=false +verbose=false +keeprunning=false +backend_opts="-noattr -noexpr" +kompare_xst=false +scriptfiles="" +toolsdir="$(cd $(dirname $0); pwd)" + +if [ ! -f $toolsdir/cmp_tbdata -o $toolsdir/cmp_tbdata.c -nt $toolsdir/cmp_tbdata ]; then + ( set -ex; gcc -Wall -o $toolsdir/cmp_tbdata $toolsdir/cmp_tbdata.c; ) || exit 1 +fi + +while getopts il:wkvrxs: opt; do + case "$opt" in + i) + use_isim=true ;; + l) + libs="$libs $(cd $(dirname $OPTARG); pwd)/$(basename $OPTARG)";; + w) + genvcd=true ;; + k) + keeprunning=true ;; + v) + verbose=true ;; + r) + backend_opts="$backend_opts norename" ;; + x) + kompare_xst=true ;; + s) + [[ "$OPTARG" == /* ]] || OPTARG="$PWD/$OPTARG" + scriptfiles="$scriptfiles $OPTARG" ;; + *) + echo "Usage: $0 [-i] [-w] [-k] [-v] [-r] [-x] [-l libs] [-s script] verilog-files\n" >&2 + exit 1 + esac +done + +create_ref() { + if $kompare_xst; then + echo "verilog work $1" > $2.prj + cat <<- EOT > $2.xst + run + -ifn $2.prj -ifmt mixed -ofn $2 -ofmt NGC -p xc6slx4-3-tqg144 + -top $( grep ^module $1 | sed -r 's,[^0-9A-Za-z_]+, ,g' | awk '{ print $2; exit; }'; ) + -opt_mode Speed -opt_level 1 -iobuf NO + EOT + ( + set +x + prefix="$2" + xilver=$( ls -v /opt/Xilinx/ | tail -n1; ) + case "$( uname -m )" in + x86_64) + set --; . /opt/Xilinx/$xilver/ISE_DS/settings64.sh ;; + *) + set --; . /opt/Xilinx/$xilver/ISE_DS/settings32.sh ;; + esac + set -x + xst -ifn $prefix.xst + netgen -w -ofmt verilog $prefix.ngc $prefix + ) + else + cp "$1" "$2.v" + fi +} + +compile_and_run() { + exe="$1"; output="$2"; shift 2 + if $use_isim; then + ( + set +x + files=( "$@" ) + xilver=$( ls -v /opt/Xilinx/ | tail -n1; ) + case "$( uname -m )" in + x86_64) + set --; . /opt/Xilinx/$xilver/ISE_DS/settings64.sh ;; + *) + set --; . /opt/Xilinx/$xilver/ISE_DS/settings32.sh ;; + esac + set -x + vlogcomp "${files[@]}" + if $kompare_xst; then + fuse -o "$exe" -lib unisims_ver -top testbench -top glbl + else + fuse -o "$exe" -top testbench + fi + { echo "run all"; echo "exit"; } > run-all.tcl + PATH="$PATH:" "$exe" -tclbatch run-all.tcl > "$output" + ) + else + iverilog -s testbench -o "$exe" "$@" + vvp -n "$exe" > "$output" + fi +} + +shift $((OPTIND - 1)) + +for fn +do + bn=${fn%.v} + if [ "$bn" == "$fn" ]; then + echo "Invalid argument: $fn" >&2 + exit 1 + fi + [[ "$bn" == *_tb ]] && continue + echo -n "Test: $bn " + + rm -f ${bn}.{err,log} + mkdir -p ${bn}.out + rm -rf ${bn}.out/* + + body() { + cd ${bn}.out + cp ../$fn $fn + if [ ! -f ../${bn}_tb.v ]; then + "$toolsdir"/../../yosys -b autotest -o ${bn}_tb.v $fn + else + cp ../${bn}_tb.v ${bn}_tb.v + fi + if $genvcd; then sed -i 's,// \$dump,$dump,g' ${bn}_tb.v; fi + create_ref $fn ${bn}_ref + compile_and_run ${bn}_tb_ref ${bn}_out_ref ${bn}_tb.v ${bn}_ref.v $libs + if $genvcd; then mv testbench.vcd ${bn}_ref.vcd; fi + + test_count=0 + test_passes() { + "$toolsdir"/../../yosys -b "verilog $backend_opts" "$@" -o ${bn}_syn${test_count}.v $fn $scriptfiles + compile_and_run ${bn}_tb_syn${test_count} ${bn}_out_syn${test_count} \ + ${bn}_tb.v ${bn}_syn${test_count}.v $libs \ + "$toolsdir"/../../techlibs/simlib.v \ + "$toolsdir"/../../techlibs/stdcells_sim.v + if $genvcd; then mv testbench.vcd ${bn}_syn${test_count}.vcd; fi + $toolsdir/cmp_tbdata ${bn}_out_ref ${bn}_out_syn${test_count} + test_count=$(( test_count + 1 )) + } + + if [ -n "$scriptfiles" ]; then + test_passes + else + test_passes -p hierarchy -p proc -p memory -p opt -p fsm -p opt + test_passes -p hierarchy -p proc -p memory -p opt -p fsm -p opt -p techmap -p opt + # test_passes -p hierarchy -p proc -p memory -p opt -p techmap -p opt -p abc -p opt + fi + touch ../${bn}.log + } + + if $verbose; then + echo ".." + echo "Output written to console." > ${bn}.err + ( set -ex; body; ) + else + ( set -ex; body; ) > ${bn}.err 2>&1 + fi + + if [ -f ${bn}.log ]; then + mv ${bn}.err ${bn}.log + echo "-> ok" + else echo "-> ERROR!"; $keeprunning || exit 1; fi +done + +exit 0 diff --git a/tests/tools/cmp_tbdata.c b/tests/tools/cmp_tbdata.c new file mode 100644 index 00000000..86485efd --- /dev/null +++ b/tests/tools/cmp_tbdata.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include + +int line = 0; +char buffer1[1024]; +char buffer2[1024]; + +void check(bool ok) +{ + if (ok) + return; + fprintf(stderr, "Error in testbench output compare (line=%d):\n-%s\n+%s\n", line, buffer1, buffer2); + exit(1); +} + +int main(int argc, char **argv) +{ + FILE *f1, *f2; + bool eof1, eof2; + int i; + + check(argc == 3); + + f1 = fopen(argv[1], "r"); + f2 = fopen(argv[2], "r"); + + check(f1 && f2); + + while (!feof(f1) && !feof(f2)) + { + line++; + buffer1[0] = 0; + buffer2[0] = 0; + + eof1 = fgets(buffer1, 1024, f1) == NULL; + eof2 = fgets(buffer2, 1024, f2) == NULL; + + if (*buffer1 && buffer1[strlen(buffer1)-1] == '\n') + buffer1[strlen(buffer1)-1] = 0; + + if (*buffer2 && buffer2[strlen(buffer2)-1] == '\n') + buffer2[strlen(buffer2)-1] = 0; + + check(eof1 == eof2); + + for (i = 0; buffer1[i] || buffer2[i]; i++) + { + check(buffer1[i] != 0 && buffer2[i] != 0); + + // first argument is the reference. An 'z' or 'x' + // here means we don't care about the result. + if (buffer1[i] == 'z' || buffer1[i] == 'x') + continue; + + check(buffer1[i] == buffer2[i]); + } + } + + check(feof(f1) && feof(f2)); + + fclose(f1); + fclose(f2); + return 0; +} + diff --git a/tests/tools/profiler.pl b/tests/tools/profiler.pl new file mode 100755 index 00000000..456f634b --- /dev/null +++ b/tests/tools/profiler.pl @@ -0,0 +1,55 @@ +#!/usr/bin/perl +# parse 'yosys -t' logfile and find slow passes + +my $max_depth = 0; +my %last_line_by_depth; +my %last_time_by_depth; + +my @lines_text; +my @lines_depth; +my @lines_time; + +while (<>) +{ + chomp; + next unless /^\[([0-9.]+)\] (([0-9]+\.)+)/; + my ($this_time, $this_id, $this_header) = ($1, $2, $4); + + push @lines_text, $_; + push @lines_depth, 0; + push @lines_time, 0; + + my $depth = $this_id; + $depth =~ s/[^.]//g; + $depth = length $depth; + $max_depth = $depth if $depth > $max_depth; + + for (my $i = $depth; $i <= $max_depth; $i++) { + next unless exists $last_time_by_depth{$i}; + $lines_time[$last_line_by_depth{$i}] = $this_time-$last_time_by_depth{$i}; + delete $last_time_by_depth{$i}; + delete $last_header_by_depth{$i}; + } + + $last_time_by_depth{$depth} = $this_time; + $last_line_by_depth{$depth} = $#lines_text; + $lines_depth[$#lines_text] = $depth; +} + +for (my $depth = 1; $depth <= $max_depth; $depth++) { + printf "\nSlow passes on recursion depth %d:\n", $depth; + my @lines; + for (my $i = 0; $i <= $#lines_text; $i++) { + next if $lines_depth[$i] != $depth or $lines_time[$i] < 1.0; + push @lines, sprintf("%3d %08.2f %s\n", $lines_depth[$i], $lines_time[$i], $lines_text[$i]); + } + for my $line (sort {$b cmp $a} @lines) { + print $line; + } +} + +printf "\nFull journal of headers:\n"; +for (my $i = 0; $i <= $#lines_text; $i++) { + printf "%3d %08.2f %s\n", $lines_depth[$i], $lines_time[$i], $lines_text[$i]; +} + diff --git a/tests/tools/rtlview.sh b/tests/tools/rtlview.sh new file mode 100755 index 00000000..6a4adcae --- /dev/null +++ b/tests/tools/rtlview.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# using Xilinx ISE to display RTL schematics + +if [ ! -f "$1" ]; then + echo "Usage: $0 " >&2 + exit 1 +fi + +prjdir="$(dirname $0)/rtlview.tmp" +mkdir -p "$prjdir" + +cp "$1" "$prjdir"/schematic.v +cp "$(dirname $0)"/../../techlibs/blackbox.v "$prjdir"/blackbox.v +cd "$prjdir" + +if fuser -s ise.out; then + echo "ISE already running. Re-create RTL schematic from GUI." + exit 1 +fi + +xilver=$( ls -v /opt/Xilinx/ | grep '^[0-9]' | tail -n1; ) + +cat > rtlview.xise << EOT + + +
+ + + + + + + + + + + + + + + + + + + + + + + +EOT + +set -- +case "$( uname -m )" in +x86_64) + . /opt/Xilinx/$xilver/ISE_DS/settings64.sh ;; +*) + . /opt/Xilinx/$xilver/ISE_DS/settings32.sh ;; +esac + +ise rtlview.xise > ise.out 2>&1 & +echo "ISE is now starting up. Create RTL schematic from GUI." + diff --git a/tests/tools/vcdcd.pl b/tests/tools/vcdcd.pl new file mode 100755 index 00000000..4875eeeb --- /dev/null +++ b/tests/tools/vcdcd.pl @@ -0,0 +1,201 @@ +#!/usr/bin/perl -w +# +# Note: You might need to install the Verilog::VCD package using CPAN.. + +use strict; +use Data::Dumper; +use Verilog::VCD qw(parse_vcd list_sigs); + +$| = 1; + +if ($#ARGV != 1) { + print STDERR "\n"; + print STDERR "VCDCD - Value Change Dump Change Dumper\n"; + print STDERR "\n"; + print STDERR "Usage: $0 gold.vcd gate.vcd\n"; + print STDERR "\n"; + print STDERR "Compare a known-good (gold) vcd file with a second (gate) vcd file.\n"; + print STDERR "This is not very efficient -- so use with care with large vcd files.\n"; + print STDERR "\n"; + exit 1; +} + +my $fn_gold = $ARGV[0]; +my $fn_gate = $ARGV[1]; + +print "Finding common signals..\n"; +my @gold_signals = list_sigs($fn_gold); +my @gate_signals = list_sigs($fn_gate); + +my %gold_signals_hash; +my %gate_signals_hash; + +for (@gold_signals) { + my $fullname = $_; + s/(\[([0-9]+|[0-9]+:[0-9]+)\])$//; + $gold_signals_hash{$_}->{$fullname} = 1 unless /(^|\.)_[0-9]+_/; +} + +for (@gate_signals) { + my $fullname = $_; + s/(\[([0-9]+|[0-9]+:[0-9]+)\])$//; + $gate_signals_hash{$_}->{$fullname} = 1 unless /(^|\.)_[0-9]+_/; +} + +my @signals; +for my $net (sort keys %gold_signals_hash) { + next unless exists $gate_signals_hash{$net}; + # next unless $net eq "tst_bench_top.i2c_top.byte_controller.bit_controller.cnt"; + my %orig_net_names; + print "common signal: $net"; + for my $fullname (keys $gold_signals_hash{$net}) { + $orig_net_names{$fullname} = 1; + } + for my $fullname (keys $gate_signals_hash{$net}) { + $orig_net_names{$fullname} = 1; + } + for my $_ (sort keys %orig_net_names) { + push @signals, $_; + print " $1" if /(\[([0-9]+|[0-9]+:[0-9]+)\])$/; + } + print "\n"; +} + +print "Loading gold vcd data..\n"; +my $vcd_gold = parse_vcd($fn_gold, {siglist => \@signals}); + +print "Loading gate vcd data..\n"; +my $vcd_gate = parse_vcd($fn_gate, {siglist => \@signals}); + +# print Dumper($vcd_gold); +# print Dumper($vcd_gate); + +my %times; +my $signal_maxlen = 8; +my $data_gold = { }; +my $data_gate = { }; + +sub checklen($$) +{ + my ($net, $val) = @_; + my $thislen = length $val; + $thislen += $1 if $net =~ /\[([0-9]+)\]$/; + $thislen += $1 if $net =~ /\[([0-9]+):[0-9]+\]$/; + $signal_maxlen = $thislen if $signal_maxlen < $thislen; +} + +print "Processing gold vcd data..\n"; +for my $key (keys %$vcd_gold) { + for my $net (@{$vcd_gold->{$key}->{'nets'}}) { + my $netname = $net->{'hier'} . "." . $net->{'name'}; + for my $tv (@{$vcd_gold->{$key}->{'tv'}}) { + my $time = int($tv->[0]); + my $value = $tv->[1]; + checklen($netname, $value); + $data_gold->{$time}->{$netname} = $value; + $times{$time} = 1; + } + } +} + +print "Processing gate vcd data..\n"; +for my $key (keys %$vcd_gate) { + for my $net (@{$vcd_gate->{$key}->{'nets'}}) { + my $netname = $net->{'hier'} . "." . $net->{'name'}; + for my $tv (@{$vcd_gate->{$key}->{'tv'}}) { + my $time = int($tv->[0]); + my $value = $tv->[1]; + checklen($netname, $value); + $data_gate->{$time}->{$netname} = $value; + $times{$time} = 1; + } + } +} + +my $diffcount = 0; +my %state_gold; +my %state_gate; +my %signal_sync; +my %touched_nets; + +sub set_state_bit($$$$) +{ + my ($state, $net, $bit, $value) = @_; + my @data; + @data = split //, $state->{$net} if exists $state->{$net}; + unshift @data, "-" while $#data < $bit; + $data[$#data - $bit] = $value; + $state->{$net} = join "", @data; + $signal_sync{$net} = 1 unless exists $signal_sync{$net}; + $touched_nets{$net} = 1; +} + +sub set_state($$$) +{ + my ($state, $net, $value) = @_; + + if ($net =~ /(.*)\[([0-9]+)\]$/) { + set_state_bit($state, $1, $2, $value); + return; + } + + if ($net =~ /(.*)\[([0-9]+):([0-9]+)\]$/) { + my ($n, $u, $d) = ($1, $2, $3); + my @bits = split //, $value; + my $extbit = $bits[0] eq "1" ? "0" : $bits[0]; + unshift @bits, $extbit while $#bits < $u - $d; + set_state_bit($state, $n, $u--, shift @bits) while $u >= $d; + return; + } + + $state->{$net} = $value; + $signal_sync{$net} = 1 unless exists $signal_sync{$net}; + $touched_nets{$net} = 1; +} + +sub cmp_signal($$) +{ + my ($a, $b) = @_; + return 1 if $a eq $b; + + my @a = split //, $a; + my @b = split //, $b; + + unshift @a, "-" while $#a < $#b; + unshift @b, "-" while $#b < $#a; + + for (my $i = 0; $i <= $#a; $i++) { + return 0 if $a[$i] ne "x" && $a[$i] ne $b[$i]; + } + + return 1; +} + +print "Comparing vcd data..\n"; +for my $time (sort { $a <=> $b } keys %times) +{ + %touched_nets = (); + for my $net (keys %{$data_gold->{$time}}) { + set_state(\%state_gold, $net, $data_gold->{$time}->{$net}); + } + for my $net (keys %{$data_gate->{$time}}) { + set_state(\%state_gate, $net, $data_gate->{$time}->{$net}); + } + for my $net (sort keys %touched_nets) { + my ($stgo, $stga) = ('-', '-'); + $stgo = $state_gold{$net} if exists $state_gold{$net}; + $stga = $state_gate{$net} if exists $state_gate{$net}; + if (cmp_signal($stgo, $stga)) { + next if $signal_sync{$net}; + printf "%-10s %-20d %-*s %-*s %s\n", "", $time, $signal_maxlen, $stgo, $signal_maxlen, $stga, $net; + $signal_sync{$net} = 1; + } else { + printf "\n%-10s %-20s %-*s %-*s %s\n", "count", "time", $signal_maxlen, "gold", $signal_maxlen, "gate", "net" if $diffcount++ == 0; + printf "%-10d %-20d %-*s %-*s %s\n", $diffcount, $time, $signal_maxlen, $stgo, $signal_maxlen, $stga, $net; + $signal_sync{$net} = 0; + } + } +} + +print "Found $diffcount differences.\n"; +exit ($diffcount > 0 ? 1 : 0); -- cgit v1.2.3