Merge remote-tracking branch 'origin/master' into ganesh_dev

This commit is contained in:
Ganesh Gore 2021-01-25 11:04:28 -07:00
commit 78e2a242b3
122 changed files with 303927 additions and 26 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,265 @@
<!-- Architecture annotation for OpenFPGA framework
This annotation supports the k4_frac_cc_sky130nm.xml
- General purpose logic block
- K = 6, N = 10, I = 40
- Single mode
- Routing architecture
- L = 4, fc_in = 0.15, fc_out = 0.1
- Skywater 130nm PDK
- circuit models are binded to the opensource skywater
foundry middle-speed (ms) standard cell library
-->
<openfpga_architecture>
<technology_library>
<device_library>
<device_model name="logic" type="transistor">
<lib type="industry" corner="TOP_TT" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="0.9" pn_ratio="2"/>
<pmos name="pch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
<nmos name="nch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
</device_model>
<device_model name="io" type="transistor">
<lib type="academia" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="2.5" pn_ratio="3"/>
<pmos name="pch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
<nmos name="nch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
</device_model>
</device_library>
<variation_library>
<variation name="logic_transistor_var" abs_deviation="0.1" num_sigma="3"/>
<variation name="io_transistor_var" abs_deviation="0.1" num_sigma="3"/>
</variation_library>
</technology_library>
<circuit_library>
<circuit_model type="inv_buf" name="sky130_fd_sc_hd__inv_1" prefix="sky130_fd_sc_hd__inv_1" is_default="true" verilog_netlist="${SKYWATER_OPENFPGA_HOME}/PDK/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/inv/sky130_fd_sc_hd__inv_1.v">
<design_technology type="cmos" topology="inverter" size="1"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" lib_name="A" size="1"/>
<port type="output" prefix="out" lib_name="Y" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="sky130_fd_sc_hd__buf_2" prefix="sky130_fd_sc_hd__buf_2" is_default="false" verilog_netlist="${SKYWATER_OPENFPGA_HOME}/PDK/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/buf/sky130_fd_sc_hd__buf_2.v">
<design_technology type="cmos" topology="buffer" size="1" num_level="2" f_per_stage="2"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" lib_name="A" size="1"/>
<port type="output" prefix="out" lib_name="X" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="sky130_fd_sc_hd__buf_4" prefix="sky130_fd_sc_hd__buf_4" is_default="false" verilog_netlist="${SKYWATER_OPENFPGA_HOME}/PDK/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/buf/sky130_fd_sc_hd__buf_4.v">
<design_technology type="cmos" topology="buffer" size="1" num_level="2" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" lib_name="A" size="1"/>
<port type="output" prefix="out" lib_name="X" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="sky130_fd_sc_hd__inv_2" prefix="sky130_fd_sc_hd__inv_2" is_default="false" verilog_netlist="${SKYWATER_OPENFPGA_HOME}/PDK/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/inv/sky130_fd_sc_hd__inv_2.v">
<design_technology type="cmos" topology="buffer" size="1"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" lib_name="A" size="1"/>
<port type="output" prefix="out" lib_name="Y" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="gate" name="sky130_fd_sc_hd__or2_1" prefix="sky130_fd_sc_hd__or2_1" is_default="true" verilog_netlist="${SKYWATER_OPENFPGA_HOME}/PDK/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/or2/sky130_fd_sc_hd__or2_1.v">
<design_technology type="cmos" topology="OR"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="a" lib_name="A" size="1"/>
<port type="input" prefix="b" lib_name="B" size="1"/>
<port type="output" prefix="out" lib_name="X" size="1"/>
<delay_matrix type="rise" in_port="a b" out_port="out">
10e-12 5e-12
</delay_matrix>
<delay_matrix type="fall" in_port="a b" out_port="out">
10e-12 5e-12
</delay_matrix>
</circuit_model>
<!-- Define a circuit model for the standard cell MUX2
OpenFPGA requires the following truth table for the MUX2
When the select signal sel is enabled, the first input, i.e., in0
will be propagated to the output, i.e., out
If your standard cell provider does not offer the exact truth table,
you can simply swap the inputs as shown in the example below
-->
<circuit_model type="gate" name="sky130_fd_sc_hd__mux2_1" prefix="sky130_fd_sc_hd__mux2_1" verilog_netlist="${SKYWATER_OPENFPGA_HOME}/PDK/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/mux2/sky130_fd_sc_hd__mux2_1.v">
<design_technology type="cmos" topology="MUX2"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in0" lib_name="A1" size="1"/>
<port type="input" prefix="in1" lib_name="A0" size="1"/>
<port type="input" prefix="sel" lib_name="S" size="1"/>
<port type="output" prefix="out" lib_name="X" size="1"/>
</circuit_model>
<circuit_model type="chan_wire" name="chan_segment" prefix="track_seg" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="101" C="22.5e-15" num_level="1"/>
<!-- model_type could be T, res_val and cap_val DON'T CARE -->
</circuit_model>
<circuit_model type="wire" name="direct_interc" prefix="direct_interc" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="0" C="0" num_level="1"/>
<!-- model_type could be T, res_val cap_val should be defined -->
</circuit_model>
<circuit_model type="mux" name="mux_tree" prefix="mux_tree" is_default="true" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" add_const_input="true" const_input_val="1"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<pass_gate_logic circuit_model_name="sky130_fd_sc_hd__mux2_1"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<circuit_model type="mux" name="mux_tree_tapbuf" prefix="mux_tree_tapbuf" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" add_const_input="true" const_input_val="1"/>
<input_buffer exist="false"/>
<output_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__buf_4"/>
<pass_gate_logic circuit_model_name="sky130_fd_sc_hd__mux2_1"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<!--DFF subckt ports should be defined as <D> <Q> <CLK> <RESET> <SET> -->
<circuit_model type="ff" name="sky130_fd_sc_hd__sdfrtp_1" prefix="sky130_fd_sc_hd__sdfrtp_1" verilog_netlist="${SKYWATER_OPENFPGA_HOME}/PDK/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/sdfrtp/sky130_fd_sc_hd__sdfrtp_1.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<output_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<port type="input" prefix="D" size="1"/>
<port type="input" prefix="DI" lib_name="SCD" size="1"/>
<port type="input" prefix="Test_en" lib_name="SCE" size="1" is_global="true" default_val="0"/>
<port type="input" prefix="reset" lib_name="RESET_B" size="1" default_val="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="clock" prefix="clk" lib_name="CLK" size="1" is_global="false" default_val="0" />
</circuit_model>
<circuit_model type="lut" name="frac_lut4" prefix="frac_lut4" dump_structural_verilog="true">
<design_technology type="cmos" fracturable_lut="true"/>
<input_buffer exist="false"/>
<output_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__buf_2"/>
<lut_input_inverter exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<lut_input_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__buf_2"/>
<lut_intermediate_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__buf_2" location_map="-1-"/>
<pass_gate_logic circuit_model_name="sky130_fd_sc_hd__mux2_1"/>
<port type="input" prefix="in" size="4" tri_state_map="---1" circuit_model_name="sky130_fd_sc_hd__or2_1"/>
<port type="output" prefix="lut2_out" size="2" lut_frac_level="2" lut_output_mask="2,3"/>
<port type="output" prefix="lut4_out" size="1" lut_output_mask="0"/>
<port type="sram" prefix="sram" size="16"/>
<port type="sram" prefix="mode" size="1" mode_select="true" circuit_model_name="sky130_fd_sc_hd__dfrtp_1" default_val="1"/>
</circuit_model>
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
<circuit_model type="ccff" name="sky130_fd_sc_hd__dfrtp_1" prefix="sky130_fd_sc_hd__dfrtp_1" verilog_netlist="${SKYWATER_OPENFPGA_HOME}/PDK/skywater-pdk/libraries/sky130_fd_sc_hd/latest/cells/dfrtp/sky130_fd_sc_hd__dfrtp_1.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<output_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<port type="input" prefix="D" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="clock" prefix="prog_clk" lib_name="CLK" size="1" is_global="true" default_val="0" is_prog="true"/>
<port type="input" prefix="pReset" lib_name="RESET_B" size="1" is_global="true" default_val="1" is_prog="true" is_reset="true"/>
</circuit_model>
<circuit_model type="iopad" name="EMBEDDED_IO_HD" prefix="EMBEDDED_IO_HD" is_default="true" verilog_netlist="${SKYWATER_OPENFPGA_HOME}/HDL/common/digital_io_hd.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<output_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<port type="input" prefix="SOC_IN" lib_name="SOC_IN" size="1" is_global="true" is_io="true" is_data_io="true"/>
<port type="output" prefix="SOC_OUT" lib_name="SOC_OUT" size="1" is_global="true" is_io="true" is_data_io="true"/>
<port type="output" prefix="SOC_DIR" lib_name="SOC_DIR" size="1" is_global="true" is_io="true"/>
<port type="input" prefix="IO_ISOL_N" lib_name="IO_ISOL_N" size="1" is_global="true" default_val="1"/>
<port type="output" prefix="inpad" lib_name="FPGA_IN" size="1"/>
<port type="input" prefix="outpad" lib_name="FPGA_OUT" size="1"/>
<port type="sram" prefix="en" lib_name="FPGA_DIR" size="1" mode_select="true" circuit_model_name="sky130_fd_sc_hd__dfrtp_1" default_val="1"/>
</circuit_model>
<circuit_model type="hard_logic" name="sky130_fd_sc_hd__mux2_1_wrapper" prefix="sky130_fd_sc_hd__mux2_1_wrapper" verilog_netlist="${SKYWATER_OPENFPGA_HOME}/HDL/common/sky130_fd_sc_hd_wrapper.v">
<design_technology type="cmos"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="a" lib_name="A0" size="1"/>
<port type="input" prefix="b" lib_name="A1" size="1"/>
<port type="input" prefix="cin" lib_name="S" size="1"/>
<port type="output" prefix="cout" lib_name="X" size="1"/>
</circuit_model>
</circuit_library>
<configuration_protocol>
<organization type="scan_chain" circuit_model_name="sky130_fd_sc_hd__dfrtp_1" num_regions="1"/>
</configuration_protocol>
<connection_block>
<switch name="ipin_cblock" circuit_model_name="mux_tree_tapbuf"/>
</connection_block>
<switch_block>
<switch name="L1_mux" circuit_model_name="mux_tree_tapbuf"/>
<switch name="L2_mux" circuit_model_name="mux_tree_tapbuf"/>
<switch name="L4_mux" circuit_model_name="mux_tree_tapbuf"/>
</switch_block>
<routing_segment>
<segment name="L1" circuit_model_name="chan_segment"/>
<segment name="L2" circuit_model_name="chan_segment"/>
<segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment>
<direct_connection>
<direct name="carry_chain" circuit_model_name="direct_interc"/>
<direct name="shift_register" circuit_model_name="direct_interc"/>
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/>
</direct_connection>
<tile_annotations>
<global_port name="clk" is_clock="true" default_val="0">
<tile name="clb" port="clk[0:3]" x="-1" y="-1"/>
</global_port>
<global_port name="Reset" is_reset="true" default_val="1">
<tile name="clb" port="reset" x="-1" y="-1"/>
</global_port>
</tile_annotations>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->
<pb_type name="io" physical_mode_name="physical" idle_mode_name="inpad"/>
<!-- IMPORTANT: must set unused I/Os to operating in INPUT mode !!! -->
<pb_type name="io[physical].iopad" circuit_model_name="EMBEDDED_IO_HD" mode_bits="1"/>
<pb_type name="io[inpad].inpad" physical_pb_type_name="io[physical].iopad" mode_bits="1"/>
<pb_type name="io[outpad].outpad" physical_pb_type_name="io[physical].iopad" mode_bits="0"/>
<!-- End physical pb_type binding in complex block IO -->
<!-- physical pb_type binding in complex block CLB -->
<!-- physical mode will be the default mode if not specified -->
<pb_type name="clb.fle" physical_mode_name="physical"/>
<pb_type name="clb.fle[physical].fabric.frac_logic.frac_lut4" circuit_model_name="frac_lut4" mode_bits="0"/>
<pb_type name="clb.fle[physical].fabric.frac_logic.carry_follower" circuit_model_name="sky130_fd_sc_hd__mux2_1_wrapper"/>
<pb_type name="clb.fle[physical].fabric.ff" circuit_model_name="sky130_fd_sc_hd__sdfrtp_1"/>
<!-- Binding operating pb_type to physical pb_type -->
<!-- Binding operating pb_types in mode 'ble4' -->
<pb_type name="clb.fle[n1_lut4].ble4.lut4" physical_pb_type_name="clb.fle[physical].fabric.frac_logic.frac_lut4" mode_bits="0">
<!-- Binding the lut4 to the first 4 inputs of fracturable lut4 -->
<port name="in" physical_mode_port="in[0:3]"/>
<port name="out" physical_mode_port="lut4_out"/>
</pb_type>
<pb_type name="clb.fle[n1_lut4].ble4.ff" physical_pb_type_name="clb.fle[physical].fabric.ff"/>
<!-- Binding operating pb_types in mode 'shift_register' -->
<pb_type name="clb.fle[shift_register].shift_reg.ff" physical_pb_type_name="clb.fle[physical].fabric.ff"/>
<!-- End physical pb_type binding in complex block IO -->
</pb_type_annotations>
</openfpga_architecture>

View File

@ -216,7 +216,9 @@
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/>
</direct_connection>
<tile_annotations>
<global_port name="clk" tile_port="clb.clk" is_clock="true" default_val="0"/>
<global_port name="clk" is_clock="true" default_val="0">
<tile name="clb" port="clk" x="-1" y="-1"/>
</global_port>
</tile_annotations>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->

View File

@ -217,8 +217,12 @@
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/>
</direct_connection>
<tile_annotations>
<global_port name="clk" tile_port="clb.clk" is_clock="true" default_val="0"/>
<global_port name="reset" tile_port="clb.reset" is_reset="true" default_val="1"/>
<global_port name="clk" is_clock="true" default_val="0">
<tile name="clb" port="clk" x="-1" y="-1"/>
</global_port>
<global_port name="Reset" is_reset="true" default_val="1">
<tile name="clb" port="reset" x="-1" y="-1"/>
</global_port>
</tile_annotations>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->

View File

@ -288,8 +288,12 @@
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/>
</direct_connection>
<tile_annotations>
<global_port name="clk" tile_port="clb.clk" is_clock="true" default_val="0"/>
<global_port name="Reset" tile_port="clb.reset" is_reset="true" default_val="1"/>
<global_port name="clk" is_clock="true" default_val="0">
<tile name="clb" port="clk" x="-1" y="-1"/>
</global_port>
<global_port name="Reset" is_reset="true" default_val="1">
<tile name="clb" port="reset" x="-1" y="-1"/>
</global_port>
</tile_annotations>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->

View File

@ -229,8 +229,12 @@
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/>
</direct_connection>
<tile_annotations>
<global_port name="clk" tile_port="clb.clk" is_clock="true" default_val="0"/>
<global_port name="Reset" tile_port="clb.reset" is_reset="true" default_val="1"/>
<global_port name="clk" is_clock="true" default_val="0">
<tile name="clb" port="clk" x="-1" y="-1"/>
</global_port>
<global_port name="Reset" is_reset="true" default_val="1">
<tile name="clb" port="reset" x="-1" y="-1"/>
</global_port>
</tile_annotations>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->

View File

@ -228,7 +228,9 @@
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/>
</direct_connection>
<tile_annotations>
<global_port name="clk" tile_port="clb.clk" is_clock="true" default_val="0"/>
<global_port name="clk" is_clock="true" default_val="0">
<tile name="clb" port="clk" x="-1" y="-1"/>
</global_port>
</tile_annotations>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->

View File

@ -214,7 +214,9 @@
<direct name="adder_carry" circuit_model_name="direct_interc"/>
</direct_connection>
<tile_annotations>
<global_port name="clk" tile_port="SUPER_LOGIC_CELL.QCK" is_clock="true" default_val="0"/>
<global_port name="clk" is_clock="true" default_val="0">
<tile name="SUPER_LOGIC_CELL" port="QCK" x="-1" y="-1"/>
</global_port>
</tile_annotations>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->

View File

@ -0,0 +1,596 @@
<!--
Low-cost homogeneous FPGA Architecture.
- Skywater 130 nm technology
- General purpose logic block:
K = 4, N = 8, fracturable 4 LUTs (can operate as one 4-LUT or two 3-LUTs with all 3 inputs shared)
with optionally registered outputs
- Routing architecture:
- 10% L = 1, fc_in = 0.15, Fc_out = 0.10
- 10% L = 2, fc_in = 0.15, Fc_out = 0.10
- 80% L = 4, fc_in = 0.15, Fc_out = 0.10
- 100 routing tracks per channel
Authors: Xifan Tang
-->
<architecture>
<!--
ODIN II specific config begins
Describes the types of user-specified netlist blocks (in blif, this corresponds to
".model [type_of_block]") that this architecture supports.
Note: Basic LUTs, I/Os, and flip-flops are not included here as there are
already special structures in blif (.names, .input, .output, and .latch)
that describe them.
-->
<models>
<!-- A virtual model for I/O to be used in the physical mode of io block -->
<model name="io">
<input_ports>
<port name="outpad"/>
</input_ports>
<output_ports>
<port name="inpad"/>
</output_ports>
</model>
<model name="frac_lut4">
<input_ports>
<port name="in"/>
</input_ports>
<output_ports>
<port name="lut2_out"/>
<port name="lut4_out"/>
</output_ports>
</model>
<model name="carry_follower">
<input_ports>
<port name="a"/>
<port name="b"/>
<port name="cin"/>
</input_ports>
<output_ports>
<port name="cout"/>
</output_ports>
</model>
<!-- A virtual model for scan-chain flip-flop to be used in the physical mode of FF -->
<model name="scff">
<input_ports>
<port name="D" clock="clk"/>
<port name="DI" clock="clk"/>
<port name="reset" clock="clk"/>
<port name="clk" is_clock="1"/>
</input_ports>
<output_ports>
<port name="Q" clock="clk"/>
</output_ports>
</model>
</models>
<tiles>
<!-- Do NOT add clock pins to I/O here!!! VPR does not build clock network in the way that OpenFPGA can support
If you need to register the I/O, define clocks in the circuit models
These clocks can be handled in back-end
-->
<!-- Top-side has 1 I/O per tile -->
<tile name="io_top" capacity="16" area="0">
<equivalent_sites>
<site pb_type="io"/>
</equivalent_sites>
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
<pinlocations pattern="custom">
<loc side="bottom">io_top.outpad io_top.inpad</loc>
</pinlocations>
</tile>
<!-- Right-side has 1 I/O per tile -->
<tile name="io_right" capacity="16" area="0">
<equivalent_sites>
<site pb_type="io"/>
</equivalent_sites>
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
<pinlocations pattern="custom">
<loc side="left">io_right.outpad io_right.inpad</loc>
</pinlocations>
</tile>
<!-- Bottom-side has 9 I/O per tile -->
<tile name="io_bottom" capacity="16" area="0">
<equivalent_sites>
<site pb_type="io"/>
</equivalent_sites>
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
<pinlocations pattern="custom">
<loc side="top">io_bottom.outpad io_bottom.inpad</loc>
</pinlocations>
</tile>
<!-- Left-side has 1 I/O per tile -->
<tile name="io_left" capacity="16" area="0">
<equivalent_sites>
<site pb_type="io"/>
</equivalent_sites>
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
<pinlocations pattern="custom">
<loc side="right">io_left.outpad io_left.inpad</loc>
</pinlocations>
</tile>
<!-- CLB has most pins on the top and right sides -->
<tile name="clb" area="53894">
<equivalent_sites>
<site pb_type="clb"/>
</equivalent_sites>
<input name="I" num_pins="24" equivalent="full"/>
<input name="reg_in" num_pins="1"/>
<input name="sc_in" num_pins="1"/>
<input name="cin" num_pins="1"/>
<input name="reset" num_pins="1" is_non_clock_global="true"/>
<output name="O" num_pins="8" equivalent="none"/>
<output name="reg_out" num_pins="1"/>
<output name="sc_out" num_pins="1"/>
<output name="cout" num_pins="1"/>
<output name="cout_copy" num_pins="1"/>
<clock name="clk" num_pins="4"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10">
<fc_override port_name="reg_in" fc_type="frac" fc_val="0"/>
<fc_override port_name="reg_out" fc_type="frac" fc_val="0"/>
<fc_override port_name="sc_in" fc_type="frac" fc_val="0"/>
<fc_override port_name="sc_out" fc_type="frac" fc_val="0"/>
<fc_override port_name="cin" fc_type="frac" fc_val="0"/>
<fc_override port_name="cout" fc_type="frac" fc_val="0"/>
<fc_override port_name="clk" fc_type="frac" fc_val="0"/>
<fc_override port_name="reset" fc_type="frac" fc_val="0"/>
</fc>
<!--pinlocations pattern="spread"/-->
<pinlocations pattern="custom">
<loc side="left">clb.clk clb.reset</loc>
<loc side="top">clb.reg_in clb.sc_in clb.cin clb.O[7:0] clb.I[11:0]</loc>
<loc side="right">clb.I[23:12]</loc>
<loc side="bottom">clb.reg_out clb.sc_out clb.cout clb.cout_copy</loc>
</pinlocations>
</tile>
</tiles>
<!-- ODIN II specific config ends -->
<!-- Physical descriptions begin -->
<layout tileable="true">
<auto_layout aspect_ratio="1.0">
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
<row type="io_top" starty="H-1" priority="100"/>
<row type="io_bottom" starty="0" priority="100"/>
<col type="io_left" startx="0" priority="100"/>
<col type="io_right" startx="W-1" priority="100"/>
<corners type="EMPTY" priority="101"/>
<!--Fill with 'clb'-->
<fill type="clb" priority="10"/>
</auto_layout>
<fixed_layout name="2x2" width="4" height="4">
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
<row type="io_top" starty="H-1" priority="100"/>
<row type="io_bottom" starty="0" priority="100"/>
<col type="io_left" startx="0" priority="100"/>
<col type="io_right" startx="W-1" priority="100"/>
<corners type="EMPTY" priority="101"/>
<!--Fill with 'clb'-->
<fill type="clb" priority="10"/>
</fixed_layout>
<fixed_layout name="12x12" width="14" height="14">
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
<row type="io_top" starty="H-1" priority="100"/>
<row type="io_bottom" starty="0" priority="100"/>
<col type="io_left" startx="0" priority="100"/>
<col type="io_right" startx="W-1" priority="100"/>
<corners type="EMPTY" priority="101"/>
<!--Fill with 'clb'-->
<fill type="clb" priority="10"/>
</fixed_layout>
<fixed_layout name="32x32" width="34" height="34">
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
<row type="io_top" starty="H-1" priority="100"/>
<row type="io_bottom" starty="0" priority="100"/>
<col type="io_left" startx="0" priority="100"/>
<col type="io_right" startx="W-1" priority="100"/>
<corners type="EMPTY" priority="101"/>
<!--Fill with 'clb'-->
<fill type="clb" priority="10"/>
</fixed_layout>
</layout>
<device>
<!-- VB & JL: Using Ian Kuon's transistor sizing and drive strength data for routing, at 40 nm. Ian used BPTM
models. We are modifying the delay values however, to include metal C and R, which allows more architecture
experimentation. We are also modifying the relative resistance of PMOS to be 1.8x that of NMOS
(vs. Ian's 3x) as 1.8x lines up with Jeff G's data from a 45 nm process (and is more typical of
45 nm in general). I'm upping the Rmin_nmos from Ian's just over 6k to nearly 9k, and dropping
RminW_pmos from 18k to 16k to hit this 1.8x ratio, while keeping the delays of buffers approximately
lined up with Stratix IV.
We are using Jeff G.'s capacitance data for 45 nm (in tech/ptm_45nm).
Jeff's tables list C in for transistors with widths in multiples of the minimum feature size (45 nm).
The minimum contactable transistor is 2.5 * 45 nm, so I need to multiply drive strength sizes in this file
by 2.5x when looking up in Jeff's tables.
The delay values are lined up with Stratix IV, which has an architecture similar to this
proposed FPGA, and which is also 40 nm
C_ipin_cblock: input capacitance of a track buffer, which VPR assumes is a single-stage
4x minimum drive strength buffer. -->
<sizing R_minW_nmos="8926" R_minW_pmos="16067"/>
<!-- The grid_logic_tile_area below will be used for all blocks that do not explicitly set their own (non-routing)
area; set to 0 since we explicitly set the area of all blocks currently in this architecture file.
-->
<area grid_logic_tile_area="0"/>
<chan_width_distr>
<x distr="uniform" peak="1.000000"/>
<y distr="uniform" peak="1.000000"/>
</chan_width_distr>
<switch_block type="wilton" fs="3" sub_type="subset" sub_fs="3"/>
<connection_block input_switch_name="ipin_cblock"/>
</device>
<switchlist>
<!-- VB: the mux_trans_size and buf_size data below is in minimum width transistor *areas*, assuming the purple
book area formula. This means the mux transistors are about 5x minimum drive strength.
We assume the first stage of the buffer is 3x min drive strength to be reasonable given the large
mux transistors, and this gives a reasonable stage ratio of a bit over 5x to the second stage. We assume
the n and p transistors in the first stage are equal-sized to lower the buffer trip point, since it's fed
by a pass transistor mux. We can then reverse engineer the buffer second stage to hit the specified
buf_size (really buffer area) - 16.2x minimum drive nmos and 1.8*16.2 = 29.2x minimum drive.
I then took the data from Jeff G.'s PTM modeling of 45 nm to get the Cin (gate of first stage) and Cout
(diff of second stage) listed below. Jeff's models are in tech/ptm_45nm, and are in min feature multiples.
The minimum contactable transistor is 2.5 * 45 nm, so I need to multiply the drive strength sizes above by
2.5x when looking up in Jeff's tables.
Finally, we choose a switch delay (58 ps) that leads to length 4 wires having a delay equal to that of SIV of 126 ps.
This also leads to the switch being 46% of the total wire delay, which is reasonable. -->
<switch type="mux" name="L1_mux" R="551" Cin=".77e-15" Cout="4e-15" Tdel="58e-12" mux_trans_size="2.630740" buf_size="27.645901"/>
<switch type="mux" name="L2_mux" R="551" Cin=".77e-15" Cout="4e-15" Tdel="58e-12" mux_trans_size="2.630740" buf_size="27.645901"/>
<switch type="mux" name="L4_mux" R="551" Cin=".77e-15" Cout="4e-15" Tdel="58e-12" mux_trans_size="2.630740" buf_size="27.645901"/>
<!--switch ipin_cblock resistance set to yeild for 4x minimum drive strength buffer-->
<switch type="mux" name="ipin_cblock" R="2231.5" Cout="0." Cin="1.47e-15" Tdel="7.247000e-11" mux_trans_size="1.222260" buf_size="auto"/>
</switchlist>
<segmentlist>
<!--- VB & JL: using ITRS metal stack data, 96 nm half pitch wires, which are intermediate metal width/space.
With the 96 nm half pitch, such wires would take 60 um of height, vs. a 90 nm high (approximated as square) Stratix IV tile so this seems
reasonable. Using a tile length of 90 nm, corresponding to the length of a Stratix IV tile if it were square. -->
<!-- GIVE a specific name for the segment! OpenFPGA appreciate that! -->
<segment name="L1" freq="0.20" length="1" type="unidir" Rmetal="101" Cmetal="22.5e-15">
<mux name="L1_mux"/>
<sb type="pattern">1 1</sb>
<cb type="pattern">1</cb>
</segment>
<segment name="L2" freq="0.10" length="2" type="unidir" Rmetal="101" Cmetal="22.5e-15">
<mux name="L2_mux"/>
<sb type="pattern">1 1 1</sb>
<cb type="pattern">1 1</cb>
</segment>
<segment name="L4" freq="0.70" length="4" type="unidir" Rmetal="101" Cmetal="22.5e-15">
<mux name="L4_mux"/>
<sb type="pattern">1 1 1 1 1</sb>
<cb type="pattern">1 1 1 1</cb>
</segment>
</segmentlist>
<directlist>
<direct name="carry_chain" from_pin="clb.cout" to_pin="clb.cin" x_offset="0" y_offset="-1" z_offset="0"/>
<direct name="shift_register" from_pin="clb.reg_out" to_pin="clb.reg_in" x_offset="0" y_offset="-1" z_offset="0"/>
<direct name="scan_chain" from_pin="clb.sc_out" to_pin="clb.sc_in" x_offset="0" y_offset="-1" z_offset="0"/>
</directlist>
<complexblocklist>
<!-- Define input pads begin -->
<pb_type name="io">
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
<!-- Do NOT add clock pins to I/O here!!! VPR does not build clock network in the way that OpenFPGA can support
If you need to register the I/O, define clocks in the circuit models
These clocks can be handled in back-end
-->
<!-- A mode denotes the physical implementation of an I/O
This mode will be not packable but is mainly used for fabric verilog generation
-->
<mode name="physical" disabled_in_pack="true">
<pb_type name="iopad" blif_model=".subckt io" num_pb="1">
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
</pb_type>
<interconnect>
<direct name="outpad" input="io.outpad" output="iopad.outpad">
<delay_constant max="1.394e-11" in_port="io.outpad" out_port="iopad.outpad"/>
</direct>
<direct name="inpad" input="iopad.inpad" output="io.inpad">
<delay_constant max="4.243e-11" in_port="iopad.inpad" out_port="io.inpad"/>
</direct>
</interconnect>
</mode>
<!-- IOs can operate as either inputs or outputs.
Delays below come from Ian Kuon. They are small, so they should be interpreted as
the delays to and from registers in the I/O (and generally I/Os are registered
today and that is when you timing analyze them.
-->
<mode name="inpad">
<pb_type name="inpad" blif_model=".input" num_pb="1">
<output name="inpad" num_pins="1"/>
</pb_type>
<interconnect>
<direct name="inpad" input="inpad.inpad" output="io.inpad">
<delay_constant max="4.243e-11" in_port="inpad.inpad" out_port="io.inpad"/>
</direct>
</interconnect>
</mode>
<mode name="outpad">
<pb_type name="outpad" blif_model=".output" num_pb="1">
<input name="outpad" num_pins="1"/>
</pb_type>
<interconnect>
<direct name="outpad" input="io.outpad" output="outpad.outpad">
<delay_constant max="1.394e-11" in_port="io.outpad" out_port="outpad.outpad"/>
</direct>
</interconnect>
</mode>
<power method="ignore"/>
</pb_type>
<!-- Define I/O pads ends -->
<!-- Define general purpose logic block (CLB) begin -->
<!-- -Due to the absence of local routing,
the 4 inputs of fracturable LUT4 are no longer equivalent,
because the 4th input can not be switched when the dual-LUT3 modes are used.
So pin equivalence should be applied to the first 3 inputs only
-->
<pb_type name="clb">
<input name="I" num_pins="24" equivalent="full"/>
<input name="reg_in" num_pins="1"/>
<input name="sc_in" num_pins="1"/>
<input name="cin" num_pins="1"/>
<input name="reset" num_pins="1" is_non_clock_global="true"/>
<output name="O" num_pins="8" equivalent="none"/>
<output name="reg_out" num_pins="1"/>
<output name="sc_out" num_pins="1"/>
<output name="cout" num_pins="1"/>
<output name="cout_copy" num_pins="1"/>
<clock name="clk" num_pins="4"/>
<!-- Describe fracturable logic element.
Each fracturable logic element has a 6-LUT that can alternatively operate as two 5-LUTs with shared inputs.
The outputs of the fracturable logic element can be optionally registered
-->
<pb_type name="fle" num_pb="8">
<input name="in" num_pins="4"/>
<input name="reg_in" num_pins="1"/>
<input name="sc_in" num_pins="1"/>
<input name="cin" num_pins="1"/>
<input name="reset" num_pins="1"/>
<output name="out" num_pins="1"/>
<output name="reg_out" num_pins="1"/>
<output name="sc_out" num_pins="1"/>
<output name="cout" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<!-- Physical mode definition begin (physical implementation of the fle) -->
<mode name="physical" disabled_in_pack="true">
<pb_type name="fabric" num_pb="1">
<input name="in" num_pins="4"/>
<input name="reg_in" num_pins="1"/>
<input name="sc_in" num_pins="1"/>
<input name="cin" num_pins="1"/>
<input name="reset" num_pins="1"/>
<output name="out" num_pins="1"/>
<output name="reg_out" num_pins="1"/>
<output name="sc_out" num_pins="1"/>
<output name="cout" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<pb_type name="frac_logic" num_pb="1">
<input name="in" num_pins="4"/>
<input name="cin" num_pins="1"/>
<output name="out" num_pins="1"/>
<output name="cout" num_pins="1"/>
<!-- Define LUT -->
<pb_type name="frac_lut4" blif_model=".subckt frac_lut4" num_pb="1">
<input name="in" num_pins="4"/>
<output name="lut2_out" num_pins="2"/>
<output name="lut4_out" num_pins="1"/>
</pb_type>
<pb_type name="carry_follower" blif_model=".subckt carry_follower" num_pb="1">
<input name="a" num_pins="1"/>
<input name="b" num_pins="1"/>
<input name="cin" num_pins="1"/>
<output name="cout" num_pins="1"/>
</pb_type>
<interconnect>
<direct name="direct1" input="frac_logic.in[0:1]" output="frac_lut4.in[0:1]"/>
<direct name="direct2" input="frac_logic.in[3:3]" output="frac_lut4.in[3:3]"/>
<direct name="direct3" input="frac_logic.cin" output="carry_follower.b"/>
<direct name="direct4" input="frac_lut4.lut2_out[1:1]" output="carry_follower.a"/>
<direct name="direct5" input="frac_lut4.lut2_out[0:0]" output="carry_follower.cin"/>
<direct name="direct6" input="carry_follower.cout" output="frac_logic.cout"/>
<!-- Xifan Tang: I use out[0] because the output of lut6 in lut6 mode is wired to the out[0] -->
<direct name="direct7" input="frac_lut4.lut4_out" output="frac_logic.out"/>
<mux name="mux2" input="frac_logic.cin frac_logic.in[2:2]" output="frac_lut4.in[2:2]"/>
</interconnect>
</pb_type>
<!-- Define flip-flop with scan-chain capability, DI is the scan-chain data input -->
<pb_type name="ff" blif_model=".subckt scff" num_pb="1">
<input name="D" num_pins="1"/>
<input name="DI" num_pins="1"/>
<input name="reset" num_pins="1"/>
<output name="Q" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<T_setup value="66e-12" port="ff.D" clock="clk"/>
<T_setup value="66e-12" port="ff.DI" clock="clk"/>
<T_setup value="66e-12" port="ff.reset" clock="clk"/>
<T_clock_to_Q max="124e-12" port="ff.Q" clock="clk"/>
</pb_type>
<interconnect>
<direct name="direct1" input="fabric.in" output="frac_logic.in"/>
<direct name="direct2" input="fabric.sc_in" output="ff.DI"/>
<direct name="direct3" input="fabric.cin" output="frac_logic.cin"/>
<direct name="direct4" input="ff.Q" output="fabric.sc_out"/>
<direct name="direct5" input="ff.Q" output="fabric.reg_out"/>
<direct name="direct6" input="frac_logic.cout" output="fabric.cout"/>
<complete name="complete1" input="fabric.clk" output="ff.clk"/>
<complete name="complete2" input="fabric.reset" output="ff.reset"/>
<mux name="mux1" input="frac_logic.out fabric.reg_in" output="ff.D">
<delay_constant max="25e-12" in_port="frac_logic.out" out_port="ff.D"/>
<delay_constant max="45e-12" in_port="fabric.reg_in" out_port="ff.D"/>
</mux>
<mux name="mux2" input="ff.Q frac_logic.out" output="fabric.out">
<!-- LUT to output is faster than FF to output on a Stratix IV -->
<delay_constant max="25e-12" in_port="frac_logic.out" out_port="fabric.out"/>
<delay_constant max="45e-12" in_port="ff.Q" out_port="fabric.out"/>
</mux>
</interconnect>
</pb_type>
<interconnect>
<direct name="direct1" input="fle.in" output="fabric.in"/>
<direct name="direct2" input="fle.reg_in" output="fabric.reg_in"/>
<direct name="direct3" input="fle.sc_in" output="fabric.sc_in"/>
<direct name="direct4" input="fle.cin" output="fabric.cin"/>
<direct name="direct5" input="fabric.out" output="fle.out"/>
<direct name="direct6" input="fabric.reg_out" output="fle.reg_out"/>
<direct name="direct7" input="fabric.sc_out" output="fle.sc_out"/>
<direct name="direct8" input="fabric.cout" output="fle.cout"/>
<direct name="direct9" input="fle.clk" output="fabric.clk"/>
<direct name="direct10" input="fle.reset" output="fabric.reset"/>
</interconnect>
</mode>
<!-- Physical mode definition end (physical implementation of the fle) -->
<mode name="n1_lut4">
<!-- Define 4-LUT mode -->
<pb_type name="ble4" num_pb="1">
<input name="in" num_pins="4"/>
<output name="out" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<!-- Define LUT -->
<pb_type name="lut4" blif_model=".names" num_pb="1" class="lut">
<input name="in" num_pins="4" port_class="lut_in"/>
<output name="out" num_pins="1" port_class="lut_out"/>
<!-- LUT timing using delay matrix -->
<!-- These are the physical delay inputs on a Stratix IV LUT but because VPR cannot do LUT rebalancing,
we instead take the average of these numbers to get more stable results
82e-12
173e-12
261e-12
263e-12
398e-12
397e-12
-->
<delay_matrix type="max" in_port="lut4.in" out_port="lut4.out">
261e-12
261e-12
261e-12
261e-12
</delay_matrix>
</pb_type>
<!-- Define flip-flop -->
<pb_type name="ff" blif_model=".latch" num_pb="1" class="flipflop">
<input name="D" num_pins="1" port_class="D"/>
<output name="Q" num_pins="1" port_class="Q"/>
<clock name="clk" num_pins="1" port_class="clock"/>
<T_setup value="66e-12" port="ff.D" clock="clk"/>
<T_clock_to_Q max="124e-12" port="ff.Q" clock="clk"/>
</pb_type>
<interconnect>
<direct name="direct1" input="ble4.in" output="lut4[0:0].in"/>
<direct name="direct2" input="lut4.out" output="ff.D">
<!-- Advanced user option that tells CAD tool to find LUT+FF pairs in netlist -->
<pack_pattern name="ble4" in_port="lut4.out" out_port="ff.D"/>
</direct>
<direct name="direct3" input="ble4.clk" output="ff.clk"/>
<mux name="mux1" input="ff.Q lut4.out" output="ble4.out">
<!-- LUT to output is faster than FF to output on a Stratix IV -->
<delay_constant max="25e-12" in_port="lut4.out" out_port="ble4.out"/>
<delay_constant max="45e-12" in_port="ff.Q" out_port="ble4.out"/>
</mux>
</interconnect>
</pb_type>
<interconnect>
<direct name="direct1" input="fle.in" output="ble4.in"/>
<direct name="direct2" input="ble4.out" output="fle.out"/>
<direct name="direct3" input="fle.clk" output="ble4.clk"/>
</interconnect>
</mode>
<!-- 4-LUT mode definition end -->
<!-- Define shift register begin -->
<mode name="shift_register" disable_packing="true">
<pb_type name="shift_reg" num_pb="1">
<input name="reg_in" num_pins="1"/>
<output name="ff_out" num_pins="1"/>
<output name="reg_out" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<pb_type name="ff" blif_model=".latch" num_pb="1" class="flipflop">
<input name="D" num_pins="1" port_class="D"/>
<output name="Q" num_pins="1" port_class="Q"/>
<clock name="clk" num_pins="1" port_class="clock"/>
<T_setup value="66e-12" port="ff.D" clock="clk"/>
<T_clock_to_Q max="124e-12" port="ff.Q" clock="clk"/>
</pb_type>
<interconnect>
<direct name="direct1" input="shift_reg.reg_in" output="ff.D"/>
<direct name="direct2" input="ff.Q" output="shift_reg.reg_out"/>
<direct name="direct3" input="ff.Q" output="shift_reg.ff_out"/>
<complete name="complete1" input="shift_reg.clk" output="ff.clk"/>
</interconnect>
</pb_type>
<interconnect>
<direct name="direct1" input="fle.reg_in" output="shift_reg.reg_in"/>
<direct name="direct2" input="shift_reg.reg_out" output="fle.reg_out"/>
<direct name="direct3" input="shift_reg.ff_out" output="fle.out"/>
<direct name="direct4" input="fle.clk" output="shift_reg.clk"/>
</interconnect>
</mode>
<!-- Define shift register end -->
</pb_type>
<interconnect>
<!-- We use direct connections to reduce the area to the most
The global local routing is going to compensate the loss in routability
-->
<!-- FIXME: The implicit port definition results in I0[0] connected to
in[2]. Such twisted connection is not expected.
I[0] should be connected to in[0]
-->
<complete name="crossbar" input="clb.I fle[7:0].out" output="fle[7:0].in">
<!-- TODO: Timing should be backannotated from post-PnR results -->
</complete>
<complete name="clks" input="clb.clk" output="fle[7:0].clk">
</complete>
<complete name="resets" input="clb.reset" output="fle[7:0].reset">
</complete>
<!-- This way of specifying direct connection to clb outputs is important because this architecture uses automatic spreading of opins.
By grouping to output pins in this fashion, if a logic block is completely filled by 6-LUTs,
then the outputs those 6-LUTs take get evenly distributed across all four sides of the CLB instead of clumped on two sides (which is what happens with a more
naive specification).
-->
<direct name="clbouts1" input="fle[3:0].out" output="clb.O[3:0]"/>
<direct name="clbouts2" input="fle[7:4].out" output="clb.O[7:4]"/>
<direct name="cout_copy" input="fle[7:7].cout" output="clb.cout_copy"/>
<!-- Shift register chain links -->
<direct name="shift_register_in" input="clb.reg_in" output="fle[0:0].reg_in">
<!-- Put all inter-block carry chain delay on this one edge -->
<delay_constant max="0.16e-9" in_port="clb.reg_in" out_port="fle[0:0].reg_in"/>
<!--pack_pattern name="chain" in_port="clb.reg_in" out_port="fle[0:0].reg_in"/-->
</direct>
<direct name="shift_register_out" input="fle[7:7].reg_out" output="clb.reg_out">
<!--pack_pattern name="chain" in_port="fle[7:7].reg_out" out_port="clb.reg_out"/-->
</direct>
<direct name="shift_register_link" input="fle[6:0].reg_out" output="fle[7:1].reg_in">
<!--pack_pattern name="chain" in_port="fle[6:0].reg_out" out_port="fle[7:1].reg_in"/-->
</direct>
<!-- Scan chain links -->
<direct name="scan_chain_in" input="clb.sc_in" output="fle[0:0].sc_in">
<!-- Put all inter-block carry chain delay on this one edge -->
<delay_constant max="0.16e-9" in_port="clb.sc_in" out_port="fle[0:0].sc_in"/>
</direct>
<direct name="scan_chain_out" input="fle[7:7].sc_out" output="clb.sc_out">
</direct>
<direct name="scan_chain_link" input="fle[6:0].sc_out" output="fle[7:1].sc_in">
</direct>
<!-- Carry chain links -->
<direct name="carry_chain_in" input="clb.cin" output="fle[0:0].cin">
<!-- Put all inter-block carry chain delay on this one edge -->
<delay_constant max="0.16e-9" in_port="clb.cin" out_port="fle[0:0].cin"/>
</direct>
<direct name="carry_chain_out" input="fle[7:7].cout" output="clb.cout">
</direct>
<direct name="carry_chain_link" input="fle[6:0].cout" output="fle[7:1].cin">
</direct>
</interconnect>
<!-- Every input pin is driven by 15% of the tracks in a channel, every output pin is driven by 10% of the tracks in a channel -->
<!-- Place this general purpose logic block in any unspecified column -->
</pb_type>
<!-- Define general purpose logic block (CLB) ends -->
</complexblocklist>
</architecture>

View File

@ -437,10 +437,12 @@
</pb_type>
<interconnect>
<direct name="direct1" input="fabric.in" output="frac_logic.in"/>
<direct name="direct2" input="fabric.sc_in" output="ff[0].DI"/>
<direct name="direct3" input="ff[0].Q" output="ff[1].DI"/>
<direct name="direct4" input="ff[1].Q" output="fabric.sc_out"/>
<direct name="direct5" input="ff[1].Q" output="fabric.reg_out"/>
<direct name="direct2" input="fabric.cin" output="frac_logic.cin"/>
<direct name="direct3" input="fabric.sc_in" output="ff[0].DI"/>
<direct name="direct4" input="ff[0].Q" output="ff[1].DI"/>
<direct name="direct5" input="ff[1].Q" output="fabric.sc_out"/>
<direct name="direct6" input="ff[1].Q" output="fabric.reg_out"/>
<direct name="direct7" input="frac_logic.cout" output="fabric.cout"/>
<complete name="complete1" input="fabric.clk" output="ff[1:0].clk"/>
<complete name="complete2" input="fabric.reset" output="ff[1:0].reset"/>
<mux name="mux1" input="frac_logic.out[0:0] fabric.reg_in" output="ff[0:0].D">

View File

@ -429,10 +429,12 @@
</pb_type>
<interconnect>
<direct name="direct1" input="fabric.in" output="frac_logic.in"/>
<direct name="direct2" input="fabric.sc_in" output="ff[0].DI"/>
<direct name="direct3" input="ff[0].Q" output="ff[1].DI"/>
<direct name="direct4" input="ff[1].Q" output="fabric.sc_out"/>
<direct name="direct5" input="ff[1].Q" output="fabric.reg_out"/>
<direct name="direct2" input="fabric.cin" output="frac_logic.cin"/>
<direct name="direct3" input="fabric.sc_in" output="ff[0].DI"/>
<direct name="direct4" input="ff[0].Q" output="ff[1].DI"/>
<direct name="direct5" input="ff[1].Q" output="fabric.sc_out"/>
<direct name="direct6" input="ff[1].Q" output="fabric.reg_out"/>
<direct name="direct7" input="frac_logic.cout" output="fabric.cout"/>
<complete name="complete1" input="fabric.clk" output="ff[1:0].clk"/>
<mux name="mux1" input="frac_logic.out[0:0] fabric.reg_in" output="ff[0:0].D">
<delay_constant max="25e-12" in_port="frac_logic.out[0:0]" out_port="ff[0:0].D"/>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,225 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Team: Virginia Tech Secure Embedded Systems (SES) Lab
// Implementer: Ege Gulcan
//
// Create Date: 17:21:26 11/13/2013
// Design Name:
// Module Name: simon_datapath_shiftreg
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module simon_datapath_shiftreg(clk,data_in,data_rdy,key_in,cipher_out,round_counter,bit_counter);
input clk,data_in,key_in;
input [1:0] data_rdy;
input round_counter;
output cipher_out;
output [5:0] bit_counter;
reg [55:0] shifter1;
reg [63:0] shifter2;
reg shift_in1,shift_in2;
wire shift_out1,shift_out2;
reg shifter_enable1,shifter_enable2;
reg fifo_ff63,fifo_ff62,fifo_ff61,fifo_ff60,fifo_ff59,fifo_ff58,fifo_ff57,fifo_ff56;
reg lut_ff63,lut_ff62,lut_ff61,lut_ff60,lut_ff59,lut_ff58,lut_ff57,lut_ff56;
reg lut_ff_input,fifo_ff_input;
reg lut_rol1,lut_rol2,lut_rol8;
reg s1,s4,s5,s6,s7;
reg [1:0] s3;
reg [5:0] bit_counter;
wire lut_out;
// Shift Register1 FIFO 56x1 Begin
// 56x1 Shift register to store the upper word
always @(posedge clk)
begin
if(shifter_enable1)
begin
shifter1 <= {shift_in1, shifter1[55:1]};
end
end
assign shift_out1 = shifter1[0];
// Shift Register1 End
// Shift Register2 FIFO 64x1 Begin
// 64x1 Shift register to store the lower word
always @(posedge clk)
begin
if(shifter_enable2)
begin
shifter2 <= {shift_in2, shifter2[63:1]};
end
end
assign shift_out2 = shifter2[0];
// Shift Register2 End
// 8 Flip-Flops to store the most significant 8 bits of the upper word at even rounds
// Denoted as Shift Register Up (SRU) in Figure 5
always@(posedge clk)
begin
if(shifter_enable1)
begin
fifo_ff63 <= fifo_ff_input;
fifo_ff62 <= fifo_ff63;
fifo_ff61 <= fifo_ff62;
fifo_ff60 <= fifo_ff61;
fifo_ff59 <= fifo_ff60;
fifo_ff58 <= fifo_ff59;
fifo_ff57 <= fifo_ff58;
fifo_ff56 <= fifo_ff57;
end
end
// 8 Flip-Flops to store the most significant 8 bits of the upper word at odd rounds
// Denoted as Shift Register Down (SRD) in Figure 5
always@(posedge clk)
begin
lut_ff63 <= lut_ff_input;
lut_ff62 <= lut_ff63;
lut_ff61 <= lut_ff62;
lut_ff60 <= lut_ff61;
lut_ff59 <= lut_ff60;
lut_ff58 <= lut_ff59;
lut_ff57 <= lut_ff58;
lut_ff56 <= lut_ff57;
end
// FIFO 64x1 Input MUX
// Input of the lower FIFO is always the output of the upper FIFO
always@(*)
begin
shift_in2 = shift_out1;
end
// FIFO 56x1 Input MUX
// Input of the upper FIFO depends on the select line S1
always@(*)
begin
if(s1==0)
shift_in1 = lut_ff56;
else
shift_in1 = fifo_ff56;
end
// FIFO FF Input MUX
// The input of FIFO_FF can be the input plaintext, output of 56x1 FIFO or the output of LUT
always@(*)
begin
if(s3==0)
fifo_ff_input = data_in;
else if(s3==1)
fifo_ff_input = shift_out1;
else if(s3==2)
fifo_ff_input = lut_out;
else
fifo_ff_input = 1'bx; // Debugging
end
// LUT FF Input MUX
// The input of the LUT_FF is either the output of 56x1 FIFO or the output of LUT
always@(*)
begin
if(s5==0)
lut_ff_input = shift_out1;
else
lut_ff_input = lut_out;
end
// LUT Input MUX
always@(*)
begin
if(s7==0)
lut_rol1 = fifo_ff63;
else
lut_rol1 = lut_ff63;
if(s4==0)
lut_rol2 = fifo_ff62;
else
lut_rol2 = lut_ff62;
if(s6==0)
lut_rol8 = fifo_ff56;
else
lut_rol8 = lut_ff56;
end
//Selection MUX
always@(*)
begin
// For the first 8 bits of each even round OR for all the bits after the first 8 bits in odd rounds OR loading the plaintext
if((round_counter==0 && bit_counter<8)||(round_counter==1 && bit_counter>7)||(data_rdy==1))
s1 = 1;
else
s1 = 0;
if(data_rdy==1) // Loading plaintext
s3 = 0;
else if(round_counter==0) // Even rounds
s3 = 1;
else if(round_counter==1) // Odd rounds
s3 = 2;
else
s3 = 1'bx; // For debugging
if(round_counter==0) // Even rounds
s6 = 0;
else
s6 = 1;
s4 = s6;
s7 = s6;
s5 = ~s6;
end
// SHIFTER ENABLES
// Two shift registers are enabled when the plaintext is being loaded (1) or when the block cipher is running (3)
always@(*)
begin
if(data_rdy==1 || data_rdy==3)
begin
shifter_enable1 = 1;
shifter_enable2 = 1;
end
else
begin
shifter_enable1 = 0;
shifter_enable2 = 0;
end
end
// The bit_counter value is incremented in each clock cycle when the block cipher is running
always@(posedge clk)
begin
if(data_rdy==0)
bit_counter <= 0;
else if(data_rdy==3)
bit_counter <= bit_counter + 1;
else
bit_counter <= bit_counter;
end
// The new computed value
assign lut_out = (lut_rol1 & lut_rol8) ^ shift_out2 ^ lut_rol2 ^ key_in;
// The global output that gives the ciphertext value
assign cipher_out = lut_out;
endmodule

View File

@ -0,0 +1,241 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Team: Virginia Tech Secure Embedded Systems (SES) Lab
// Implementer: Ege Gulcan
//
// Create Date: 16:55:06 11/12/2013
// Design Name:
// Module Name: simon_key_expansion_shiftreg
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module simon_key_expansion_shiftreg(clk,data_in,key_out,data_rdy,bit_counter,round_counter_out);
input clk;
input data_in;
input [1:0] data_rdy;
input [5:0] bit_counter;
output key_out;
output round_counter_out;
reg [59:0] shifter1;
reg [63:0] shifter2;
reg shift_in1,shift_in2;
wire shift_out1,shift_out2;
reg shifter_enable1,shifter_enable2;
reg lut_ff_enable,fifo_ff_enable;
wire lut_out;
reg lut_in3;
reg s2,s3;
reg [1:0] s1;
reg [6:0] round_counter;
reg z_value;
reg fifo_ff0,fifo_ff1,fifo_ff2,fifo_ff3;
//(* shreg_extract = "no" *)
reg lut_ff0,lut_ff1,lut_ff2,lut_ff3;
//Constant value Z ROM
reg [0:67] Z = 68'b10101111011100000011010010011000101000010001111110010110110011101011;
reg c;
/////////////////////////////////////////
//// BEGIN CODE ////////////////////////
///////////////////////////////////////
// Least bit of the round counter is sent to the datapath to check if it is even or odd
assign round_counter_out = round_counter[0];
// Shift Register1 FIFO 60x1 Begin
// 60x1 shift register storing the 60 most significant bits of the upper word of the key
always @(posedge clk)
begin
if(shifter_enable1)
begin
shifter1 <= {shift_in1, shifter1[59:1]};
end
end
assign shift_out1 = shifter1[0];
// Shift Register1 End
// Shift Register2 FIFO 64x1 Begin
// 64x1 shift register storing the lower word of the key
always @(posedge clk)
begin
if(shifter_enable2)
begin
shifter2 <= {shift_in2, shifter2[63:1]};
end
end
assign shift_out2 = shifter2[0];
// Shift Register2 End
// 4 flip-flops storing the least significant 4 bits of the upper word in the first round
always @(posedge clk)
begin
if(fifo_ff_enable)
begin
fifo_ff3 <= shift_out1;
fifo_ff2 <= fifo_ff3;
fifo_ff1 <= fifo_ff2;
fifo_ff0 <= fifo_ff1;
end
end
// 4 flip-flops storing the least significant 4 bits of the upper word after the first round
always@(posedge clk)
begin
if(lut_ff_enable)
begin
lut_ff3 <= lut_out;
lut_ff2 <= lut_ff3;
lut_ff1 <= lut_ff2;
lut_ff0 <= lut_ff1;
end
end
//FIFO 64x1 Input MUX
always@(*)
begin
if(data_rdy==2)
shift_in2 = fifo_ff0;
else if(data_rdy==3 && (round_counter<1 || bit_counter>3))
shift_in2 = fifo_ff0;
else if(data_rdy==3 && bit_counter<4 && round_counter>0)
shift_in2 = lut_ff0;
else
shift_in2 = 1'bx;
end
//LUT >>3 Input MUX
always@(*)
begin
if(s2==0)
lut_in3 = fifo_ff3;
else
lut_in3 = lut_ff3;
end
//FIFO 60x1 Input MUX
always@(*)
begin
if(s1==0)
shift_in1 = fifo_ff0;
else if(s1==1)
shift_in1 = data_in;
else if(s1==2)
shift_in1 = lut_out;
else if(s1==3)
shift_in1 = lut_ff0;
else
shift_in1 = 1'bx;
end
//S2 MUX
always@(*)
begin
if(bit_counter==0 && round_counter!=0)
s2 = 1;
else
s2 = 0;
end
//S1 MUX
always@(*)
begin
if(data_rdy==2)
s1 = 1;
else if(data_rdy==3 && bit_counter<4 && round_counter==0)
s1 = 0;
else if(data_rdy==3 && bit_counter<4 && round_counter>0)
s1 = 3;
else
s1 = 2;
end
// LUT FF ENABLE MUX
// LUT FFs are used only at the first four clock cycles of each round
always@(*)
begin
if(data_rdy==3 && bit_counter<4)
lut_ff_enable = 1;
else
lut_ff_enable = 0;
end
//FIFO FF ENABLE MUX
always@(*)
begin
if(data_rdy==2 || data_rdy==3)
fifo_ff_enable = 1;
else
fifo_ff_enable = 0;
end
//SHIFTER ENABLES
// Shifters are enabled when the key is loaded or block cipher is running
always@(*)
begin
if(data_rdy==2 || data_rdy==3)
shifter_enable1 = 1;
else
shifter_enable1 = 0;
if(data_rdy==2 || data_rdy==3)
shifter_enable2 = 1;
else
shifter_enable2 = 0;
end
//Round Counter
always@(posedge clk)
begin
if(data_rdy==3 && bit_counter==63)
round_counter <= round_counter + 1;
else if(data_rdy==0)
round_counter <= 0;
else
round_counter <= round_counter;
end
// The necessary bit of the constant Z is selected by the round counter
always @(*)
begin
if(bit_counter==0)
z_value = Z[round_counter];
else
z_value = 0;
end
// The value of c is 1 at the first two cycles of each round only
always @(*)
begin
if(bit_counter==0 || bit_counter==1)
c = 0;
else
c = 1;
end
// New computed key bit
assign lut_out = shift_out2 ^ lut_in3 ^ shift_out1 ^ z_value ^ c;
// Output key bit that is connected to the datapath
assign key_out = shift_out2;
endmodule

View File

@ -0,0 +1,45 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Team: Virginia Tech Secure Embedded Systems (SES) Lab
// Implementer: Ege Gulcan
//
// Create Date: 19:14:37 11/13/2013
// Design Name:
// Module Name: top_module
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module Simon_bit_serial_top(clk,data_in,data_rdy,cipher_out);
input clk,data_in;
input [1:0] data_rdy;
output cipher_out;
wire key;
wire [5:0] bit_counter;
wire round_counter_out;
/*
data_rdy=0 -> Reset, Idle
data_rdy=1 -> Load Plaintext
data_rdy=2 -> Load Key
data_rdy=3 -> Run (keep at 3 while the block cipher is running)
*/
simon_datapath_shiftreg datapath(.clk(clk), .data_in(data_in), .data_rdy(data_rdy), .key_in(key),
. cipher_out(cipher_out), .round_counter(round_counter_out), .bit_counter(bit_counter));
simon_key_expansion_shiftreg key_exp(.clk(clk), .data_in(data_in), .data_rdy(data_rdy), .key_out(key), .bit_counter(bit_counter),
.round_counter_out(round_counter_out));
endmodule

View File

@ -0,0 +1,143 @@
/*-------------------------------------------------------------------
CM_FIFO_1x
Communication Manager (CM) FIFO, using 1 RAM block.
18-bit write port (512 deep), 9-bit read port (1024 deep).
The LSB on the write port will be the first byte to appear on
the read port.
Valid data appears on the output data port without first
having to do a pop.
Over-run and under-run protection are both implemented:
reads when empty will be ignored and provide invalid data,
writes when full will be ignored.
-------------------------------------------------------------------*/
`timescale 1ns / 10ps
module CM_FIFO_1x (
rst,
push_clk,
push,
din,
full,
push_flag,
overflow,
pop_clk,
pop,
dout,
empty,
pop_flag,
CM_FIFO_1x_din_o ,
CM_FIFO_1x_push_int_o ,
CM_FIFO_1x_pop_int_o ,
CM_FIFO_1x_push_clk_o ,
CM_FIFO_1x_pop_clk_o ,
CM_FIFO_1x_rst_o ,
CM_FIFO_1x_almost_full_i ,
CM_FIFO_1x_almost_empty_i ,
CM_FIFO_1x_push_flag_i ,
CM_FIFO_1x_pop_flag_i ,
CM_FIFO_1x_dout_i
);
input rst;
input push_clk;
input push;
input [17:0] din;
output full;
output [3:0] push_flag;
output overflow;
input pop_clk;
input pop;
output [8:0] dout;
output empty;
output [3:0] pop_flag;
output [17:0] CM_FIFO_1x_din_o ;
output CM_FIFO_1x_push_int_o ;
output CM_FIFO_1x_pop_int_o ;
output CM_FIFO_1x_push_clk_o ;
output CM_FIFO_1x_pop_clk_o ;
output CM_FIFO_1x_rst_o ;
input CM_FIFO_1x_almost_full_i ;
input CM_FIFO_1x_almost_empty_i ;
input [3:0] CM_FIFO_1x_push_flag_i ;
input [3:0] CM_FIFO_1x_pop_flag_i ;
input [8:0] CM_FIFO_1x_dout_i ;
reg overflow;
wire push_int;
wire pop_int;
reg pop_r1, pop_r2, pop_r3;
// over-run/under-run protection
assign push_int = full ? 1'b0 : push;
// changed to match the current S2 functionality
//assign pop_int = empty ? 1'b0 : pop;
assign pop_int = empty ? 1'b0 : (pop_r2 ^ pop_r3);
assign CM_FIFO_1x_din_o = din;
assign CM_FIFO_1x_push_int_o = push_int;
assign CM_FIFO_1x_pop_int_o = pop_int;
assign CM_FIFO_1x_push_clk_o = push_clk;
assign CM_FIFO_1x_pop_clk_o = pop_clk;
assign CM_FIFO_1x_rst_o = rst;
assign almost_full = CM_FIFO_1x_almost_full_i;
assign almost_empty = CM_FIFO_1x_almost_empty_i;
assign push_flag = CM_FIFO_1x_push_flag_i;
assign pop_flag = CM_FIFO_1x_pop_flag_i;
assign dout = CM_FIFO_1x_dout_i;
assign full = (push_flag == 4'h0);
assign empty = (pop_flag == 4'h0);
// overflow detection
always @(posedge push_clk or posedge rst)
if (rst)
overflow <= 0;
else
if (push && full)
overflow <= 1;
else
overflow <= 0;
/// Synchronize SPI FIFO Read to SPI CLock due to delay
always @(posedge pop_clk or posedge rst)
if (rst) begin
pop_r1 <= 1'b0;
pop_r2 <= 1'b0;
pop_r3 <= 1'b0;
end
else begin
pop_r1 <= pop;
pop_r2 <= pop_r1;
pop_r3 <= pop_r2;
end
endmodule

View File

@ -0,0 +1,152 @@
/*-----------------------------------------------------------------------------
CM_FIFO_autodrain
This module will auto-drain (read from) the CM FIFO when RingBufferMode
is enabled. It will stop on packet boundaries (designated by bit 8 of
the FIFO data).
-----------------------------------------------------------------------------*/
`timescale 1ns / 10ps
module CM_FIFO_autodrain (
input rst,
input FFE_CLK_gclk,
input RingBufferMode,
input [3:0] CM_FIFO_PushFlags,
input CM_FIFO_Empty,
input CM_FIFO_PopFromTLC,
input [8:0] CM_FIFO_ReadData,
output CM_FIFO_Pop,
output busy,
output TP1,
output TP2
);
// state definitions
localparam ST_IDLE = 3'b000;
localparam ST_SETBUSY1 = 3'b001;
localparam ST_SETBUSY2 = 3'b010;
localparam ST_WAIT = 3'b011;
localparam ST_READ = 3'b100;
wire SOP_Marker;
wire FIFO_AutoRead_Threshold;
reg RingBufferMode_r1;
reg RingBufferMode_r2;
reg [2:0] state;
reg busy_reg;
reg CM_FIFO_PopAutoDrain;
assign SOP_Marker = CM_FIFO_ReadData[8];
/* PUSH_FLAG:
0x0: full
0x1: empty
0x2: room for 1/2 to (full - 1)
0x3: room for 1/4 to (1/2 -1)
0x4: room for 64 to (1/4 - 1)
0xA: room for 32 to 63
0xB: room for 16 to 31
0xC: room for 8 to 15
0xD: room for 4 to 7
0xE: room for 2 to 3
0xF: room for 1
others: reserved */
assign FIFO_AutoRead_Threshold = ((CM_FIFO_PushFlags == 4'h0) || (CM_FIFO_PushFlags[3])); // full or (63 or less) 16-bit words
// sync RingBufferMode to the FFE clk
always @(posedge rst or posedge FFE_CLK_gclk)
if (rst) begin
RingBufferMode_r1 <= 0;
RingBufferMode_r2 <= 0;
end
else begin
RingBufferMode_r1 <= RingBufferMode;
RingBufferMode_r2 <= RingBufferMode_r1;
end
// state machine
always @(posedge rst or posedge FFE_CLK_gclk)
if (rst)
state <= ST_IDLE;
else
case (state)
ST_IDLE: if (RingBufferMode_r2)
state <= ST_SETBUSY1;
else
state <= ST_IDLE;
ST_SETBUSY1: state <= ST_SETBUSY2; // allow time for the FIFO read clock to switch safely
ST_SETBUSY2: state <= ST_WAIT;
ST_WAIT: if (!RingBufferMode_r2)
state <= ST_IDLE;
else
state <= ST_READ;
ST_READ: if (SOP_Marker && !RingBufferMode_r2)
state <= ST_SETBUSY1; // goto ST_SETBUSY1 to allow time to switch to SPI_SCLK
else
state <= ST_READ;
endcase
// busy
wire busy_reg_reset;
assign busy_reg_reset = rst || !RingBufferMode;
always @(posedge busy_reg_reset or posedge FFE_CLK_gclk)
if (busy_reg_reset)
busy_reg <= 0;
else
case (busy_reg)
1'b0: if ((state == ST_IDLE) && (RingBufferMode_r2))
busy_reg <= 1;
else
busy_reg <= 0;
1'b1: if (((state == ST_SETBUSY1) && !RingBufferMode_r2) || (state == ST_IDLE))
busy_reg <= 0;
else
busy_reg <= 1;
endcase
// FIFO Read control
always @(*)
if (state == ST_READ) // pop only allowed in ST_READ state...
if (!CM_FIFO_Empty) // ...and FIFO not empty
if (!SOP_Marker) // if not on SOP marker, keep reading
CM_FIFO_PopAutoDrain <= 1;
else // (SOP_Marker)
if (FIFO_AutoRead_Threshold && RingBufferMode_r2) // if SOP marker, read next packet if FIFO is at or past threshold and RingBufferMode still on
CM_FIFO_PopAutoDrain <= 1;
else
CM_FIFO_PopAutoDrain <= 0; // else pop=0
else // (CM_FIFO_Empty)
CM_FIFO_PopAutoDrain <= 0;
else // (state != ST_READ)
CM_FIFO_PopAutoDrain <= 0;
assign CM_FIFO_Pop = busy_reg ? CM_FIFO_PopAutoDrain : CM_FIFO_PopFromTLC;
assign busy = busy_reg;
assign TP1 = FIFO_AutoRead_Threshold;
assign TP2 = 0;
endmodule

View File

@ -0,0 +1,291 @@
// 4k deep CM
// This module bypasses the FFEControlMememoryMux since the addressing of the individual RAM blocks
// is not the same when coming from the TLC vs. FFE, and dynamic code updates must be supported for
// the fabric RAM's.
// Note: in order for this to work correctly, RdClk and WrClk must be the same (tied together externally).
`timescale 1ns / 10ps
`include "ulpsh_rtl_defines.v"
module FFEControlMemory_4k (
// General Interface
input ResetIn,
input SPI_clk,
input TLC_FFE_clk2x_muxed, // already muxed based on UseFastClock from TLC
input MemSelect_en, // MemorySelect and enable from TLC
input [2:0] MemSelect,
input FFE_clock_halfperiod,
input [11:0] Address_TLC, // TLC address is used for both TLC reads and writes
input [35:0] MemoryMux_in,
output [35:0] MemoryMux_out,
//Read Interface
input [11:0] ReadAddress_FFE,
output [35:0] ReadData,
input ReadEnable_TLC,
input ReadEnable_FFE,
//Write Interface
input [35:0] WriteData_TLC,
input WriteEnable_TLC,
// ASSP RAM interface - left bank
output assp_lb_ram0_clk,
output [8:0] assp_lb_ram0_addr,
output [35:0] assp_lb_ram0_wr_data,
input [35:0] assp_lb_ram0_rd_data,
output assp_lb_ram0_wr_en,
output assp_lb_ram0_rd_en,
output [3:0] assp_lb_ram0_wr_be,
// ASSP RAM interface - right bank
output assp_rb_ram1_clk,
output [8:0] assp_rb_ram1_addr,
output [35:0] assp_rb_ram1_wr_data,
input [35:0] assp_rb_ram1_rd_data,
output assp_rb_ram1_wr_en,
output assp_rb_ram1_rd_en,
output [3:0] assp_rb_ram1_wr_be,
// ASSP RAM interface - 8k - left bank
output assp_lb_ram8k_clk,
output [11:0] assp_lb_ram8k_addr,
output [16:0] assp_lb_ram8k_wr_data,
input [16:0] assp_lb_ram8k_rd_data,
output assp_lb_ram8k_wr_en,
output assp_lb_ram8k_rd_en,
output [1:0] assp_lb_ram8k_wr_be,
//AP2
output [8:0] FFEControlMemory_4k_Address_TLC_o ,
output [8:0] FFEControlMemory_4k_ReadAddress_muxed_o ,
output FFEControlMemory_4k_ram5_wr_en_o,
output FFEControlMemory_4k_ram5_rd_en_o,
output FFEControlMemory_4k_SPI_clk_o,
output FFEControlMemory_4k_TLC_FFE_clk2x_muxed_o,
output [35:0] FFEControlMemory_4k_WriteData_TLC_o ,
input [35:0] FFEControlMemory_4k_ram5_rd_data_i ,
output FFEControlMemory_4k_ram4_wr_en_o ,
output FFEControlMemory_4k_ram4_rd_en_o,
input [35:0] FFEControlMemory_4k_ram4_rd_data_i,
output [9:0] FFEControlMemory_4k_fabric_ram1Kx9_addr_o,
output FFEControlMemory_4k_ram1_wr_en_o ,
output FFEControlMemory_4k_ram1_rd_en_o ,
input [8:0] FFEControlMemory_4k_ram1_rd_data_i
);
wire [11:0] ReadAddress_muxed;
wire Select_from_TLC;
wire ram0_wr_en;
wire ram1_wr_en;
wire ram2_wr_en;
wire ram3_wr_en;
wire ram4_wr_en;
wire ram5_wr_en;
wire ram0_rd_en;
wire ram1_rd_en;
wire ram2_rd_en;
wire ram3_rd_en;
wire ram4_rd_en;
wire ram5_rd_en;
wire [11:0] assp_ram8k_addr;
wire [9:0] fabric_ram1Kx9_addr;
wire [16:0] ram0_rd_data;
wire [8:0] ram1_rd_data;
wire [35:0] ram2_rd_data;
wire [35:0] ram3_rd_data;
wire [35:0] ram4_rd_data;
wire [35:0] ram5_rd_data;
reg [35:0] lower2k_rd_data;
reg [16:0] lower2k_rd_data_phase0, lower2k_rd_data_phase1;
reg ReadAddress_muxed_bit0_r1;
reg [2:0] ram_rd_select;
reg [35:0] ram_rd_data;
wire [8:0] assp_ram_addr;
// RAM blocks are arranged as follows:
// RAM 0: 0-2k: 4Kx17 (double-clocked to create the lower 34 bits of each uInstruction)
// RAM 1: 0-2k: 1024x9 (one-half of the 1024x9 word is used for the remaining 2 bits of each uInstruction)
// RAM 2,3: 2k-3k: ASSP RAM's (formerly 0k-1k in the 2k CM)
// RAM 4,5: 3k-4k: fabric RAM's (formerly 1k-2k in the 2k CM)
assign Select_from_TLC = (MemSelect_en && (MemSelect == 3'h0 || MemSelect == 3'h4 || MemSelect == 3'h5));
// memory mux to pass data back to TLC
assign MemoryMux_out = Select_from_TLC ? ReadData : MemoryMux_in;
// mux between the TLC and FFE control signals
assign ReadAddress_muxed = Select_from_TLC ? Address_TLC : ReadAddress_FFE;
assign ReadEnable_muxed = Select_from_TLC ? ReadEnable_TLC : ReadEnable_FFE;
// generate the read address for the 4Kx17 ASSP RAM
assign assp_ram8k_addr = Select_from_TLC ? Address_TLC : {ReadAddress_FFE[10:0], FFE_clock_halfperiod};
/// generate the read address for the 1Kx9 fabric RAM
assign fabric_ram1Kx9_addr = Select_from_TLC ? Address_TLC : ReadAddress_FFE[10:1];
// write enables for each RAM block
// note: fabric RAM's cannot use MemSelect_en since these RAM's may be updated during run-time.
assign ram0_wr_en = (MemSelect_en && MemSelect == 3'h4 && WriteEnable_TLC);
assign ram1_wr_en = (MemSelect_en && MemSelect == 3'h5 && WriteEnable_TLC);
assign ram2_wr_en = (MemSelect_en && MemSelect == 3'h0 && WriteEnable_TLC && Address_TLC[10:9] == 2'b00);
assign ram3_wr_en = (MemSelect_en && MemSelect == 3'h0 && WriteEnable_TLC && Address_TLC[10:9] == 2'b01);
assign ram4_wr_en = ( MemSelect == 3'h0 && WriteEnable_TLC && Address_TLC[10:9] == 2'b10);
assign ram5_wr_en = ( MemSelect == 3'h0 && WriteEnable_TLC && Address_TLC[10:9] == 2'b11);
// read enables for each RAM block
assign ram0_rd_en = (MemSelect_en && MemSelect == 3'h4) ? ReadEnable_TLC : (ReadEnable_FFE && ReadAddress_FFE[11] == 1'b0);
assign ram1_rd_en = (MemSelect_en && MemSelect == 3'h5) ? ReadEnable_TLC : (ReadEnable_FFE && ReadAddress_FFE[11] == 1'b0 && FFE_clock_halfperiod);
assign ram2_rd_en = (MemSelect_en && MemSelect == 3'h0) ? (ReadEnable_TLC && Address_TLC[10:9] == 2'b00) : (ReadEnable_FFE && FFE_clock_halfperiod && ReadAddress_FFE[11:9] == 3'b100 && FFE_clock_halfperiod);
assign ram3_rd_en = (MemSelect_en && MemSelect == 3'h0) ? (ReadEnable_TLC && Address_TLC[10:9] == 2'b01) : (ReadEnable_FFE && FFE_clock_halfperiod && ReadAddress_FFE[11:9] == 3'b101 && FFE_clock_halfperiod);
assign ram4_rd_en = (MemSelect_en && MemSelect == 3'h0) ? (ReadEnable_TLC && Address_TLC[10:9] == 2'b10) : (ReadEnable_FFE && FFE_clock_halfperiod && ReadAddress_FFE[11:9] == 3'b110 && FFE_clock_halfperiod);
assign ram5_rd_en = (MemSelect_en && MemSelect == 3'h0) ? (ReadEnable_TLC && Address_TLC[10:9] == 2'b11) : (ReadEnable_FFE && FFE_clock_halfperiod && ReadAddress_FFE[11:9] == 3'b111 && FFE_clock_halfperiod);
// RAM 5 (fabric)
assign FFEControlMemory_4k_Address_TLC_o[8:0] = Address_TLC[8:0];
assign FFEControlMemory_4k_ReadAddress_muxed_o[8:0] = ReadAddress_muxed[8:0];
assign FFEControlMemory_4k_ram5_wr_en_o = ram5_wr_en ;
assign FFEControlMemory_4k_ram5_rd_en_o = ram5_rd_en;
assign FFEControlMemory_4k_SPI_clk_o = SPI_clk;
assign FFEControlMemory_4k_TLC_FFE_clk2x_muxed_o = TLC_FFE_clk2x_muxed;
assign FFEControlMemory_4k_WriteData_TLC_o = WriteData_TLC;
assign ram5_rd_data = FFEControlMemory_4k_ram5_rd_data_i;
assign FFEControlMemory_4k_ram4_wr_en_o = ram4_wr_en ;
assign FFEControlMemory_4k_ram4_rd_en_o = ram4_rd_en;
assign ram4_rd_data = FFEControlMemory_4k_ram4_rd_data_i;
// mappings to the ASSP RAM's
assign assp_ram_addr = (MemSelect_en && MemSelect == 3'h0) ? Address_TLC[8:0] : ReadAddress_muxed[8:0];
// RAM 3 (ASSP right bank)
// note: the port names are still called "ram1" to maintain compatibility with the 2k CM variant
assign assp_rb_ram1_clk = TLC_FFE_clk2x_muxed;
assign assp_rb_ram1_addr = assp_ram_addr;
assign assp_rb_ram1_wr_data = WriteData_TLC;
assign ram3_rd_data = assp_rb_ram1_rd_data;
assign assp_rb_ram1_wr_en = ram3_wr_en;
assign assp_rb_ram1_rd_en = ram3_rd_en;
assign assp_rb_ram1_wr_be = 4'b1111;
// RAM 2 (ASSP left bank)
// note: the port names are still called "ram0" to maintain compatibility with the 2k CM variant
assign assp_lb_ram0_clk = TLC_FFE_clk2x_muxed;
assign assp_lb_ram0_addr = assp_ram_addr;
assign assp_lb_ram0_wr_data = WriteData_TLC;
assign ram2_rd_data = assp_lb_ram0_rd_data;
assign assp_lb_ram0_wr_en = ram2_wr_en;
assign assp_lb_ram0_rd_en = ram2_rd_en;
assign assp_lb_ram0_wr_be = 4'b1111;
assign FFEControlMemory_4k_fabric_ram1Kx9_addr_o = fabric_ram1Kx9_addr;
assign FFEControlMemory_4k_ram1_wr_en_o = ram1_wr_en ;
assign FFEControlMemory_4k_ram1_rd_en_o = ram1_rd_en;
assign FFEControlMemory_4k_SPI_clk_o = SPI_clk;
assign ram1_rd_data = FFEControlMemory_4k_ram1_rd_data_i;
// RAM 0 (ASSP 8k left bank)
assign assp_lb_ram8k_clk = TLC_FFE_clk2x_muxed;
assign assp_lb_ram8k_addr = assp_ram8k_addr;
assign assp_lb_ram8k_wr_data = WriteData_TLC;
assign ram0_rd_data = assp_lb_ram8k_rd_data;
assign assp_lb_ram8k_wr_en = ram0_wr_en;
assign assp_lb_ram8k_rd_en = ram0_rd_en;
assign assp_lb_ram8k_wr_be = 2'b11;
// latch the 4Kx17 read data
always @(posedge TLC_FFE_clk2x_muxed) begin
if (FFE_clock_halfperiod)
lower2k_rd_data_phase0 <= ram0_rd_data;
if (!FFE_clock_halfperiod)
lower2k_rd_data_phase1 <= ram0_rd_data;
if (FFE_clock_halfperiod)
ReadAddress_muxed_bit0_r1 <= ReadAddress_muxed[0];
end
// assemble the read data for the lower 2k (ram0/ram1)
always @(*)
if (FFE_clock_halfperiod == 0)
if (ReadAddress_muxed_bit0_r1 == 0)
lower2k_rd_data <= {ram1_rd_data[1:0], ram0_rd_data[16:0], lower2k_rd_data_phase0[16:0]};
else
lower2k_rd_data <= {ram1_rd_data[3:2], ram0_rd_data[16:0], lower2k_rd_data_phase0[16:0]};
else
if (ReadAddress_muxed_bit0_r1 == 0)
lower2k_rd_data <= {ram1_rd_data[1:0], lower2k_rd_data_phase1[16:0], lower2k_rd_data_phase0[16:0]};
else
lower2k_rd_data <= {ram1_rd_data[3:2], lower2k_rd_data_phase1[16:0], lower2k_rd_data_phase0[16:0]};
// mux the read data from each RAM block, for the FFE
always @(posedge TLC_FFE_clk2x_muxed)
if (FFE_clock_halfperiod)
ram_rd_select <= ReadAddress_muxed[11:9];
always @(*)
if (MemSelect_en)
// TLC is reading
if (MemSelect == 3'h0)
case (ram_rd_select[1:0])
2'b00: ram_rd_data <= ram2_rd_data;
2'b01: ram_rd_data <= ram3_rd_data;
2'b10: ram_rd_data <= ram4_rd_data;
2'b11: ram_rd_data <= ram5_rd_data;
endcase
else
if (MemSelect == 3'h4)
ram_rd_data <= ram0_rd_data;
else
// assume select=5 to reduce logic
//if (MemSelect == 3'h5)
ram_rd_data <= ram1_rd_data;
//else
// ram_rd_data <= 0;
else
// FFE is reading
if (ram_rd_select[2])
// upper 2k
case(ram_rd_select[1:0])
2'b00: ram_rd_data <= ram2_rd_data;
2'b01: ram_rd_data <= ram3_rd_data;
2'b10: ram_rd_data <= ram4_rd_data;
2'b11: ram_rd_data <= ram5_rd_data;
endcase
else
// lower 2k
ram_rd_data <= lower2k_rd_data;
assign ReadData = ram_rd_data;
endmodule

View File

@ -0,0 +1,38 @@
`timescale 1ns / 10ps
module FFEDataMemoryMux (
input Select,
input [9:0] ReadAddressIn0,
input [9:0] ReadAddressIn1,
output[9:0] ReadAddressOut,
input [9:0] WriteAddressIn0,
input [9:0] WriteAddressIn1,
output[9:0] WriteAddressOut,
input [35:0] DataToMemoryIn0,
input [35:0] DataToMemoryIn1,
output[35:0] DataToMemoryOut,
input [35:0] DataFromMemoryIn0,
input [35:0] DataFromMemoryIn1,
output[35:0] DataFromMemoryOut,
input ReadEnable0,
input ReadEnable1,
output ReadEnable,
input WriteEnable0,
input WriteEnable1,
output WriteEnable
);
assign ReadAddressOut = (Select) ? ReadAddressIn1 : ReadAddressIn0;
assign WriteAddressOut = (Select) ? WriteAddressIn1 : WriteAddressIn0;
assign DataToMemoryOut = (Select) ? DataToMemoryIn1 : DataToMemoryIn0;
assign DataFromMemoryOut = (Select) ? DataFromMemoryIn1 : DataFromMemoryIn0;
assign ReadEnable = (Select) ? ReadEnable1 : ReadEnable0;
assign WriteEnable = (Select) ? WriteEnable1 : WriteEnable0;
endmodule

View File

@ -0,0 +1,476 @@
// -----------------------------------------------------------------------------
// title : FFE_ALU.v
// project : ULP Sensor Hub
// description : 32-bit ALU
// -----------------------------------------------------------------------------
// copyright (c) 2013, QuickLogic Corporation
// -----------------------------------------------------------------------------
// History :
// date version author description
//
// -----------------------------------------------------------------------------
// date version author description
// 10-31-2013 1.1 Anthony Le Add AND function to code
// Details:
// 1. Add new bus signal xT30 as 32-bit for output of AND function
// 2. Assign a temporary 32bit bus to hold the concatenation of MailBox bit:
// Mailbox32bit = {8'b0, MailBox[7:0], 16'h0};
// 3. Add code to perform AND function between Mailbox32bit and xT23
// 4. Add mux function between xT30 and MailBox in using signal[38]
// 5. Expected the Synthesis to remove all unused logics
//
// 11-29-2013 1.2 Anthony Le Add additional comparison functions
// Details:
// 1. Current system supports only three jump functions:
// a. JMP: jump
// b. JMPNEZ: jump when result is not equal to zero
// c. JMPGEZ: jump when result is greater or equal to zero
// 2. Add four more compriason jump functions
// a. JMPEQZ: jump when result is equal to zero
// b. JMPLTZ: jump when result is less than zero
// c. JMPLEZ: jump when result is less than or equal to zero
// d. JMPGTZ: jump when result is greater than zero
// 3. Re-use the three control signals[19:17]
// 4. Use an 8-to-1 mux for JUMP logic
// 5. Update xJumpFlag from wire to reg type
//
//
// -----------------------------------------------------------------------------
`timescale 1ns / 10ps
`include "ulpsh_rtl_defines.v"
module FFE_ALU (
input [31:0] xReadData1,
input [31:0] xReadData2,
input [63:0] signals,
input ClockIn,
input Clock_x2In,
input FFE_clock_halfperiod,
input [15:0] TimeStampIn,
input [31:0] MailboxIn,
input [3:0] SM_InterruptIn,
input MultClockIn,
input [3:0] MultStateIn,
output [8:0] xIndexRegister,
output [31:0] xWriteData,
output reg xJumpFlag,
input Save_BG_registers,
input Restore_BG_registers,
output [31:0] mult_in1,
output [31:0] mult_in2,
output mult_enable,
input [63:0] mult_out
);
wire [31:0] xT0, xT1, xT2;
//wire [31:0] xT3; // defined below, depending on the multiplier implementation
wire [31:0] xT4;
reg [31:0] xT5;
wire [31:0] xT6, xT7, xT8, xT9;
wire [31:0] xT10, xT11, xT12, xT13, xT14, xT15, xT16, xT17, xT18, xT19, xT20, xT21, xT22;
reg [31:0] xT23;
wire [31:0] xT24, xT25;
wire [8:0] xT26, xT27, xT28;
reg [8:0] xT29;
wire [31:0] xT30;
wire signed [31:0] xT12_signed;
wire f0;
reg f2, f5, f2_BG, f5_BG;
wire f3, f6;
reg f2_latched, f2_BG_latched;
reg [31:0] xT5_latched;
reg f5_latched, f5_BG_latched;
reg [8:0] xT29_latched;
// compiler options, from rtl_defines.v
// ENABLE_FFE_F0_EXTENDED_DM
// ENABLE_FFE_F0_SINGLE_DM
// ENABLE_FFE_F0_PROGRAMMABLE_SEG0_OFFSET
// FFE_F0_SEG0_OFFSET [value]
// compiler directives related to CM size:
// ENABLE_FFE_F0_CM_SIZE_2K
// ENABLE_FFE_F0_CM_SIZE_4K
// ENABLE_FFE_F0_CM_SIZE_3K (future support if needed)
// select the multiplier implementation
`define ASSP_MULT
`ifdef FullSingleCycle
wire [63:0] xT3;
wire [63:0] xT1extended, xT2extended;
assign xT1extended[63:0] = { {32{xT1[31]}}, xT1[31:0] };
assign xT2extended[63:0] = { {32{xT2[31]}}, xT2[31:0] };
assign xT3 = xT1extended * xT2extended;
assign xT4 = (xT3 >> 16);
`elsif Handicapped
wire [31:0] xT3;
assign xT3 = xT1 + xT2; // replace multiplier with adder
assign xT4 = xT3;
`elsif MultiCycle
wire [31:0] xT3;
Multiplier Multiplier_1 (
.ClockIn ( MultClockIn ),
.StateIn ( MultStateIn ),
.Arg1In ( xT1 ),
.Arg2In ( xT2 ),
.ResultOut ( xT3 )
);
assign xT4 = xT3;
`elsif ASSP_MULT
wire [63:0] xT3;
assign xT3 = mult_out;
assign xT4 = (xT3 >> 16);
`else
wire [31:0] xT3;
assign xT3 = 0;
assign xT4 = 0;
`endif
// drive the outputs for the ASSP multiplier
assign mult_in1 = xT1;
assign mult_in2 = xT2;
assign mult_enable = signals[5];
assign xT22 = signals[2] ? (xReadData1<<16) : xReadData1;
always @(*)
case (signals[1:0])
2'b00: xT23 <= xReadData2;
2'b01: xT23 <= MailboxIn;
2'b10: xT23 <= {TimeStampIn[15:0], 16'b0};
2'b11: xT23 <= {7'b0, xT29[8:0], 16'b0}; // IndexReg
endcase
assign xT24 = signals[3] ? {12'b0, SM_InterruptIn[3:0], 16'b0} : xT23;
assign xT30 = xReadData1 & xT24;
assign xT9 = signals[38] ? xT30 : xT24;
assign xT21 = xReadData1 | xT24;
assign xT25 = signals[39] ? xT21 : xT9;
assign xT0 = signals[4] ? xT25 : xT22;
assign xT12_signed = xT12;
// remove these muxes to save space
//assign xT1 = signals[5] ? xT0 : xT1; // this mux (latch) keeps the multiplier inputs stable, to save power
//assign xT2 = signals[5] ? xT25 : xT2; // this mux (latch) keeps the multiplier inputs stable, to save power
assign xT1 = xT0;
assign xT2 = xT25;
assign xT7 = signals[5] ? xT4 : xT25;
assign xT10 = signals[8] ? ~xT7 : xT7;
assign xT11 = signals[8] ? 32'b1 : 32'b0;
assign xT13 = signals[9] ? xT7 : xT10;
assign xT6 = signals[6] ? xT22 : xT5;
assign xT8 = signals[7] ? xT6 : 32'b0;
assign xT12 = xT8 + xT10 + xT11;
assign xT14 = (xT12_signed >>> 1);
assign xT16 = signals[11] ? xT14 : xT12;
assign xT19 = signals[12] ? xT16 : xT6;
assign f0 = xT12[31];
// Sign bit
`ifndef ENABLE_FFE_F0_SINGLE_DM
// double DM, default behavior
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
// 4k CM
always @(posedge Clock_x2In) begin
if (FFE_clock_halfperiod) begin
if (Restore_BG_registers)
f2 <= f2_BG;
else
f2 <= signals[10] ? f0 : f2;
if (Save_BG_registers)
f2_BG <= f2;
else
f2_BG <= f2_BG;
end
end
`else
// 2k CM
always @(posedge ClockIn) begin
if (Restore_BG_registers)
f2 <= f2_BG;
else
f2 <= signals[10] ? f0 : f2;
if (Save_BG_registers)
f2_BG <= f2;
else
f2_BG <= f2_BG;
end
`endif
`else
// single DM
always @(posedge Clock_x2In) begin
if (!FFE_clock_halfperiod) begin
if (Restore_BG_registers)
f2_latched <= f2_BG;
else
f2_latched <= signals[10] ? f0 : f2;
if (Save_BG_registers)
f2_BG_latched <= f2;
else
f2_BG_latched <= f2_BG;
end
end
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
if (FFE_clock_halfperiod) begin
f2 <= f2_latched;
f2_BG <= f2_BG_latched;
end
end
`else
always @(posedge ClockIn) begin
f2 <= f2_latched;
f2_BG <= f2_BG_latched;
end
`endif
`endif
assign f6 = signals[33] ? (f2) : (f0);
assign f3 = signals[35] ? !f5 : f6;
assign xT15 = (f3) ? xT13 : xT19;
assign xT17 = signals[13] ? xT15 : xT16;
assign xT18 = (xT17 << 1);
assign xT20 = signals[14] ? xT18 : xT17;
assign xWriteData = xT20;
// accumulator
`ifndef ENABLE_FFE_F0_SINGLE_DM
// double DM, default behavior
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
if (FFE_clock_halfperiod)
xT5 <= signals[16] ? xT20 : xT5;
end
`else
always @(posedge ClockIn) begin
xT5 <= signals[16] ? xT20 : xT5;
end
`endif
`else
// single DM
always @(posedge Clock_x2In) begin
if (!FFE_clock_halfperiod)
xT5_latched <= signals[16] ? xT20 : xT5;
end
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In)
if (FFE_clock_halfperiod)
xT5 <= xT5_latched;
`else
always @(posedge ClockIn)
xT5 <= xT5_latched;
`endif
`endif
// NEZ flag
`ifndef ENABLE_FFE_F0_SINGLE_DM
// double DM, default behavior
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
if (FFE_clock_halfperiod) begin
if (Restore_BG_registers)
f5 <= f5_BG;
else
f5 <= signals[15] ? f5 : (xT20 != 32'b0);
if (Save_BG_registers)
f5_BG <= f5;
else
f5_BG <= f5_BG;
end
end
`else
always @(posedge ClockIn) begin
if (Restore_BG_registers)
f5 <= f5_BG;
else
f5 <= signals[15] ? f5 : (xT20 != 32'b0);
if (Save_BG_registers)
f5_BG <= f5;
else
f5_BG <= f5_BG;
end
`endif
`else
// single DM
always @(posedge Clock_x2In) begin
if (!FFE_clock_halfperiod) begin
if (Restore_BG_registers)
f5_latched <= f5_BG;
//f5_latched <= f5_BG_latched;
else
f5_latched <= signals[15] ? f5 : (xT20 != 32'b0);
//f5_latched <= signals[15] ? f5_latched : (xT20 != 32'b0);
if (Save_BG_registers)
f5_BG_latched <= f5;
//f5_BG_latched <= f5_latched;
else
f5_BG_latched <= f5_BG;
//f5_BG_latched <= f5_BG_latched;
end
end
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
if (FFE_clock_halfperiod) begin
f5 <= f5_latched;
f5_BG <= f5_BG_latched;
end
end
`else
always @(posedge ClockIn) begin
f5 <= f5_latched;
f5_BG <= f5_BG_latched;
end
`endif
`endif
always @(*)
begin
case ({signals[19], signals[18], signals[17]})
3'b000: xJumpFlag = 1'b0; // no jump
3'b001: xJumpFlag = 1'b1; // JMP (unconditional jump)
3'b010: xJumpFlag = f5; // JMPNEZ (jump if NEZflag)
3'b011: xJumpFlag = !f5; // JMPEQZ (jump if !NEZflag)
3'b100: xJumpFlag = !f2; // JMPGEZ (jump if !SignBit)
3'b101: xJumpFlag = f2; // JMPLTZ (jump if SignBit)
3'b110: xJumpFlag = !(!f2 && f5); // JMPLEZ (jump if SignBit or !NEZflag)
3'b111: xJumpFlag = !f2 && f5; // JMPGTZ (jump if !SignBit and NEZflag)
default: xJumpFlag = 1'b0;
endcase
end
// Index register code
assign xT26 = xT29 + 1;
assign xT27 = signals[24] ? xT26 : 9'b0;
assign xT28 = signals[26] ? xT20[24:16] : xT27; // assign the integer portion of xT20, or xT27
// Index Register
`ifndef ENABLE_FFE_F0_SINGLE_DM
// double DM, default behavior
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
if (FFE_clock_halfperiod) begin
if (signals[25])
xT29 <= xT28;
else
xT29 <= xT29;
end
end
`else
always @(posedge ClockIn) begin
if (signals[25])
xT29 <= xT28;
else
xT29 <= xT29;
end
`endif
`else
// single DM
always @(posedge Clock_x2In) begin
if (!FFE_clock_halfperiod) begin
if (signals[25])
xT29_latched <= xT28;
else
xT29_latched <= xT29;
end
end
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In)
if (FFE_clock_halfperiod)
xT29 <= xT29_latched;
`else
always @(posedge ClockIn)
xT29 <= xT29_latched;
`endif
`endif
assign xIndexRegister = xT29;
// prevent logic duplication
//pragma attribute xT0 preserve_driver true
//pragma attribute xT1 preserve_driver true
//pragma attribute xT2 preserve_driver true
//pragma attribute xT3 preserve_driver true
//pragma attribute xT4 preserve_driver true
//pragma attribute xT5 preserve_driver true
//pragma attribute xT6 preserve_driver true
//pragma attribute xT7 preserve_driver true
//pragma attribute xT8 preserve_driver true
//pragma attribute xT9 preserve_driver true
//pragma attribute xT10 preserve_driver true
//pragma attribute xT11 preserve_driver true
//pragma attribute xT12 preserve_driver true
//pragma attribute xT13 preserve_driver true
//pragma attribute xT14 preserve_driver true
//pragma attribute xT15 preserve_driver true
//pragma attribute xT16 preserve_driver true
//pragma attribute xT17 preserve_driver true
//pragma attribute xT18 preserve_driver true
//pragma attribute xT19 preserve_driver true
//pragma attribute xT20 preserve_driver true
//pragma attribute xT20 preserve_driver true
//pragma attribute xT21 preserve_driver true
//pragma attribute xT22 preserve_driver true
//pragma attribute xT23 preserve_driver true
//pragma attribute xT24 preserve_driver true
//pragma attribute xT25 preserve_driver true
//pragma attribute xT26 preserve_driver true
//pragma attribute xT27 preserve_driver true
//pragma attribute xT28 preserve_driver true
//pragma attribute xT29 preserve_driver true
//pragma attribute xT30 preserve_driver true
//pragma attribute xT12_signed preserve_driver true
//pragma attribute f0 preserve_driver true
//pragma attribute f2 preserve_driver true
//pragma attribute f5 preserve_driver true
//pragma attribute f3 preserve_driver true
//pragma attribute f6 preserve_driver true
endmodule

View File

@ -0,0 +1,964 @@
/* -----------------------------------------------------------------------------
title : FlexFusionEngine Control
project : Jim-Bob Hardware Sensor Hub
-----------------------------------------------------------------------------
platform : Alabama test chip
standard : Verilog 2001
-----------------------------------------------------------------------------
description: Module for controlling the FlexFusionEngine
-----------------------------------------------------------------------------
copyright (c) 2013, QuickLogic Corporation
-----------------------------------------------------------------------------
History :
Date Version Author Description
2013/03/21 1.0 Jason Lew Created
2013/05/02 1.1 Jason Lew Migrated from FFEAT v21d
2013/06/14 1.2 Randy O. Corrected assignment to DataMemReadAddr's b/c it wasn't using IndexReg properly.
Corrected assignment to MemReadData's b/c it shouldn't use IndexReg.
2013/06/26 1.3 Randy O. Made the Signals bus 64 bits wide instead of 32, since it needs to be at least as wide as the one in microopdecodes.v
2013/07/01 1.4 Randy O. Cosmetic changes to improve readability.
Removed DataMem1WriteData_int & DataMem2WriteData_int since they were unused.
2013/07/08 1.5 Randy O. Added unit delays to aid in functional sim.
2014/05/21 1.6 Glen G. Added ability to read/write expanded Sensor Manager Memory
-----------------------------------------------------------------------------
Comments: This solution is specifically for implementing into the Alabama
test chip. Verification will be done using the Jim-Bob Sensor Board
------------------------------------------------------------------------------*/
`include "ulpsh_rtl_defines.v"
`timescale 1ns / 10ps
module FFE_Control ( // named RunFlexFusionEngine in C source
input ClockIn,
input Clock_x2In,
input ResetIn,
input StartIn,
output StartSMOut,
input [15:0] TimeStampIn,
input [31:0] MailboxIn,
input [3:0] SM_InterruptIn,
output [11:0] ControlMemAddressOut,
output reg ControlMemReadEnableOut,
output [9:0] SensorMemReadAddressOut, // Expanded for Rel 0 on 6/18
output SensorMemReadEnableOut,
output [9:0] SensorMemWriteAddressOut, // New for Rel 0 on 6/18
output SensorMemWriteEnableOut, // New for Rel 0 on 6/18
input [35:0] ControlMemDataIn,
input [35:0] Mem1ReadData,
input [35:0] Mem2ReadData,
input [17:0] SensorMemReadDataIn,
input SensorMemBusyIn,
output [8:0] SensorMemWriteDataOut, // New for Rel 0 on 6/18
output BusyOut,
output DataMem1ReadEnable,
output DataMem2ReadEnable,
output DataMem1WriteEnable,
output DataMem2WriteEnable,
output [9:0] DataMem1ReadAddressOut,
output [9:0] DataMem1WriteAddressOut,
output [35:0] DataMem1WriteDataOut,
output [9:0] DataMem2ReadAddressOut,
output [9:0] DataMem2WriteAddressOut,
output [35:0] DataMem2WriteDataOut,
output reg FFE_clock_halfperiod,
input MultClockIn,
input [3:0] MultStateIn,
// Status data
input SMBusyIn,
output reg SMOverrunOut,
// CM FIFO controls
output [17:0] CMWriteDataOut,
output CMWriteEnableOut,
output [7:0] InterruptMsgOut,
// interface to ASSP multiplier
output [31:0] mult_in1,
output [31:0] mult_in2,
output mult_enable,
input [63:0] mult_out,
output TP1,
output TP2,
output TP3
);
// compiler directives related to CM size:
// ENABLE_FFE_F0_CM_SIZE_2K
// ENABLE_FFE_F0_CM_SIZE_4K
// ENABLE_FFE_F0_CM_SIZE_3K (future support if needed)
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
// 4k CM
reg [11:0] xPC;
wire [11:0] xJumpAddress;
reg [11:0] PC_BG;
`else
// 2k CM (3k CM support may be added in the future)
reg [10:0] xPC;
wire [10:0] xJumpAddress;
reg [10:0] PC_BG;
`endif
reg BusyOut_reg, BusyOut_r1;
reg Start_r1, Start_r2, Start_r3;
wire [31:0] Mem1ReadDataToALU;
wire [31:0] Mem2ReadDataToALU;
wire [8:0] MicroOpCode;
wire [63:0] Signals; // the width of Signals is defined to be way larger than it needs to be (today), extra bits should get optimized out.
wire [8:0] xIndexRegister;
wire [31:0] xWriteData;
wire xJumpFlag;
wire [35:0] Mem1ReadDataX;
wire [35:0] Mem2ReadDataX;
reg [7:0] InterruptMsg_reg;
reg StartSM_reg;
reg [15:0] TimeStamp_r1, TimeStamp_r2, TimeStamp_synced;
reg f5_BG;
reg f2_BG;
reg BGcontinue_pending;
reg BGsave_pending;
reg BGstop_pending;
reg BG_active;
reg Start_pending;
wire Start_detected;
wire Save_BG_registers;
wire Restore_BG_registers;
wire Clear_PC;
wire Disable_DataMem_WrEn;
reg [2:0] Thread_switch_cnt;
parameter [2:0] THREAD_SWITCH_CNT_DONE = 3'b111;
// standard-depth DM addresses (9 bits)
wire [8:0] DataMem1ReadAddressOut_std;
wire [8:0] DataMem1WriteAddressOut_std;
wire [8:0] DataMem2ReadAddressOut_std;
wire [8:0] DataMem2WriteAddressOut_std;
wire [9:0] DataMem1WriteAddressOut_trans;
wire [9:0] DataMem2WriteAddressOut_trans;
wire [9:0] DataMem1ReadAddressOut_trans;
wire [9:0] DataMem2ReadAddressOut_trans;
reg [9:0] DataMem2ReadAddressOut_trans_hold;
reg DataMem1ReadAddressOut_trans_MSB_r1;
wire [9:0] DataMem1WriteAddressOut_mux;
wire [9:0] DataMem1ReadAddressOut_mux;
wire DataMem1ReadEnable_mux;
wire DataMem1WriteEnable_mux;
wire [9:0] DataMem1WriteAddressOut_split;
wire [9:0] DataMem2WriteAddressOut_split;
wire [9:0] DataMem1ReadAddressOut_split;
wire [9:0] DataMem2ReadAddressOut_split;
wire DataMem1ReadEnable_split;
wire DataMem1WriteEnable_split;
wire DataMem2ReadEnable_split;
wire DataMem2WriteEnable_split;
//reg FFE_clock_halfperiod;
wire DataMem1ReadEnable_std;
wire DataMem2ReadEnable_std;
reg DataMem2ReadEnable_std_hold;
wire DataMem1WriteEnable_std;
wire DataMem2WriteEnable_std;
reg [31:0] Mem1ReadData_latched;
reg [31:0] Mem2ReadData_latched;
wire ClockIn_dly1;
wire ClockIn_dly2;
wire ClockIn_dly3;
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
reg SensorMemReadEnable_reg;
reg SensorMemWriteEnable_reg;
reg [9:0] SensorMemReadAddress_reg;
reg [9:0] SensorMemWriteAddress_reg;
reg CMWriteEnable_reg;
`endif
// compiler options, from rtl_defines.v
// ENABLE_FFE_F0_EXTENDED_DM
// ENABLE_FFE_F0_SINGLE_DM
// ENABLE_FFE_F0_PROGRAMMABLE_SEG0_OFFSET
// FFE_F0_SEG0_OFFSET [value]
`ifdef FFE_F0_SEG0_OFFSET
parameter [8:0] Segment0_offset = `FFE_F0_SEG0_OFFSET;
`endif
`ifdef ENABLE_FFE_F0_EXTENDED_DM
reg [9:0] CurrentSegment_offset;
reg DataMem2ReadAddress_MSB_r1;
`endif
`ifdef ENABLE_FFE_F0_SINGLE_DM
reg [31:16] WriteData_latched;
reg sig37_latched;
`endif
// sync the timestamp to this clock domain
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
`else
always @(posedge ClockIn) begin
`endif
TimeStamp_r1 <= TimeStampIn;
TimeStamp_r2 <= TimeStamp_r1;
if (TimeStamp_r1 == TimeStamp_r2)
TimeStamp_synced <= TimeStamp_r2;
else
TimeStamp_synced <= TimeStamp_synced;
end
FFE_ALU u_FFE_ALU (
.xReadData1 ( Mem1ReadDataToALU[31:0] ),
.xReadData2 ( Mem2ReadDataToALU[31:0] ),
.signals ( Signals ),
.ClockIn ( ClockIn ),
.Clock_x2In ( Clock_x2In ),
.FFE_clock_halfperiod ( FFE_clock_halfperiod ),
.MultClockIn ( MultClockIn ),
.MultStateIn ( MultStateIn ),
.TimeStampIn ( TimeStamp_synced ),
.MailboxIn ( MailboxIn ),
.SM_InterruptIn ( SM_InterruptIn ),
.xIndexRegister ( xIndexRegister ),
.xWriteData ( xWriteData ),
.xJumpFlag ( xJumpFlag ),
.Save_BG_registers ( Save_BG_registers ),
.Restore_BG_registers ( Restore_BG_registers ),
.mult_in1 ( mult_in1 ),
.mult_in2 ( mult_in2 ),
.mult_enable ( mult_enable ),
.mult_out ( mult_out )
);
decodeMicroOpCode U_decodeMicroOpCode (
.MicroOpCode ( MicroOpCode ),
.Signals ( Signals )
);
// Fetch Micro OpCode from Control Memory
// then needs to be decoded for the various control signals to the ALU (these are called 'signals')
assign MicroOpCode = BusyOut_reg ? ControlMemDataIn[8:0] : 9'b0; // xMicroOpCode (hold at zero if FFE is not running because of single port ASSP RAMs
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
// 4k CM
assign xJumpAddress = ControlMemDataIn[20:9];
`else
// 2k CM
assign xJumpAddress = ControlMemDataIn[19:9];
`endif
// standard (legacy) control/address signals for the DM's
assign DataMem1ReadEnable_std = Signals[20];
assign DataMem2ReadEnable_std = Signals[21];
assign DataMem1WriteEnable_std = Disable_DataMem_WrEn ? 1'b0 : (Signals[22] && BusyOut_reg);
assign DataMem2WriteEnable_std = Disable_DataMem_WrEn ? 1'b0 : (Signals[23] && BusyOut_reg);
assign DataMem1WriteAddressOut_std = Signals[34] ? (ControlMemDataIn[17:9] + xIndexRegister) : ControlMemDataIn[17:9];
assign DataMem2WriteAddressOut_std = Signals[34] ? (ControlMemDataIn[17:9] + xIndexRegister) : ControlMemDataIn[17:9];
assign DataMem1ReadAddressOut_std = Signals[28] ? (ControlMemDataIn[26:18] + xIndexRegister) : ControlMemDataIn[26:18];
assign DataMem2ReadAddressOut_std = Signals[29] ? (ControlMemDataIn[35:27] + xIndexRegister) : ControlMemDataIn[35:27];
// translate DM read/write addresses if an extended-length DM is specified
`ifdef ENABLE_FFE_F0_EXTENDED_DM
// extended-length DM
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
CurrentSegment_offset <= 0;
else
if (Signals[44] && FFE_clock_halfperiod) // seg_offset being written
CurrentSegment_offset <= ControlMemDataIn[32:23];
`else
always @(posedge ClockIn or posedge ResetIn)
if (ResetIn)
CurrentSegment_offset <= 0;
else
if (Signals[44]) // seg_offset being written
CurrentSegment_offset <= ControlMemDataIn[32:23];
`endif
// translate addresses to handle extended data memory(ies)
assign DataMem1WriteAddressOut_trans = (DataMem1WriteAddressOut_std < Segment0_offset) ?
{1'b0, DataMem1WriteAddressOut_std[8:0]} :
({1'b0, DataMem1WriteAddressOut_std} + {1'b0, CurrentSegment_offset});
assign DataMem2WriteAddressOut_trans = (DataMem2WriteAddressOut_std < Segment0_offset) ?
{1'b0, DataMem2WriteAddressOut_std[8:0]} :
({1'b0, DataMem2WriteAddressOut_std} + {1'b0, CurrentSegment_offset});
assign DataMem1ReadAddressOut_trans = (DataMem1ReadAddressOut_std < Segment0_offset) ?
{1'b0, DataMem1ReadAddressOut_std[8:0]} :
({1'b0, DataMem1ReadAddressOut_std} + {1'b0, CurrentSegment_offset});
assign DataMem2ReadAddressOut_trans = (DataMem2ReadAddressOut_std < Segment0_offset) ?
{1'b0, DataMem2ReadAddressOut_std[8:0]} :
({1'b0, DataMem2ReadAddressOut_std} + {1'b0, CurrentSegment_offset});
`else
// standard-length DM (could be single or double)
assign DataMem1WriteAddressOut_trans = {1'b0, DataMem1WriteAddressOut_std};
assign DataMem2WriteAddressOut_trans = {1'b0, DataMem2WriteAddressOut_std};
assign DataMem1ReadAddressOut_trans = {1'b0, DataMem1ReadAddressOut_std};
assign DataMem2ReadAddressOut_trans = {1'b0, DataMem2ReadAddressOut_std};
`endif
// mux the DM1/DM2 addresses into a single logical DM1 address if a single-DM design is specified
`ifdef ENABLE_FFE_F0_SINGLE_DM
// single DM
// keep track of the half-period (0 or 1) within a single FFE clock, by using the 2x FFE clock.
// FFE_clock_halfperiod should be 0 when the 1x clock is low, 1 when the 1x clock is high (it's registered here to help eliminate timing issues).
buff buff_clockin_dly1 (.A(ClockIn), .Q(ClockIn_dly1));
buff buff_clockin_dly2 (.A(ClockIn_dly1), .Q(ClockIn_dly2));
buff buff_clockin_dly3 (.A(ClockIn_dly2), .Q(ClockIn_dly3));
//pragma attribute buff_clockin_dly1 dont_touch true
//pragma attribute buff_clockin_dly2 dont_touch true
//pragma attribute buff_clockin_dly3 dont_touch true
assign #3 ClockIn_dly4 = ClockIn_dly3;
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
FFE_clock_halfperiod <= 0;
else
FFE_clock_halfperiod <= #1 ClockIn_dly4;
/*
if (BusyOut_reg)
FFE_clock_halfperiod <= !FFE_clock_halfperiod;
else
FFE_clock_halfperiod <= 0;
*/
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn) begin
DataMem2ReadAddressOut_trans_hold <= 0;
DataMem2ReadEnable_std_hold <= 0;
end
else begin
if (!FFE_clock_halfperiod) begin
DataMem2ReadAddressOut_trans_hold <= DataMem2ReadAddressOut_trans;
DataMem2ReadEnable_std_hold <= DataMem2ReadEnable_std;
end
end
// on half-period 0, drive the DM1 read address and read enable
// on half-period 1, drive the DM2 read address and read enable
// drive the write address on both half-periods, and the write enable on half-period 0
assign DataMem1ReadAddressOut_mux = FFE_clock_halfperiod ? DataMem2ReadAddressOut_trans_hold : DataMem1ReadAddressOut_trans;
assign DataMem1ReadEnable_mux = FFE_clock_halfperiod ? DataMem2ReadEnable_std_hold : DataMem1ReadEnable_std;
assign DataMem1WriteAddressOut_mux = DataMem1WriteAddressOut_trans; // note: DM1 write address = DM2 write address
assign DataMem1WriteEnable_mux = FFE_clock_halfperiod ? 0 : DataMem1WriteEnable_std;
`else
// double DM
// FFE_clock_halfperiod should never be used in this case. Assign it to 0.
always @(*)
FFE_clock_halfperiod <= 0;
`endif
// split the muxed RAM control signals across both physical memories if an extended-depth DM is specified.
// (if an extended-depth DM is specified, it must also be a single DM)
`ifdef ENABLE_FFE_F0_EXTENDED_DM
// extended-length DM
// note that the DM2 "_mux" signals are not defined, since it's assumed that an extended-length DM is also a single-DM
assign DataMem1ReadAddressOut_split = DataMem1ReadAddressOut_mux;
assign DataMem1ReadEnable_split = (DataMem1ReadAddressOut_mux[9] == 1'b0) ? DataMem1ReadEnable_mux : 1'b0;
assign DataMem1WriteAddressOut_split = DataMem1WriteAddressOut_mux;
// assign DataMem1WriteEnable_split = (DataMem1WriteAddressOut_mux[9] == 1'b0) ? DataMem1WriteEnable_split : 1'b0; // original
assign DataMem1WriteEnable_split = (DataMem1WriteAddressOut_mux[9] == 1'b0) ? DataMem1WriteEnable_mux : 1'b0; // Anthony Le 11-01-2014
assign DataMem2ReadAddressOut_split = DataMem1ReadAddressOut_mux;
assign DataMem2ReadEnable_split = (DataMem1ReadAddressOut_mux[9] == 1'b1) ? DataMem1ReadEnable_mux : 1'b0;
assign DataMem2WriteAddressOut_split = DataMem1WriteAddressOut_mux;
// assign DataMem2WriteEnable_split = (DataMem1WriteAddressOut_mux[9] == 1'b1) ? DataMem1WriteEnable_split : 1'b0; // original
assign DataMem2WriteEnable_split = (DataMem1WriteAddressOut_mux[9] == 1'b1) ? DataMem1WriteEnable_mux : 1'b0; // Anthony Le 11-01-2014
`endif
// drive the outputs for the DM control/address
`ifdef ENABLE_FFE_F0_EXTENDED_DM
// extended-length DM (must be single DM as well)
// must use the translated then muxed then split signals...
assign DataMem1ReadEnable = DataMem1ReadEnable_split;
assign DataMem1WriteEnable = DataMem1WriteEnable_split;
assign DataMem1WriteAddressOut = DataMem1WriteAddressOut_split;
assign DataMem1ReadAddressOut = DataMem1ReadAddressOut_split;
assign DataMem2ReadEnable = DataMem2ReadEnable_split;
assign DataMem2WriteEnable = DataMem2WriteEnable_split;
assign DataMem2WriteAddressOut = DataMem2WriteAddressOut_split;
assign DataMem2ReadAddressOut = DataMem2ReadAddressOut_split;
`else
// standard-length DM
`ifdef ENABLE_FFE_F0_SINGLE_DM
// standard-length single DM
// must use the non-translated then muxed signals
// note that physical DM2 is unused, so those outputs are grounded.
assign DataMem1ReadEnable = DataMem1ReadEnable_mux;
assign DataMem1WriteEnable = DataMem1WriteEnable_mux;
assign DataMem1WriteAddressOut = DataMem1WriteAddressOut_mux;
assign DataMem1ReadAddressOut = DataMem1ReadAddressOut_mux;
assign DataMem2ReadEnable = 0;
assign DataMem2WriteEnable = 0;
assign DataMem2WriteAddressOut = 0;
assign DataMem2ReadAddressOut = 0;
`else
// standard-length double DM (legacy)
// use the standard signals
assign DataMem1WriteAddressOut = {1'b0, DataMem1WriteAddressOut_std};
assign DataMem2WriteAddressOut = {1'b0, DataMem2WriteAddressOut_std};
assign DataMem1ReadAddressOut = {1'b0, DataMem1ReadAddressOut_std};
assign DataMem2ReadAddressOut = {1'b0, DataMem2ReadAddressOut_std};
assign DataMem1ReadEnable = DataMem1ReadEnable_std;
assign DataMem2ReadEnable = DataMem2ReadEnable_std;
assign DataMem1WriteEnable = DataMem1WriteEnable_std;
assign DataMem2WriteEnable = DataMem2WriteEnable_std;
`endif
`endif
`ifdef ENABLE_FFE_F0_SINGLE_DM
// single DM, extended or standard length
// hold the write data so it can be written to the CM FIFO or SM Mem correctly, when a single DM is used
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn) begin
WriteData_latched <= 0;
sig37_latched <= 0;
end
else begin
if (!FFE_clock_halfperiod) begin
sig37_latched <= Signals[37];
//if (!FFE_clock_halfperiod && (CMWriteEnableOut || SensorMemWriteEnableOut || Signals[36]))
if (Signals[30] || Signals[40] || Signals[36]) // CM write or SM write or Interrupt msg write
WriteData_latched <= xWriteData[31:16];
end
end
//assign CMWriteDataOut = {1'b0, WriteData_latched[31:24], Signals[37], WriteData_latched[23:16]};
assign CMWriteDataOut = {1'b0, WriteData_latched[31:24], sig37_latched, WriteData_latched[23:16]};
assign SensorMemWriteDataOut = WriteData_latched[24:16];
`else
// double DM (legacy)
assign CMWriteDataOut = {1'b0, xWriteData[31:24], Signals[37], xWriteData[23:16]};
assign SensorMemWriteDataOut = xWriteData[24:16];
`endif
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
// 4k CM
// this is done to make sure that all of these signals are stable when the 1x clock occurs.
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn) begin
SensorMemReadEnable_reg <= 0;
SensorMemWriteEnable_reg <= 0;
SensorMemReadAddress_reg <= 0;
SensorMemWriteAddress_reg <= 0;
CMWriteEnable_reg <= 0;
end
else begin
if (!FFE_clock_halfperiod ) begin
SensorMemReadEnable_reg <= DataMem1ReadEnable_std;
SensorMemWriteEnable_reg <= Disable_DataMem_WrEn ? 1'b0 : (Signals[40] && BusyOut_reg);
SensorMemReadAddress_reg <= Signals[28] ? (ControlMemDataIn[27:18] + xIndexRegister) : ControlMemDataIn[27:18];
SensorMemWriteAddress_reg <= Signals[34] ? (ControlMemDataIn[18:9] + xIndexRegister) : ControlMemDataIn[18:9];
CMWriteEnable_reg <= Disable_DataMem_WrEn ? 1'b0 : (Signals[30] && BusyOut_reg); // Write enable to CM FIFO
end
end
assign SensorMemReadEnableOut = SensorMemReadEnable_reg;
assign SensorMemWriteEnableOut = SensorMemWriteEnable_reg;
assign SensorMemReadAddressOut = SensorMemReadAddress_reg;
assign SensorMemWriteAddressOut = SensorMemWriteAddress_reg;
assign CMWriteEnableOut = CMWriteEnable_reg;
`else
// 2k CM
assign SensorMemReadEnableOut = DataMem1ReadEnable_std;
assign SensorMemWriteEnableOut = Disable_DataMem_WrEn ? 1'b0 : (Signals[40] && BusyOut_reg);
assign SensorMemReadAddressOut = (Signals[28] ? (ControlMemDataIn[27:18] + xIndexRegister) : ControlMemDataIn[27:18]);
assign SensorMemWriteAddressOut = Signals[34] ? (ControlMemDataIn[18:9] + xIndexRegister) : ControlMemDataIn[18:9];
assign CMWriteEnableOut = Disable_DataMem_WrEn ? 1'b0 : (Signals[30] && BusyOut_reg); // Write enable to CM FIFO
`endif
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
// 4k CM
assign ControlMemAddressOut = xPC;
`else
// 2k CM
assign ControlMemAddressOut = {1'b0, xPC};
`endif
assign DataMem1WriteDataOut = {4'b0000,xWriteData};
assign DataMem2WriteDataOut = {4'b0000,xWriteData};
// latch the read data from the DM(s)
`ifdef ENABLE_FFE_F0_SINGLE_DM
`ifdef ENABLE_FFE_F0_EXTENDED_DM
// extended-length single-DM
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
DataMem1ReadAddressOut_trans_MSB_r1 <= 0;
else
if (!FFE_clock_halfperiod)
DataMem1ReadAddressOut_trans_MSB_r1 <= DataMem1ReadAddressOut_trans[9];
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
Mem1ReadData_latched <= 0;
else
if (FFE_clock_halfperiod)
Mem1ReadData_latched <= DataMem1ReadAddressOut_trans_MSB_r1 ? Mem2ReadData : Mem1ReadData; // read from the correct physical DM
// store the (logical) DM2 read address' MSB, so it can be used on the following clock to select the correct physical DM
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
DataMem2ReadAddress_MSB_r1 <= 0;
else
if (FFE_clock_halfperiod)
DataMem2ReadAddress_MSB_r1 <= DataMem2ReadAddressOut_trans[9];
`else
always @(posedge ClockIn or posedge ResetIn)
if (ResetIn)
DataMem2ReadAddress_MSB_r1 <= 0;
else
DataMem2ReadAddress_MSB_r1 <= DataMem2ReadAddressOut_trans[9];
`endif
always @(*)
Mem2ReadData_latched <= DataMem2ReadAddress_MSB_r1 ? Mem2ReadData : Mem1ReadData; // read from the correct physical DM
// note that Mem2ReadData_latched will only be valid on the first half-period
// note that ReadData2 can be registered as well, to make FFE clock-to-clock timing easier (at the cost of more FFs).
`else
// standard-length single-DM, latch & hold at the appropriate half-periods
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
Mem1ReadData_latched <= 0;
else
if (FFE_clock_halfperiod)
Mem1ReadData_latched <= Mem1ReadData;
else
Mem1ReadData_latched <= Mem1ReadData_latched;
always @(*)
Mem2ReadData_latched <= Mem1ReadData;
// note that ReadData2 can be registered as well, to make FFE clock-to-clock timing easier (at the cost of more FFs).
`endif
`else
// standard-length double-DM, pass-thru
always @(*) begin
Mem1ReadData_latched <= Mem1ReadData;
Mem2ReadData_latched <= Mem2ReadData;
end
`endif
assign Mem1ReadDataX = Mem1ReadData_latched[31:0];
//a mux that switches between data read from FFEDM2 or SMSM
assign Mem2ReadDataX = Signals[27] ? {SensorMemReadDataIn[16:9], SensorMemReadDataIn[7:0], 16'b0} : Mem2ReadData_latched[31:0];
assign Mem1ReadDataToALU = Mem1ReadDataX;
assign Mem2ReadDataToALU = Mem2ReadDataX;
// toggle StartSM each time Signals[31] is active
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
if (ResetIn)
StartSM_reg <= 0;
else
if (FFE_clock_halfperiod && Signals[31])
StartSM_reg <= !StartSM_reg;
else
StartSM_reg <= StartSM_reg;
`else
always @(posedge ClockIn or posedge ResetIn)
if (ResetIn)
StartSM_reg <= 0;
else
if (Signals[31])
StartSM_reg <= !StartSM_reg;
else
StartSM_reg <= StartSM_reg;
`endif
assign StartSMOut = StartSM_reg;
// de-glitch the interrupt msg signal since it comes out of the decoder and data mem
`ifdef ENABLE_FFE_F0_SINGLE_DM
// single DM
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
// 4k CM
always @(posedge Clock_x2In)
InterruptMsg_reg <= (FFE_clock_halfperiod && Signals[36]) ? WriteData_latched[23:16] : 8'b0;
`else
// 2k CM
always @(posedge ClockIn)
InterruptMsg_reg <= Signals[36] ? WriteData_latched[23:16] : 8'b0;
`endif
`else
// double DM, legacy behavior
always @(posedge ClockIn)
InterruptMsg_reg <= Signals[36] ? xWriteData[23:16] : 8'b0;
`endif
assign InterruptMsgOut = InterruptMsg_reg;
// sync to local clock
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In) begin
`else
always @(posedge ClockIn) begin
`endif
Start_r1 <= StartIn;
Start_r2 <= Start_r1;
Start_r3 <= Start_r2;
end
assign Start_detected = (Start_r1 != Start_r2) || (Start_r2 != Start_r3);
// Program Counter to step through the Control Memory
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn) begin
`else
always @(posedge ClockIn or posedge ResetIn) begin
`endif
if (ResetIn) begin
xPC <= 0;
BusyOut_reg <= 1'b0;
BusyOut_r1 <= 1'b0;
ControlMemReadEnableOut <= 1'b0;
SMOverrunOut <= 1'b0;
end else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
begin
BusyOut_r1 <= BusyOut_reg;
if (BusyOut_reg && BusyOut_r1) begin // make sure the 1st control word appears on the RAM outputs... requires one clock cycle after the read enable is turned on.
if (!Signals[32]) begin // !Signals[32] = continue running = !STOP
if (Restore_BG_registers)
xPC <= PC_BG;
else
if (Clear_PC)
xPC <= 0;
else
// hold the PC while switching threads
if (BG_active &&
((Start_detected || BGsave_pending) ||
(BGcontinue_pending && (Thread_switch_cnt != THREAD_SWITCH_CNT_DONE))))
xPC <= xPC;
else
if (xJumpFlag)
xPC <= xJumpAddress;
else
xPC <= xPC + 1;
end else begin // Signals[32] = STOP
xPC <= 0;
if (!BG_active) begin // FG mode
BusyOut_reg <= 1'b0;
ControlMemReadEnableOut <= 1'b0;
end else begin // BG mode
ControlMemReadEnableOut <= 1'b1;
if (BGstop_pending && (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE) && !Start_pending && !Start_detected)
BusyOut_reg <= 1'b0;
else
BusyOut_reg <= 1'b1;
end
end
end else // new start condition not detected, keep running
if (Start_detected) begin
if (SMBusyIn) begin
SMOverrunOut <= 1'b1;
end else begin
BusyOut_reg <= 1'b1;
ControlMemReadEnableOut <= 1'b1;
end
end
end
end
assign BusyOut = BusyOut_reg;
// --- BG thread support
// Signals[42] = SetBGflag (instruction modifier)
// Signals[43] = BGcontinue (instruction)
// Start_pending, flag to latch the start event, in case it happens right as we're switching to the BG thread or while running the BG thread.
// This needs to be latched so the FG thread can be started immediately once we've switched out of the BG thread.
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
Start_pending <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
case (Start_pending)
1'b0: if (Start_detected && // start detected AND...
(Signals[42] || // ...SetBGflag active (about to start or continue BG)...OR...
BG_active)) // ...BG active (switching to BG, running BG, about to stop/end BG, stopping BG)
Start_pending <= 1;
1'b1: if (!BG_active) // clear this flag when BG_active goes away
Start_pending <= 0;
endcase
// BG_pending counter, used instead of individual state machines for each type of context switch
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
Thread_switch_cnt <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
if (BGsave_pending || BGcontinue_pending || BGstop_pending)
if (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE)
Thread_switch_cnt <= 0;
else
Thread_switch_cnt <= Thread_switch_cnt + 1;
else
Thread_switch_cnt <= 0;
// BGcontinue_pending, flag that goes active while resuming the BG thread (BGcontinue instruction)
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
BGcontinue_pending <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
case (BGcontinue_pending)
1'b0: if (Signals[43])
BGcontinue_pending <= 1;
1'b1: if (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE)
BGcontinue_pending <= 0;
endcase
// BGsave_pending, flag that goes active while saving the state of the BG thread (BG_continue or BG thread interrupted by the sample timer)
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
BGsave_pending <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
case (BGsave_pending)
1'b0: if (BG_active && // in the BG thread...AND...
(Start_detected || // ...started detected...OR...
(BGcontinue_pending && (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE) && Start_pending))) // ...about to complete BGcontinue AND start was detected
BGsave_pending <= 1;
1'b1: if (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE)
BGsave_pending <= 0;
endcase
// BGstop_pending, flag that goes active while stopping the BG thread (normal completion)
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
BGstop_pending <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
case (BGstop_pending)
1'b0: if (BG_active && Signals[32])
BGstop_pending <= 1;
1'b1: if (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE)
BGstop_pending <= 0;
endcase
// BG_active, flag that is active while switching to, in, or switching from, the BG thread
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
BG_active <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
case (BG_active)
1'b0: if (Signals[42]) // SetBGactive (entering BG mode, either via start BG or continue BG)
BG_active <= 1;
1'b1: if ((BGsave_pending || BGstop_pending) && (Thread_switch_cnt == THREAD_SWITCH_CNT_DONE)) // done switching out of BG mode
BG_active <= 0;
endcase
// Control signal used to save the BG copy of the PC and ALU flags
assign Save_BG_registers = (BGsave_pending && (Thread_switch_cnt == 1));
// clock-by-clock sequence of events:
// {BGsave_pending,Thread_switch_cnt}
// 0,0 - Start detected, last BG instruction, hold PC
// 1,0 - hold PC, disable DataMemWrEn
// 1,1 - hold PC, save PC & flags (Save_BG_registers active), disable DataMemWrEn
// 1,2 - clear PC, disable DataMemWrEn
// 1,3 - hold PC (driving into CodeMem), disable DataMemWrEn
// 1,4 - hold PC (CodeMem available, driving DataMem), disable DataMemWrEn
// 1,5 - hold PC (DataMem available), disable DataMemWrEn
// 1,6 - hold PC (extraneous), disable DataMemWrEn
// 1,7 - hold PC (extraneous), disable DataMemWrEn
// 0,0 - continue running normally (now in FG thread)
// Control signal used to restore the BG state of the PC and ALU flags
assign Restore_BG_registers = (BGcontinue_pending && (Thread_switch_cnt == 1));
// clock-by-clock sequence of events:
// {BGcontinue_pending,Thread_switch_cnt} - action(s)
// 0,0 - BGcontinue();
// 1,0 - NOP;, disable DataMemWrEn
// 1,1 - load PC & flags (Restore_BG_registers active), disable DataMemWrEn
// 1,2 - hold PC (driving into CodeMem), disable DataMemWrEn
// 1,3 - hold PC (CodeMem available, driving DataMem), disable DataMemWrEn
// 1,4 - hold PC (DataMem available), disable DataMemWrEn
// 1,5 - hold PC (extraneous), disable DataMemWrEn
// 1,6 - hold PC (extraneous), disable DataMemWrEn
// 1,7 - increment PC, disable DataMemWrEn
// 0,0 - continue running normally (now in BG thread)
// Control signal used to reset the PC (during BGstop or BGsave)
assign Clear_PC = ((BGsave_pending && (Thread_switch_cnt == 2)) || (BGstop_pending));
// Control signal used to disable the FFE DataMem write enable, while resuming the BG thread
assign Disable_DataMem_WrEn = (BGcontinue_pending);
// BG copy of the PC
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
always @(posedge Clock_x2In or posedge ResetIn)
`else
always @(posedge ClockIn or posedge ResetIn)
`endif
if (ResetIn)
PC_BG <= 0;
else
`ifdef ENABLE_FFE_F0_CM_SIZE_4K
if (FFE_clock_halfperiod)
`endif
if (Save_BG_registers)
PC_BG <= xPC;
else
PC_BG <= PC_BG;
// test points
assign TP1 = 0;
assign TP2 = 0;
assign TP3 = 0;
endmodule

View File

@ -0,0 +1,59 @@
`timescale 1ns / 10ps
// algorithm file = 'ulpsh_s2_main_JB4_BMI160_AK09911_PD.alg'
// UlpshType = S2_1KDM
module decodeMicroOpCode (MicroOpCode, Signals);
input [8:0] MicroOpCode;
output [45:0] Signals;
wire [45:0] Signals;
assign Signals[0] = (MicroOpCode == 9'h00e) || 0;
assign Signals[1] = (MicroOpCode == 9'h012) || (MicroOpCode == 9'h013) || 0;
assign Signals[2] = 0;
assign Signals[3] = 0;
assign Signals[4] = (MicroOpCode == 9'h038) || 0;
assign Signals[5] = (MicroOpCode == 9'h016) || (MicroOpCode == 9'h017) || (MicroOpCode == 9'h021) || (MicroOpCode == 9'h034) || (MicroOpCode == 9'h035) || (MicroOpCode == 9'h036) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h040) || (MicroOpCode == 9'h041) || (MicroOpCode == 9'h042) || (MicroOpCode == 9'h045) || (MicroOpCode == 9'h04a) || (MicroOpCode == 9'h04e) || (MicroOpCode == 9'h04f) || 0;
assign Signals[6] = (MicroOpCode == 9'h00a) || (MicroOpCode == 9'h014) || (MicroOpCode == 9'h020) || (MicroOpCode == 9'h024) || (MicroOpCode == 9'h026) || (MicroOpCode == 9'h027) || (MicroOpCode == 9'h028) || (MicroOpCode == 9'h02d) || (MicroOpCode == 9'h033) || (MicroOpCode == 9'h037) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h039) || (MicroOpCode == 9'h03e) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || (MicroOpCode == 9'h050) || 0;
assign Signals[7] = (MicroOpCode == 9'h00a) || (MicroOpCode == 9'h014) || (MicroOpCode == 9'h020) || (MicroOpCode == 9'h024) || (MicroOpCode == 9'h026) || (MicroOpCode == 9'h027) || (MicroOpCode == 9'h028) || (MicroOpCode == 9'h02d) || (MicroOpCode == 9'h033) || (MicroOpCode == 9'h035) || (MicroOpCode == 9'h036) || (MicroOpCode == 9'h037) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h039) || (MicroOpCode == 9'h03e) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04a) || (MicroOpCode == 9'h050) || 0;
assign Signals[8] = (MicroOpCode == 9'h00a) || (MicroOpCode == 9'h024) || (MicroOpCode == 9'h026) || (MicroOpCode == 9'h033) || (MicroOpCode == 9'h037) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h03b) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04a) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || 0;
assign Signals[9] = (MicroOpCode == 9'h027) || (MicroOpCode == 9'h028) || (MicroOpCode == 9'h039) || (MicroOpCode == 9'h03b) || (MicroOpCode == 9'h03e) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || 0;
assign Signals[10] = (MicroOpCode == 9'h007) || (MicroOpCode == 9'h008) || (MicroOpCode == 9'h009) || (MicroOpCode == 9'h00a) || (MicroOpCode == 9'h00d) || (MicroOpCode == 9'h00e) || (MicroOpCode == 9'h010) || (MicroOpCode == 9'h012) || (MicroOpCode == 9'h013) || (MicroOpCode == 9'h014) || (MicroOpCode == 9'h020) || (MicroOpCode == 9'h022) || (MicroOpCode == 9'h024) || (MicroOpCode == 9'h025) || (MicroOpCode == 9'h026) || (MicroOpCode == 9'h036) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h03a) || (MicroOpCode == 9'h03c) || (MicroOpCode == 9'h03d) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h040) || (MicroOpCode == 9'h041) || (MicroOpCode == 9'h042) || (MicroOpCode == 9'h046) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04a) || (MicroOpCode == 9'h04e) || (MicroOpCode == 9'h04f) || (MicroOpCode == 9'h050) || 0;
assign Signals[11] = (MicroOpCode == 9'h037) || (MicroOpCode == 9'h049) || 0;
assign Signals[12] = (MicroOpCode == 9'h03b) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || 0;
assign Signals[13] = (MicroOpCode == 9'h027) || (MicroOpCode == 9'h028) || (MicroOpCode == 9'h039) || (MicroOpCode == 9'h03b) || (MicroOpCode == 9'h03e) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || 0;
assign Signals[14] = 0;
assign Signals[15] = (MicroOpCode == 9'h038) || (MicroOpCode == 9'h039) || (MicroOpCode == 9'h04a) || 0;
assign Signals[16] = (MicroOpCode == 9'h034) || (MicroOpCode == 9'h035) || (MicroOpCode == 9'h048) || 0;
assign Signals[17] = (MicroOpCode == 9'h00f) || (MicroOpCode == 9'h011) || (MicroOpCode == 9'h015) || (MicroOpCode == 9'h01c) || (MicroOpCode == 9'h029) || 0;
assign Signals[18] = (MicroOpCode == 9'h00b) || (MicroOpCode == 9'h00f) || (MicroOpCode == 9'h01f) || (MicroOpCode == 9'h029) || 0;
assign Signals[19] = (MicroOpCode == 9'h015) || (MicroOpCode == 9'h01f) || (MicroOpCode == 9'h029) || (MicroOpCode == 9'h031) || 0;
assign Signals[20] = (MicroOpCode == 9'h001) || (MicroOpCode == 9'h002) || (MicroOpCode == 9'h009) || (MicroOpCode == 9'h00c) || (MicroOpCode == 9'h016) || (MicroOpCode == 9'h020) || (MicroOpCode == 9'h025) || (MicroOpCode == 9'h026) || (MicroOpCode == 9'h02c) || (MicroOpCode == 9'h02d) || (MicroOpCode == 9'h032) || (MicroOpCode == 9'h033) || (MicroOpCode == 9'h034) || (MicroOpCode == 9'h035) || (MicroOpCode == 9'h037) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h03c) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h042) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h048) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04a) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04d) || (MicroOpCode == 9'h04f) || 0;
assign Signals[21] = (MicroOpCode == 9'h004) || (MicroOpCode == 9'h008) || (MicroOpCode == 9'h009) || (MicroOpCode == 9'h00c) || (MicroOpCode == 9'h010) || (MicroOpCode == 9'h013) || (MicroOpCode == 9'h016) || (MicroOpCode == 9'h019) || (MicroOpCode == 9'h01b) || (MicroOpCode == 9'h020) || (MicroOpCode == 9'h023) || (MicroOpCode == 9'h026) || (MicroOpCode == 9'h028) || (MicroOpCode == 9'h02a) || (MicroOpCode == 9'h02c) || (MicroOpCode == 9'h02d) || (MicroOpCode == 9'h02e) || (MicroOpCode == 9'h030) || (MicroOpCode == 9'h032) || (MicroOpCode == 9'h033) || (MicroOpCode == 9'h034) || (MicroOpCode == 9'h035) || (MicroOpCode == 9'h037) || (MicroOpCode == 9'h038) || (MicroOpCode == 9'h03a) || (MicroOpCode == 9'h03c) || (MicroOpCode == 9'h03d) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h041) || (MicroOpCode == 9'h042) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h045) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h048) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04a) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04d) || (MicroOpCode == 9'h04f) || (MicroOpCode == 9'h050) || 0;
assign Signals[22] = (MicroOpCode == 9'h002) || (MicroOpCode == 9'h003) || (MicroOpCode == 9'h007) || (MicroOpCode == 9'h008) || (MicroOpCode == 9'h009) || (MicroOpCode == 9'h00d) || (MicroOpCode == 9'h00e) || (MicroOpCode == 9'h010) || (MicroOpCode == 9'h012) || (MicroOpCode == 9'h013) || (MicroOpCode == 9'h014) || (MicroOpCode == 9'h016) || (MicroOpCode == 9'h017) || (MicroOpCode == 9'h020) || (MicroOpCode == 9'h022) || (MicroOpCode == 9'h024) || (MicroOpCode == 9'h025) || (MicroOpCode == 9'h027) || (MicroOpCode == 9'h028) || (MicroOpCode == 9'h02a) || (MicroOpCode == 9'h02b) || (MicroOpCode == 9'h02c) || (MicroOpCode == 9'h02d) || (MicroOpCode == 9'h02e) || (MicroOpCode == 9'h02f) || (MicroOpCode == 9'h030) || (MicroOpCode == 9'h032) || (MicroOpCode == 9'h033) || (MicroOpCode == 9'h036) || (MicroOpCode == 9'h037) || (MicroOpCode == 9'h039) || (MicroOpCode == 9'h03a) || (MicroOpCode == 9'h03b) || (MicroOpCode == 9'h03c) || (MicroOpCode == 9'h03d) || (MicroOpCode == 9'h03e) || (MicroOpCode == 9'h03f) || (MicroOpCode == 9'h040) || (MicroOpCode == 9'h041) || (MicroOpCode == 9'h042) || (MicroOpCode == 9'h043) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h045) || (MicroOpCode == 9'h047) || (MicroOpCode == 9'h049) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || (MicroOpCode == 9'h04e) || (MicroOpCode == 9'h04f) || (MicroOpCode == 9'h050) || 0;
assign Signals[23] = 0;
assign Signals[24] = 0;
assign Signals[25] = (MicroOpCode == 9'h021) || 0;
assign Signals[26] = (MicroOpCode == 9'h021) || 0;
assign Signals[27] = (MicroOpCode == 9'h002) || (MicroOpCode == 9'h003) || 0;
assign Signals[28] = (MicroOpCode == 9'h04d) || 0;
assign Signals[29] = (MicroOpCode == 9'h023) || (MicroOpCode == 9'h02e) || (MicroOpCode == 9'h03d) || (MicroOpCode == 9'h04d) || 0;
assign Signals[30] = (MicroOpCode == 9'h018) || (MicroOpCode == 9'h019) || (MicroOpCode == 9'h01a) || (MicroOpCode == 9'h01b) || 0;
assign Signals[31] = (MicroOpCode == 9'h006) || 0;
assign Signals[32] = (MicroOpCode == 9'h01e) || 0;
assign Signals[33] = (MicroOpCode == 9'h039) || (MicroOpCode == 9'h03e) || (MicroOpCode == 9'h044) || (MicroOpCode == 9'h04b) || (MicroOpCode == 9'h04c) || 0;
assign Signals[34] = (MicroOpCode == 9'h022) || (MicroOpCode == 9'h02a) || (MicroOpCode == 9'h02b) || (MicroOpCode == 9'h02c) || (MicroOpCode == 9'h03a) || (MicroOpCode == 9'h03c) || (MicroOpCode == 9'h03d) || (MicroOpCode == 9'h04e) || (MicroOpCode == 9'h04f) || 0;
assign Signals[35] = (MicroOpCode == 9'h027) || (MicroOpCode == 9'h028) || 0;
assign Signals[36] = (MicroOpCode == 9'h01d) || 0;
assign Signals[37] = (MicroOpCode == 9'h018) || (MicroOpCode == 9'h019) || 0;
assign Signals[38] = (MicroOpCode == 9'h00d) || (MicroOpCode == 9'h00e) || (MicroOpCode == 9'h010) || 0;
assign Signals[39] = 0;
assign Signals[40] = (MicroOpCode == 9'h005) || 0;
assign Signals[41] = 0;
assign Signals[42] = 0;
assign Signals[43] = 0;
assign Signals[44] = (MicroOpCode == 9'h01c) || 0;
assign Signals[45] = 0;
endmodule

View File

@ -0,0 +1,70 @@
// -----------------------------------------------------------------------------
// title : Sensor Manager Memory Module
// project : ULP Sensor Hub
// -----------------------------------------------------------------------------
// file : SMEMemoryMux.v
// author : OCTO
// company : QuickLogic Corp
// created : 2012/??/??
// last update : 2014/05/20
// platform : PolarPro III
// standard : Verilog 2001
// -----------------------------------------------------------------------------
// description: The Sensor Manger Memory Mux selects between several sources
// for passing both read and write information.
// -----------------------------------------------------------------------------
// copyright (c) 2013
// -----------------------------------------------------------------------------
// revisions :
// date version author description
// 2014/05/20 1.0 Glen Gomes Updated -> Added support for a second
// memory block by adding
// address bits.
// -----------------------------------------------------------------------------
// Comments: This solution is specifically for use with the QuickLogic
// PolarPro III S2 device.
// -----------------------------------------------------------------------------
`timescale 1ns / 10ps
module SMEMemoryMux (
input Select,
input [9:0] ReadAddressIn0, // Expanded for Rel 0 on 6/18
input [9:0] ReadAddressIn1, // Expanded for Rel 0 on 6/18
output[9:0] ReadAddressOut, // Expanded for Rel 0 on 6/18
input [9:0] WriteAddressIn0,
input [9:0] WriteAddressIn1,
output[9:0] WriteAddressOut,
input [8:0] DataToMemoryIn0,
input [8:0] DataToMemoryIn1,
output[8:0] DataToMemoryOut,
input [17:0] DataFromMemoryIn0,
input [17:0] DataFromMemoryIn1,
output[17:0] DataFromMemoryOut,
input ReadEnableIn0,
input ReadEnableIn1,
output ReadEnableOut,
input WriteEnableIn0,
input WriteEnableIn1,
output WriteEnableOut,
input ReadClockIn0,
input ReadClockIn1,
output ReadClockOut
);
assign ReadAddressOut = (Select) ? ReadAddressIn1 : ReadAddressIn0;
assign WriteAddressOut = (Select) ? WriteAddressIn1 : WriteAddressIn0;
assign DataToMemoryOut = (Select) ? DataToMemoryIn1 : DataToMemoryIn0;
assign DataFromMemoryOut = (Select) ? DataFromMemoryIn1 : DataFromMemoryIn0;
assign ReadEnableOut = (Select) ? ReadEnableIn1 : ReadEnableIn0;
assign WriteEnableOut = (Select) ? WriteEnableIn1 : WriteEnableIn0;
assign ReadClockOut = (Select) ? ReadClockIn1 : ReadClockIn0;
endmodule

View File

@ -0,0 +1,112 @@
// -----------------------------------------------------------------------------
// title : Sensor Manager Memory Module
// project : ULP Sensor Hub
// -----------------------------------------------------------------------------
// file : SMMemory.v
// author : OCTO
// company : QuickLogic Corp
// created : 2012/??/??
// last update : 2014/05/20
// platform : PolarPro III
// standard : Verilog 2001
// -----------------------------------------------------------------------------
// description: The Sensor Manger Memory performs several tasks. These include
// storing Sensor Manager Instructions, Sensor Data, and FFE mail
// box data. This memory consists of several physical memory
// blocks.
// -----------------------------------------------------------------------------
// copyright (c) 2013
// -----------------------------------------------------------------------------
// revisions :
// date version author description
// 2014/05/20 1.0 Glen Gomes Updated -> Added a second memory block
// -----------------------------------------------------------------------------
// Comments: This solution is specifically for use with the QuickLogic
// PolarPro III S2 device.
// -----------------------------------------------------------------------------
`timescale 1ns / 10ps
module SMMemory (
// General Interface
input ResetIn,
input SMBusyIn,
//Read Interface
input [9:0] ReadAddressIn,
output [17:0] ReadDataOut,
input ReadSelectIn,
input ReadClockIn,
//Write Interface
input [9:0] WriteAddressIn,
input [8:0] WriteDataIn,
input WriteSelectIn,
input [9:0] WriteAddressIn_TLC,
input [8:0] WriteDataIn_TLC,
input WriteSelectIn_TLC,
input WriteClockIn,
output [9:0] SMMemory_WriteAddressIn_TLC_o,
output [8:0] SMMemory_ReadAddressIn_o,
output SMMemory_WriteSelectIn_TLC_o,
output SMMemory_ReadSelect_RAM0_o,
output SMMemory_WriteClockIn_o,
output SMMemory_ReadClockIn_o,
output [8:0] SMMemory_WriteDataIn_TLC_o,
input [17:0] SMMemory_ReadDataOut_SRAM_i,
output [9:0] SMMemory_WriteAddressIn_o,
output SMMemory_WriteSelectIn_o,
output SMMemory_ReadSelect_RAM1_o,
output SMMemory_WriteDataIn_o,
input [17:0] SMMemory_ReadDataOut_SRAM1_i
);
// Define local variables
//
wire [17:0] ReadDataOut_SRAM;
wire [17:0] ReadDataOut_SRAM_1;
reg ReadDataSel;
wire ReadSelect_RAM0;
wire ReadSelect_RAM1;
wire SMMemoryBankSelect;
// generate individual read enables
assign ReadSelect_RAM0 = ReadSelectIn && !ReadAddressIn[9];
assign ReadSelect_RAM1 = ReadSelectIn && ReadAddressIn[9];
// Mux the read data
always @(posedge ReadClockIn)
ReadDataSel <= ReadAddressIn[9];
assign SMMemoryBankSelect = SMBusyIn ? ReadAddressIn[9] : ReadDataSel;
assign ReadDataOut = SMMemoryBankSelect ? ReadDataOut_SRAM_1: ReadDataOut_SRAM;
// Instantiate the Memory Blocks
//
assign SMMemory_WriteAddressIn_TLC_o = WriteAddressIn_TLC;
assign SMMemory_ReadAddressIn_o[8:0] = ReadAddressIn[8:0];
assign SMMemory_WriteSelectIn_TLC_o = WriteSelectIn_TLC;
assign SMMemory_ReadSelect_RAM0_o = ReadSelect_RAM0;
assign SMMemory_WriteClockIn_o = WriteClockIn;
assign SMMemory_ReadClockIn_o = ReadClockIn;
assign SMMemory_WriteDataIn_TLC_o = WriteDataIn_TLC;
assign ReadDataOut_SRAM = SMMemory_ReadDataOut_SRAM_i;
assign SMMemory_WriteAddressIn_o = WriteAddressIn;
assign SMMemory_WriteSelectIn_o = WriteSelectIn;
assign SMMemory_ReadSelect_RAM1_o = ReadSelect_RAM1;
assign SMMemory_WriteDataIn_o = WriteDataIn;
assign ReadDataOut_SRAM1 = SMMemory_ReadDataOut_SRAM1_i;
endmodule

View File

@ -0,0 +1,292 @@
/*------------------------------------------------------------------------------
SPI_slave
SPI slave interface, designed for the ULP Sensor Hub.
This module is designed to be as small and simple as possible, while
supporting the ULP Sensor Hub. Only supports SPI Mode 0 (CPOL=CPHA=0)...
which means that input data is latched on the positive edge of SPI_SCLK,
and driven out on the negative edge of SPI_SCLK, with the base value of
SPI_SCLK being 0.
SPI Protocol:
Writes: MOSI: A0 + D0 + D1 + ... + Dn
MISO: xx + xx + xx + ... + xx
Reads: MOSI: A0 + xx + xx + ... + xx
MISO: xx + xx + D0 + ... + Dn
A0 = [1-bit R/W: 1=write, 0=read] + [7-bit address]
Dn = valid data byte
xx = don't-care data byte
It is assumed that the MSb is transmitted first, and the LSb last.
The address is latched, and auto-incremented to support burst reads/writes.
The address, when 0d11, jumps back to 0d07, to support repeated (burst)
reads to/from the memory data port. The logic to re-map addresses above
0d11, that previously was in TLC.v, can now be removed. New registers
above 0d11 may now be added if needed.
This SPI slave requires extra edges on SPI_SCLK to complete any write
operation. This may be accomplished in any one of several ways:
1. A (non-destructive) read should be performed following the last
write operation.
2. SPI_SCLK should be toggled after SPI_SS goes inactive
(a free-running SPI_SCLK would accomplish this).
3. A few extra bits (totaling less than a full byte) should be
transmitted by the master. These extra bits will be ignored by
this core, but will provide the clocks needed to generated the
wr_data_valid pulse.
4. A "null" transaction should be performed following the last
write transaction, during which the address byte is transmitted
by the SPI master followed by 0 bytes of read/write data.
------------------------------------------------------------------------------*/
`timescale 1ns / 1ns
`include "SensorHubDefines.v"
module SPI_slave (
input rst, // system/global reset (active-high)
// SPI interface
input SPI_SCLK, // base value 0 (mode 0)
input SPI_MOSI, // master out, slave in
output SPI_MISO, // master in, slave out
input SPI_SS, // slave select (active-low)
// internal interface
output [6:0] addr,
output [7:0] wr_data,
output wr_data_valid, // active high
input [7:0] rd_data,
output rd_data_ack
);
parameter WR = 1'b1;
parameter RD = 1'b0;
wire rst_int;
reg [7:0] shift_in;
reg [7:0] shift_out;
reg [2:0] bit_cnt, bit_cnt_neg;
reg rcv_byte_valid;
reg addr_has_been_latched;
reg first_data_has_been_latched;
reg [6:0] addr_reg;
reg write_readn;
reg [7:0] write_data_reg;
reg wr_data_valid_reg;
reg write_pending;
reg rd_data_ack_reg;
// rst_int is active when the global rst occurs or when the SPI interface is idle.
// Some logic needs to remain active after a SPI transaction occurs, so rst will be used in those cases.
assign rst_int = rst || SPI_SS;
// input shift register
always @(posedge rst_int or posedge SPI_SCLK)
if (rst_int)
shift_in <= 8'b0;
else
if (!SPI_SS)
shift_in <= {shift_in[6:0], SPI_MOSI};
else
shift_in <= shift_in;
// bit counter
always @(posedge rst_int or posedge SPI_SCLK)
if (rst_int)
bit_cnt <= 3'b0;
else
if (!SPI_SS)
bit_cnt <= bit_cnt + 1;
else
bit_cnt <= 3'b0;
// byte valid, active for 1 clk every time a full byte has been received from the master
always @(posedge rst_int or posedge SPI_SCLK)
if (rst_int)
rcv_byte_valid <= 1'b0;
else
if (rcv_byte_valid) // added to guarantee that rcv_byte_valid is only active for 1 clock
rcv_byte_valid <= 1'b0;
else
if (!SPI_SS && (bit_cnt == 3'b111))
rcv_byte_valid <= 1'b1;
else
rcv_byte_valid <= 1'b0;
// flags for keeping track of the address byte and 1st data byte
always @(posedge rst_int or posedge SPI_SCLK)
if (rst_int) begin
addr_has_been_latched <= 1'b0; // flag that gets set after the addr has been received (and latched)
first_data_has_been_latched <= 1'b0; // flag that gets set after the 1st data byte has been received (and latched)
end
else begin
// if (SPI_SS) // if SPI interface is idle
// addr_has_been_latched <= 1'b0;
// else
// the above is not necessary since the async rst includes SPI_SS
if (rcv_byte_valid)
addr_has_been_latched <= 1'b1; // set flag after first byte (the address) is received, keep at 1 until transaction is over
else
addr_has_been_latched <= addr_has_been_latched;
// if (SPI_SS) // if SPI interface is idle
// first_data_has_been_latched <= 1'b0;
// else
// the above is not necessary since the async rst includes SPI_SS
if (addr_has_been_latched && rcv_byte_valid)
first_data_has_been_latched <= 1'b1;
else
first_data_has_been_latched <= first_data_has_been_latched;
end
// address register, direction control flag
always @(posedge rst or posedge SPI_SCLK) // don't use rst_int so these signals will remain active even after SPI_SS has gone inactive
if (rst) begin
addr_reg <= 7'b0;
write_readn <= 1'b0; // flag that signifies a write vs. read transaction
end
else begin
if (!addr_has_been_latched && rcv_byte_valid)
write_readn <= shift_in[7]; // the direction (r/w) flag is in the MSb of the address byte.
else
write_readn <= write_readn;
if (!addr_has_been_latched)
if (rcv_byte_valid)
addr_reg <= shift_in[6:0]; // latch the new address, located in the lowest 7 bits of the address byte.
else
addr_reg <= addr_reg;
else // addr_has_been_latched
// if (((write_readn == WR) && wr_data_valid_reg) || ((write_readn == RD) && rcv_byte_valid))
// addr_reg <= addr_reg + 1;
// else
// addr_reg <= addr_reg;
// during writes, make addr_reg wrap back to MemDataByte0 after MemDataByte4
if ((write_readn == WR) && wr_data_valid_reg)
if (addr_reg == `MemDataByte4)
addr_reg <= `MemDataByte0;
else
addr_reg <= addr_reg + 1;
else
// during reads, do not increment addr_reg when accessing CM_FIFO_Data
//if ((write_readn == RD) && rcv_byte_valid)
if ((write_readn == RD) && rd_data_ack_reg)
if (addr_reg == `CM_FIFO_Data)
addr_reg <= addr_reg;
else
addr_reg <= addr_reg + 1;
else
addr_reg <= addr_reg;
end
// write_pending flag, so writes eventually get sent to the internal interface when more SPI_SCLK edges occur
always @(posedge rst or posedge SPI_SCLK) // don't use rst_int since this may need to stay active after SPI_SS goes inactive
if (rst)
write_pending <= 1'b0;
else
if (wr_data_valid_reg)
write_pending <= 1'b0;
else
if ((write_readn == WR) && !SPI_SS && addr_has_been_latched && (bit_cnt == 3'b111)) // can't use rcv_byte_valid since there may not be extra clocks after this byte is being written
write_pending <= 1'b1;
else
write_pending <= write_pending;
// write data valid signal
always @(posedge rst or posedge SPI_SCLK) // don't use rst_int since this may need to be set after SPI_SS goes inactive
if (rst)
wr_data_valid_reg <= 1'b0;
else
if (wr_data_valid_reg)
wr_data_valid_reg <= 1'b0;
else
if (write_pending)
wr_data_valid_reg <= 1'b1;
else
wr_data_valid_reg <= wr_data_valid_reg;
always @(posedge rst or posedge SPI_SCLK) // don't use rst_int since this needs to stay valid after SPI_SS goes inactive
if (rst)
write_data_reg <= 8'b0;
else
if (!SPI_SS && (bit_cnt == 3'b111))
write_data_reg <= {shift_in[6:0], SPI_MOSI};
else
write_data_reg <= write_data_reg;
// output shift register
always @(posedge rst_int or negedge SPI_SCLK)
if (rst_int) begin
bit_cnt_neg <= 3'b0;
shift_out <= 8'b0;
end
else begin
if (!SPI_SS) begin
bit_cnt_neg <= bit_cnt_neg + 1;
if (addr_has_been_latched && (bit_cnt_neg == 7))
shift_out <= rd_data;
else
shift_out <= {shift_out[6:0], 1'b0};
end
else begin
bit_cnt_neg <= 3'b0;
shift_out <= shift_out;
end
end
// read data acknowledge. this is required to pop data from the CM FIFO
always @(posedge rst_int or posedge SPI_SCLK)
if (rst_int)
rd_data_ack_reg <= 1'b0;
else
//if ( addr_has_been_latched && (write_readn == RD) && (bit_cnt == 3'b111) )
if ( addr_has_been_latched && (write_readn == RD) && rcv_byte_valid)
rd_data_ack_reg <= 1'b1;
else
rd_data_ack_reg <= 1'b0;
// assignments to the outputs
//assign SPI_MISO = SPI_SS ? 1'bz : shift_out[7];
assign SPI_MISO = shift_out[7];//AP2 doesn't support tristate
assign addr = addr_reg;
assign wr_data = write_data_reg;
assign wr_data_valid = wr_data_valid_reg;
assign rd_data_ack = rd_data_ack_reg;
endmodule

View File

@ -0,0 +1,65 @@
`ifndef SensorHub_Definitions
`define SensorHub_Definitions
// Communication Manager register offsets
`define CommandReg 7'h00
`define StatusReg 7'h01
`define milSecSample 7'h02
`define InterruptCtrl 7'h03
`define InterruptStat 7'h04
`define CalValueLow 7'h05
`define CalValueHi 7'h06
`define Reserved_10 7'h07
`define Reserved_11 7'h08
`define Reserved_12 7'h09
`define Reserved_13 7'h0A
`define Reserved_14 7'h0B
`define CM_FIFO_Data 7'h0C
`define CM_Control 7'h0D
`define CM_Status 7'h0E
`define CM_FIFO_Flags_0 7'h0F
`define Reserved_1 7'h10 /* reserved for CM_FIFO_Flags_23 */
`define MailboxToFFE_0 7'h11
`define MailboxToFFE_1 7'h12
`define MailboxToFFE_2 7'h13
`define MailboxToFFE_3 7'h14
`define InterruptFFEMsg 7'h15
`define Reserved_5 7'h16
`define Reserved_6 7'h17
`define Reserved_7 7'h18
`define RunTimeAdrReg 7'h19
`define DemoLedCtrlReg 7'h1A /* Register to control demo LEDs */
`define ClocksControl 7'h1B
`define SleepControl 7'h1C
`define RunTimeAdrReg_Upr 7'h1D /* New for Rel 0 on 6/18 */
`define MemAddrLow 7'h20
`define MemAddrHigh 7'h21
`define MemSelect 7'h22
`define MemDataByte0 7'h28
`define MemDataByte1 7'h29
`define MemDataByte2 7'h2A
`define MemDataByte3 7'h2B
`define MemDataByte4 7'h2C
`define CtrlSensorManager 8'h00
`define CtrlReceiveAddress 8'h01
`define CtrlRunTimeAddress 8'h02
`define MasterPreLo 8'h08
`define MasterPreHi 8'h09
`define MasterCTR 8'h0A
`define MasterTXR 8'h0B
`define MasterCR 8'h0C
`define CR_START 8'b1000_0000
`define CR_STOP 8'b0100_0000
`define CR_READ 8'b0010_0000
`define CR_WRITE 8'b0001_0000
`define CR_NAK 8'b0000_1000
// `define CR_POLL 8'b0000_0100
`define CR_IACK 8'b0000_0001
`endif

View File

@ -0,0 +1,960 @@
// -----------------------------------------------------------------------------
// title : Sensor Manager Main Routine
// project : ULP Sensor Hub
// -----------------------------------------------------------------------------
// file : SensorManager.v
// author : OCTO
// company : QuickLogic Corp
// created : 2012/??/??
// last update : 2013/12/06
// platform : PolarPro III
// standard : Verilog 2001
// -----------------------------------------------------------------------------
// description: The Sensor Manger is responsible for controlling various
// external sensors and storing the resulting data in Sensor
// Manager Memory. These include performing transfers between
// Sensor Memory and various registers.
// -----------------------------------------------------------------------------
// copyright (c) 2013
// -----------------------------------------------------------------------------
// revisions :
// date version author description
// 2013/12/06 1.0 Glen Gomes Updated -> Mostly re-written
// -----------------------------------------------------------------------------
// Comments: This solution is specifically for use with the QuickLogic
// PolarPro III device.
// -----------------------------------------------------------------------------
`timescale 1ns / 10ps
module SensorManager (
// General interface
ClockIn,
ResetIn,
StartFromFFE,
StartFromTLC,
BusyOut,
TimeStamp_Delta_i,
TimeStamp_Delta_Tog_i,
SensorInterrupt_0_i,
SensorInterrupt_1_i,
SensorInterrupt_2_i,
SensorInterrupt_3_i,
SensorInterrupt_0_o,
SensorInterrupt_1_o,
SensorInterrupt_2_o,
SensorInterrupt_3_o,
CtrlRunTimeAddressSM,
CtrlRunTimeAddressOut,
CtrlRunTimeAddressReg,
MemReadAddressOut,
MemReadEnableOut,
MemReadDataIn,
MemWriteAddressOut,
MemWriteEnableOut,
MemWriteDataOut,
MemClockOut,
I2C_wb_adr_o,
I2C_wb_dat_o,
I2C_wb_dat_i,
I2C_wb_we_o,
I2C_wb_stb_o,
I2C_wb_cyc_o,
I2C_wb_ack_i,
I2C_tip_i,
TP1,
TP2,
TP3,
SmClockSelect_o
);
//-----Port Signals--------------------
//
input ClockIn;
input ResetIn;
input StartFromFFE;
input StartFromTLC;
output BusyOut;
input [15:0] TimeStamp_Delta_i;
input TimeStamp_Delta_Tog_i;
input SensorInterrupt_0_i;
input SensorInterrupt_1_i;
input SensorInterrupt_2_i;
input SensorInterrupt_3_i;
output SensorInterrupt_0_o;
output SensorInterrupt_1_o;
output SensorInterrupt_2_o;
output SensorInterrupt_3_o;
input CtrlRunTimeAddressSM;
input [9:0] CtrlRunTimeAddressOut;
output [9:0] CtrlRunTimeAddressReg;
output [9:0] MemReadAddressOut; // Expanded for Rel 0 on 6/18
output MemReadEnableOut;
input [17:0] MemReadDataIn;
output [9:0] MemWriteAddressOut;
output MemWriteEnableOut;
output [8:0] MemWriteDataOut;
output MemClockOut;
output [2:0] I2C_wb_adr_o;
output [7:0] I2C_wb_dat_o;
input [7:0] I2C_wb_dat_i;
output I2C_wb_we_o;
output I2C_wb_stb_o;
output I2C_wb_cyc_o;
input I2C_wb_ack_i;
input I2C_tip_i;
output TP1;
output TP2;
output TP3;
output SmClockSelect_o;
wire ClockIn;
wire ResetIn;
wire StartFromFFE;
wire StartFromTLC;
wire BusyOut;
wire [15:0] TimeStamp_Delta_i;
wire TimeStamp_Delta_Tog_i;
wire SensorInterrupt_0_i;
wire SensorInterrupt_1_i;
wire SensorInterrupt_2_i;
wire SensorInterrupt_3_i;
reg SensorInterrupt_0_o;
reg SensorInterrupt_1_o;
reg SensorInterrupt_2_o;
reg SensorInterrupt_3_o;
wire CtrlRunTimeAddressSM;
wire [9:0] CtrlRunTimeAddressOut;
reg [9:0] CtrlRunTimeAddressReg;
wire [9:0] MemReadAddressOut; // Expanded for Rel 0 on 6/18
wire MemReadEnableOut;
wire [17:0] MemReadDataIn;
wire [9:0] MemWriteAddressOut;
wire MemWriteEnableOut;
reg [8:0] MemWriteDataOut;
wire [2:0] I2C_wb_adr_o;
wire [7:0] I2C_wb_dat_o;
wire [7:0] I2C_wb_dat_i;
wire I2C_wb_we_o;
wire I2C_wb_stb_o;
wire I2C_wb_cyc_o;
wire I2C_wb_ack_i;
wire I2C_tip_i;
wire MemClockOut;
wire TP1;
wire TP2;
wire TP3;
reg SmClockSelect_o;
//-----Internal Signals--------------------
//
wire wb_cyc;
wire wb_we;
wire wb_stb;
wire wb_ack;
reg wb_ack_sm;
wire wb_busy_poll;
reg [9:0] CtrlReceiveAddressReg;
reg [5:0] CtrlMailBoxSegmentCtr;
reg CtrlMailBoxSegmentCtr_ce;
reg [9:2] CtrlMailBoxTablePtr;
reg [9:0] CtrlMailBoxJumpInstPtr;
reg CtrlMailBoxJumpInstCycle;
reg CtrlMailBoxJumpInstCycle_ce;
wire [9:0] StateMachineCtrlMemAddr;
wire [7:0] i2c_masterDataToMem;
wire save_reg_2_mem;
wire control_sensor_manager_reg_dcd;
wire control_receive_reg_dcd;
wire control_runtime_reg_dcd;
wire control_jump_reg_dcd;
wire control_mailbox_tbl_ptr_dcd;
wire control_mailbox_jump_inst_ptr_dcd;
reg RunSM;
wire BusySM;
wire StartIn_stb;
reg StartFromFFE_1ff;
reg StartFromFFE_2ff;
reg StartFromFFE_3ff;
reg StartFromFFE_4ff;
reg StartFromFFE_5ff;
reg StartFromFFE_6ff;
reg StartFromTLC_1ff;
reg StartFromTLC_2ff;
reg CtrlRunTimeAddressSM_1ff;
reg CtrlRunTimeAddressSM_2ff;
reg s1_BusyOut, s2_BusyOut;
// Define write enable controls for each TimeStamp register
//
wire SensorInterrupt_event_reg_we_dcd;
wire SensorInterrupt_event_mask_we_dcd;
reg SensorInterrupt_event_mask_0;
reg SensorInterrupt_event_mask_1;
reg SensorInterrupt_event_mask_2;
reg SensorInterrupt_event_mask_3;
// Delta Time Stamp registers for each sensor
//
reg [7:0] TimeStamp_Delta_sensor_0;
reg [7:0] TimeStamp_Delta_sensor_1;
reg [7:0] TimeStamp_Delta_sensor_2;
reg [7:0] TimeStamp_Delta_sensor_3;
reg [15:0] TimeStamp_Delta_capt;
reg [15:0] TimeStamp_Delta_readback;
reg TimeStamp_Delta_Tog_1ff;
reg TimeStamp_Delta_Tog_2ff;
reg TimeStamp_Delta_Tog_3ff;
// Meta-state registers for each sensor interrupt
//
reg SensorInterrupt_0_1ff;
reg SensorInterrupt_0_2ff;
reg SensorInterrupt_0_3ff;
reg SensorInterrupt_1_1ff;
reg SensorInterrupt_1_2ff;
reg SensorInterrupt_1_3ff;
reg SensorInterrupt_2_1ff;
reg SensorInterrupt_2_2ff;
reg SensorInterrupt_2_3ff;
reg SensorInterrupt_3_1ff;
reg SensorInterrupt_3_2ff;
reg SensorInterrupt_3_3ff;
// Wait Instruction Registers
//
wire control_wait_instr_reg_dcd;
reg [12:0] control_wait_instr_cntr;
reg [12:0] control_wait_instr_cntr_nxt;
reg control_wait_instr_cntr_tc;
reg control_wait_instr_cntr_tc_nxt;
reg control_wait_instr_busy;
wire control_wait_instr_busy_nxt;
//------Define Parameters---------
//
//
// Define the various address spaces
//
// Note: These correspond to bits [7:3] of the register address field.
//
parameter SENSOR_MANAGER_ADR = 5'h0;
parameter I2C_MASTER_ADR = 5'h1;
parameter TIMESTAMP_DELTA_ADR = 5'h2;
//
// Define the available registers in the Sensor Manager
//
// Note: These correspond to bits [2:0] of the register address field.
//
parameter CONTROL_SENSOR_MANAGER_ADDRESS = 3'h0;
parameter CONTROL_RECEIVE_ADDRESS = 3'h1;
parameter CONTROL_RUNTIME_ADDRESS = 3'h2;
parameter CONTROL_WAIT_INSTR_ADDRESS = 3'h4;
parameter CONTROL_MAILBOX_TABLE_PTR = 3'h5;
parameter CONTROL_MAILBOX_JUMP_INST_PTR = 3'h6;
parameter CONTROL_JUMP_ADDRESS = 3'h7;
//
// Define the key registers in the I2C Master IP
//
// Note: These correspond to bits [2:0] of the register address field.
//
parameter I2C_MASTER_PRELO = 3'h0;
parameter I2C_MASTER_PREHI = 3'h1;
parameter I2C_MASTER_CTR = 3'h2;
parameter I2C_MASTER_TXR = 3'h3;
parameter I2C_MASTER_CR = 3'h4;
// Define the available registers in the TimeStamp Logic
//
// Note: These correspond to bits [2:0] of the register address field.
//
parameter TIMESTAMP_DELTA_SENSOR_0 = 3'h0;
parameter TIMESTAMP_DELTA_SENSOR_1 = 3'h1;
parameter TIMESTAMP_DELTA_SENSOR_2 = 3'h2;
parameter TIMESTAMP_DELTA_SENSOR_3 = 3'h3;
parameter TIMESTAMP_DELTA_GENERIC_LSB = 3'h4;
parameter TIMESTAMP_DELTA_GENERIC_MSB = 3'h5;
parameter TIMESTAMP_DELTA_INT_EVENT = 3'h6;
//
// Define the default location of the Mail Box structure in SM Memory
//
parameter MAILBOX_SM_ADDRESS = 8'hFF; // Note: This is "3FC" shifted by two to the right
//------Logic Operations----------
//
// I2C Interface to the Right Bank ASSP
//
assign I2C_wb_dat_o = MemReadDataIn[15:8];
assign i2c_masterDataToMem = I2C_wb_dat_i;
assign I2C_wb_we_o = wb_we;
assign I2C_wb_stb_o = wb_stb;
// Decode the Wishbone bus address space(s)
//
assign I2C_wb_cyc_o = (MemReadDataIn[7:3] == I2C_MASTER_ADR) & wb_cyc & ~CtrlMailBoxJumpInstCycle;
// Define the write enables controls for each register
//
assign control_sensor_manager_reg_dcd = (MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_SENSOR_MANAGER_ADDRESS}) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
assign control_runtime_reg_dcd = (MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_RUNTIME_ADDRESS}) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
assign control_wait_instr_reg_dcd = (MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_WAIT_INSTR_ADDRESS}) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
assign control_receive_reg_dcd = ((MemReadDataIn[7:0] == { SENSOR_MANAGER_ADR, CONTROL_RECEIVE_ADDRESS})
| (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_0})
| (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_1})
| (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_2})
| (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_3})
| (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_GENERIC_MSB})
| (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_GENERIC_LSB})) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
// Define the write enable for the Interrupt event of the Time Stamp Logic
//
// Note: This write occurs after the write of interrupt data to SM Memory
//
assign SensorInterrupt_event_reg_we_dcd = (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_INT_EVENT}) & wb_cyc & wb_stb & ~wb_we & wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
assign SensorInterrupt_event_mask_we_dcd = (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_INT_EVENT}) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
assign TimeStamp_Delta_lsb_reg_we_dcd = (MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_GENERIC_LSB}) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
// Deterimine if the current cycle is a write to the instruction pointer.
//
// Note: This only happens during the "jump" instruction
//
// This signals the Sensor Manager Statemachine that the current cycle
// is a "jump" and to load the register data value into the instruction
// pointer at the end of the current "register write" instruction.
//
assign control_jump_reg_dcd = (MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_JUMP_ADDRESS}) & ~CtrlMailBoxJumpInstCycle;
// Determine if the current cycle is the start of a Mail Box based Jump
// sequence.
//
// Note: The value of the bits in the Mail Box region of SM Memory determine
// if the current jump address should be loaded into the instruction
// pointer or if it should be ignored.
//
assign control_mailbox_tbl_ptr_dcd = (MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_MAILBOX_TABLE_PTR}) & wb_cyc & wb_stb & wb_we & ~wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
assign control_mailbox_jump_inst_ptr_dcd = (MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_MAILBOX_JUMP_INST_PTR}) & wb_cyc & wb_stb & wb_we & wb_ack_sm & ~CtrlMailBoxJumpInstCycle;
// Determine if the current address should include a write to the Sensor Manager's Memory
//
// Note: There is currently only one address but this may expand with, for
// example, a TimeStamp function.
//
assign save_reg_2_mem = ((MemReadDataIn[7:0] == { I2C_MASTER_ADR, I2C_MASTER_CR}) & MemReadDataIn[13] & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_0}) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_1}) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_2}) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_SENSOR_3}) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_GENERIC_LSB}) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_GENERIC_MSB}) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {TIMESTAMP_DELTA_ADR, TIMESTAMP_DELTA_INT_EVENT}) & ~CtrlMailBoxJumpInstCycle);
// Determine if the Wishbone device requires monitoring its busy signal
//
// Note: The only device currently supported is the I2C Master IP. This IP
// will generate a I2C bus cycle when the "read" or "write"
// bits are set in the control register.
//
assign wb_busy_poll = ((MemReadDataIn[7:0] == {I2C_MASTER_ADR, I2C_MASTER_CR }) & (MemReadDataIn[12] | MemReadDataIn[13]) & ~CtrlMailBoxJumpInstCycle)
| ((MemReadDataIn[7:0] == {SENSOR_MANAGER_ADR, CONTROL_WAIT_INSTR_ADDRESS}) & ~CtrlMailBoxJumpInstCycle);
// Determine when to start the Sensor Manager Statemachine
//
// Note: Use double-rank synchronization to resolve meta-stability issues.
//
// Simulation shows these signals toggle from TLC.v clock domain to
// the Sensor Manager's.
//
assign StartIn_stb = (StartFromFFE_5ff ^ StartFromFFE_6ff)
| (StartFromTLC_1ff ^ StartFromTLC_2ff);
// Define the Sensor Manager Control Registers
//
always @(posedge ClockIn or posedge ResetIn)
begin
if (ResetIn)
begin
wb_ack_sm <= 1'b0;
StartFromFFE_1ff <= 1'b0;
StartFromFFE_2ff <= 1'b0;
StartFromFFE_3ff <= 1'b0;
StartFromFFE_4ff <= 1'b0;
StartFromFFE_5ff <= 1'b0;
StartFromFFE_6ff <= 1'b0;
StartFromTLC_1ff <= 1'b0;
StartFromTLC_2ff <= 1'b0;
RunSM <= 1'b0;
CtrlReceiveAddressReg <= 10'h0;
CtrlRunTimeAddressReg <= 10'h0;
CtrlRunTimeAddressSM_1ff <= 1'b0;
CtrlRunTimeAddressSM_2ff <= 1'b0;
TimeStamp_Delta_sensor_0 <= 8'h0;
TimeStamp_Delta_sensor_1 <= 8'h0;
TimeStamp_Delta_sensor_2 <= 8'h0;
TimeStamp_Delta_sensor_3 <= 8'h0;
SensorInterrupt_0_1ff <= 4'h0;
SensorInterrupt_0_2ff <= 4'h0;
SensorInterrupt_0_3ff <= 4'h0;
SensorInterrupt_1_1ff <= 4'h0;
SensorInterrupt_1_2ff <= 4'h0;
SensorInterrupt_1_3ff <= 4'h0;
SensorInterrupt_2_1ff <= 4'h0;
SensorInterrupt_2_2ff <= 4'h0;
SensorInterrupt_2_3ff <= 4'h0;
SensorInterrupt_3_1ff <= 4'h0;
SensorInterrupt_3_2ff <= 4'h0;
SensorInterrupt_3_3ff <= 4'h0;
SensorInterrupt_0_o <= 1'b0;
SensorInterrupt_1_o <= 1'b0;
SensorInterrupt_2_o <= 1'b0;
SensorInterrupt_3_o <= 1'b0;
SensorInterrupt_event_mask_0 <= 1'b0;
SensorInterrupt_event_mask_1 <= 1'b0;
SensorInterrupt_event_mask_2 <= 1'b0;
SensorInterrupt_event_mask_3 <= 1'b0;
TimeStamp_Delta_capt <= 16'h0;
TimeStamp_Delta_readback <= 16'h0;
TimeStamp_Delta_Tog_1ff <= 1'b0;
TimeStamp_Delta_Tog_2ff <= 1'b0;
TimeStamp_Delta_Tog_3ff <= 1'b0;
CtrlMailBoxSegmentCtr <= 6'h0;
CtrlMailBoxSegmentCtr_ce <= 1'b0;
CtrlMailBoxTablePtr <= MAILBOX_SM_ADDRESS;
CtrlMailBoxJumpInstPtr <= 10'h0;
CtrlMailBoxJumpInstCycle <= 1'b0;
CtrlMailBoxJumpInstCycle_ce <= 1'b0;
control_wait_instr_cntr <= 13'h0;
control_wait_instr_cntr_tc <= 1'b0;
control_wait_instr_busy <= 1'b0;
end
else
begin
wb_ack_sm <= ((MemReadDataIn[7:3] == SENSOR_MANAGER_ADR )
| (MemReadDataIn[7:3] == TIMESTAMP_DELTA_ADR)
| (CtrlMailBoxJumpInstCycle)) & wb_cyc & wb_stb & ~wb_ack_sm;
// Double-rank synchronization between clock domains to avoid meta-state issues
//
StartFromFFE_1ff <= StartFromFFE;
StartFromFFE_2ff <= StartFromFFE_1ff;
StartFromFFE_3ff <= StartFromFFE_2ff;
StartFromFFE_4ff <= StartFromFFE_3ff;
StartFromFFE_5ff <= StartFromFFE_4ff;
StartFromFFE_6ff <= StartFromFFE_5ff;
StartFromTLC_1ff <= StartFromTLC;
StartFromTLC_2ff <= StartFromTLC_1ff;
CtrlRunTimeAddressSM_1ff <= CtrlRunTimeAddressSM;
CtrlRunTimeAddressSM_2ff <= CtrlRunTimeAddressSM_1ff;
// Define the Sensor Manager Control Register
//
// Note: A write of "0" to bit "0" of Sensor Manager Register "0" stops execution.
//
// The remaining bits of the "control" register can be used for other purposes.
//
if (StartIn_stb)
RunSM <= 1'b1;
else if (control_sensor_manager_reg_dcd)
RunSM <= MemReadDataIn[8];
// Define the Sensor Manager Receive Address Register
//
if (control_receive_reg_dcd)
CtrlReceiveAddressReg <= MemReadDataIn[17:8];
// Define the Sensor Manager Run-time Address Register
//
if (control_runtime_reg_dcd)
CtrlRunTimeAddressReg <= MemReadDataIn[17:8];
else if ( CtrlRunTimeAddressSM_1ff ^ CtrlRunTimeAddressSM_2ff)
CtrlRunTimeAddressReg <= CtrlRunTimeAddressOut;
// Synchronize the interrupt inputs to avoid meta-state issues
//
SensorInterrupt_0_1ff <= SensorInterrupt_0_i;
SensorInterrupt_0_2ff <= SensorInterrupt_0_1ff;
SensorInterrupt_0_3ff <= SensorInterrupt_0_2ff;
SensorInterrupt_1_1ff <= SensorInterrupt_1_i;
SensorInterrupt_1_2ff <= SensorInterrupt_1_1ff;
SensorInterrupt_1_3ff <= SensorInterrupt_1_2ff;
SensorInterrupt_2_1ff <= SensorInterrupt_2_i;
SensorInterrupt_2_2ff <= SensorInterrupt_2_1ff;
SensorInterrupt_2_3ff <= SensorInterrupt_2_2ff;
SensorInterrupt_3_1ff <= SensorInterrupt_3_i;
SensorInterrupt_3_2ff <= SensorInterrupt_3_1ff;
SensorInterrupt_3_3ff <= SensorInterrupt_3_2ff;
TimeStamp_Delta_Tog_1ff <= TimeStamp_Delta_Tog_i;
TimeStamp_Delta_Tog_2ff <= TimeStamp_Delta_Tog_1ff;
TimeStamp_Delta_Tog_3ff <= TimeStamp_Delta_Tog_2ff;
// Capture the external TimeStamp from the Communication Manager.
//
// Note: The Communication Manager uses the 32KHz clock for the
// TimeStamp function. In the current application, this is not
// the same clock used for the Sensor Manager. However, the
// Sensor Manager's clock is currently significantly faster than
// the 32KHz clock and can capture the TimeStamp value reliably
// when is receives the TimeStamp toggle signal from the
// Communication Manager.
//
// This scheme may need to be revisted if the clock assignments
// change on future designs.
//
if (TimeStamp_Delta_Tog_2ff ^ TimeStamp_Delta_Tog_3ff)
TimeStamp_Delta_capt <= TimeStamp_Delta_i;
// Capture the TimeStamp Value for a "generic" TimeStamp write to SM
// Memory.
//
// Note: The entire TimeStamp value is captured when a write of the
// LSB value to SM Memory is triggered. This allows for the
// writting of the MSB bits without the danger of the TimeStamp
// value changing between writes of each TimeStamp byte to
// SM Memory.
//
if (TimeStamp_Delta_lsb_reg_we_dcd)
TimeStamp_Delta_readback <= TimeStamp_Delta_capt;
// Capture the time stamp delta when an interrupt is detected.
//
// Note: See below for the definition of the bit operations.
//
if (SensorInterrupt_0_2ff && (!SensorInterrupt_0_3ff))
TimeStamp_Delta_sensor_0 <= TimeStamp_Delta_capt;
if (SensorInterrupt_1_2ff && (!SensorInterrupt_1_3ff))
TimeStamp_Delta_sensor_1 <= TimeStamp_Delta_capt;
if (SensorInterrupt_2_2ff && (!SensorInterrupt_2_3ff))
TimeStamp_Delta_sensor_2 <= TimeStamp_Delta_capt;
if (SensorInterrupt_3_2ff && (!SensorInterrupt_3_3ff))
TimeStamp_Delta_sensor_3 <= TimeStamp_Delta_capt;
// Set the Interrupt Status Mask bits
//
// Note: These bits are used "ANDed" with the write signal to clear
// individual status bits.
//
// The alternate way is to write the interrupt status once
// at the end of a series of SM code segments. However, there
// may be a significant amount of time between TimeStamp value
// capture and a single status being written to memory. This
// can allow the interrupt status to change after the TimeStamp
// is written to memory. This could result in the assumption
// of a good TimeStamp when, in fact, the TimeStamp is not
// valid.
//
if (SensorInterrupt_event_mask_we_dcd)
begin
SensorInterrupt_event_mask_0 <= MemReadDataIn[8];
SensorInterrupt_event_mask_1 <= MemReadDataIn[9];
SensorInterrupt_event_mask_2 <= MemReadDataIn[10];
SensorInterrupt_event_mask_3 <= MemReadDataIn[11];
end
// Set the interrupt event bit for each sensor when an interrupt is
// detected.
//
// Note: Without this "interrupt event bit" is may not be possible to
// know for certain if an interrupt happened. For example,
// a value of "0" may be correct given the right
// sampling period.
//
// These status bits assume a positive (i.e. low-to-high)
// interrupt assertion.
//
// All interrupts are cleared when this register is read.
//
if (SensorInterrupt_event_reg_we_dcd && SensorInterrupt_event_mask_0)
SensorInterrupt_0_o <= 1'h0;
else if (SensorInterrupt_0_2ff && (!SensorInterrupt_0_3ff))
SensorInterrupt_0_o <= 1'h1;
if (SensorInterrupt_event_reg_we_dcd && SensorInterrupt_event_mask_1)
SensorInterrupt_1_o <= 1'h0;
else if (SensorInterrupt_1_2ff && (!SensorInterrupt_1_3ff))
SensorInterrupt_1_o <= 1'h1;
if (SensorInterrupt_event_reg_we_dcd && SensorInterrupt_event_mask_2)
SensorInterrupt_2_o <= 1'h0;
else if (SensorInterrupt_2_2ff && (!SensorInterrupt_2_3ff))
SensorInterrupt_2_o <= 1'h1;
if (SensorInterrupt_event_reg_we_dcd && SensorInterrupt_event_mask_3)
SensorInterrupt_3_o <= 1'h0;
else if (SensorInterrupt_3_2ff && (!SensorInterrupt_3_3ff))
SensorInterrupt_3_o <= 1'h1;
// Mail Box Bit Counter
//
// Note: Reset Bit Counter between SM Sessions.
//
// This counter selects the Mail Box bits corresponding to each
// SM code segment.
//
if (!BusySM)
CtrlMailBoxSegmentCtr <= 6'h0;
else if (CtrlMailBoxSegmentCtr_ce)
CtrlMailBoxSegmentCtr <= CtrlMailBoxSegmentCtr + 1'b1;
CtrlMailBoxSegmentCtr_ce <= wb_cyc & wb_stb & wb_we & ~wb_ack_sm & CtrlMailBoxJumpInstCycle;
// Mail Box Table Address Pointer
//
// Note: This is the location in SM Memory where the Mail Box is
// located. Typically, the mail box will be in the last four
// 18-bit words in SM Memory.
//
// This value can be dynamically changed by instructions in SM
// memory.
//
if (control_mailbox_tbl_ptr_dcd)
CtrlMailBoxTablePtr <= MemReadDataIn[17:10];
// Mail Box Jump Address
//
// Note: This address must be temporarily storged while the Mail Box
// bits are being read from SM Memory.
//
// Based on the Mail Box bit for the current code segment, this
// jump address may or may not be used for a jump.
//
if (control_mailbox_jump_inst_ptr_dcd)
CtrlMailBoxJumpInstPtr <= MemReadDataIn[17:8];
// Mail Box Jump Decode Cycle Flag
//
// Note: This flags that the current SM write cycle is a Mail Box Jump
// decode operation.
//
// The data from SM Memory consist of Mail Box bits and should
// not be decoded as a SM "write" instruction would.
//
// The decode consists of selecting the correct bit from the
// Mail Box for the current SM code segment. Based on the state
// of this bit (i.e. 0 - No Jump; 1 - Jump), the SM instruction
// pointer will either proceed with the next instruction address
// or jump to a new code segment.
//
if (control_mailbox_jump_inst_ptr_dcd)
CtrlMailBoxJumpInstCycle <= 1'b1;
else if (CtrlMailBoxJumpInstCycle_ce)
CtrlMailBoxJumpInstCycle <= 1'b0;
CtrlMailBoxJumpInstCycle_ce <= wb_cyc & wb_stb & wb_we & wb_ack_sm & ~control_mailbox_jump_inst_ptr_dcd;
// Wait Instruction Register
//
if (control_wait_instr_reg_dcd || control_wait_instr_busy)
begin
control_wait_instr_cntr <= control_wait_instr_cntr_nxt;
control_wait_instr_cntr_tc <= control_wait_instr_cntr_tc_nxt;
end
control_wait_instr_busy <= control_wait_instr_busy_nxt;
end
end
// Define the Wait Instruction Busy signal
//
// Note: This busy starts with the first write and ends when the counter is done.
//
// This is an N-1 counter. Therefore, a value of "0" means an "N" of "1".
// Therefore, there should be one cycle of busy even with a value of "0".
//
assign control_wait_instr_busy_nxt = (~control_wait_instr_busy & control_wait_instr_reg_dcd)
| ( control_wait_instr_busy & ~control_wait_instr_cntr_tc);
// Define the operation of the Wait Instruction Counter
//
always @(MemReadDataIn or
control_wait_instr_busy or
control_wait_instr_cntr
)
begin
case({control_wait_instr_busy, MemReadDataIn[17]})
2'b00: // MSB == 0 then count 1-to-1
begin
control_wait_instr_cntr_nxt <= {4'h0, MemReadDataIn[16:8] };
control_wait_instr_cntr_tc_nxt <= ( MemReadDataIn[16:8] == 9'h0);
end
2'b01: // MSB == 1 then count 16-to-1
begin
control_wait_instr_cntr_nxt <= { MemReadDataIn[16:8], 4'hF}; // Remember: N-1 means that "0" should be one wait period
control_wait_instr_cntr_tc_nxt <= 1'b0;
end
2'b10: // Normal Count
begin
control_wait_instr_cntr_nxt <= control_wait_instr_cntr - 13'h1;
control_wait_instr_cntr_tc_nxt <= (control_wait_instr_cntr == 13'h1);
end
2'b11: // Normal Count - The value was shift << 4 so it is already 16x larger at loading time
begin
control_wait_instr_cntr_nxt <= control_wait_instr_cntr - 13'h1;
control_wait_instr_cntr_tc_nxt <= (control_wait_instr_cntr == 13'h1);
end
endcase
end
// Use the "run" bit to signal when the statemachine is "busy" in addition to
// the statemachine busy bit.
//
assign BusyOut = RunSM | BusySM;
// Define the Sensor Manager Memory's read address
//
// Note: StateMachine is allowed to read all of SensorManager Memory
//
// The Sensor Manager Memory's "read" port is 10-bits (i.e. [9:0])
//
// Select the Mail Box Address pointer during Mail Box Jump operations.
// The location pointed to contains Mail Box Jump enable bits AND NOT
// SM instructions.
//
assign MemReadAddressOut = CtrlMailBoxJumpInstCycle ? {CtrlMailBoxTablePtr, CtrlMailBoxSegmentCtr[5:4]}
: StateMachineCtrlMemAddr ;
// Limit the register write function to the upper half of the Sensor Manager's Memory space
//
// Note: The Sensor Manager Memory's "write" port address is 10-bits (i.e. [9:0])
//
assign MemWriteAddressOut = CtrlReceiveAddressReg;
// Define the Data to be written to Sensor Memory
//
// Note: The I2C Master IP only outputs byte wide values
//
// For the current design, the following are read back:
// - I2C Master IP is read back
// - TimeStamp registers for four sensors
// - TimeSTamp related interrupt event register
//
// Only the I2C Master IP was supported in previous designs
//
always @(MemReadDataIn or
MemWriteDataOut or
i2c_masterDataToMem or
TimeStamp_Delta_sensor_0 or
TimeStamp_Delta_sensor_1 or
TimeStamp_Delta_sensor_2 or
TimeStamp_Delta_sensor_3 or
TimeStamp_Delta_readback or
SensorInterrupt_0_o or
SensorInterrupt_1_o or
SensorInterrupt_2_o or
SensorInterrupt_3_o
)
begin
case(MemReadDataIn[7:3])
I2C_MASTER_ADR: MemWriteDataOut <= {1'b0, i2c_masterDataToMem};
TIMESTAMP_DELTA_ADR:
begin
case(MemReadDataIn[2:0])
TIMESTAMP_DELTA_SENSOR_0 : MemWriteDataOut <= {1'b0, TimeStamp_Delta_sensor_0};
TIMESTAMP_DELTA_SENSOR_1 : MemWriteDataOut <= {1'b0, TimeStamp_Delta_sensor_1};
TIMESTAMP_DELTA_SENSOR_2 : MemWriteDataOut <= {1'b0, TimeStamp_Delta_sensor_2};
TIMESTAMP_DELTA_SENSOR_3 : MemWriteDataOut <= {1'b0, TimeStamp_Delta_sensor_3};
TIMESTAMP_DELTA_GENERIC_LSB : MemWriteDataOut <= {1'b0, TimeStamp_Delta_readback[7:0]};
TIMESTAMP_DELTA_GENERIC_MSB : MemWriteDataOut <= {1'b0, TimeStamp_Delta_readback[15:8]};
TIMESTAMP_DELTA_INT_EVENT : MemWriteDataOut <= {4'h0, SensorInterrupt_3_o,
SensorInterrupt_2_o,
SensorInterrupt_1_o,
SensorInterrupt_0_o};
default: MemWriteDataOut <= {1'b0, i2c_masterDataToMem};
endcase
end
default: MemWriteDataOut <= {1'b0, i2c_masterDataToMem};
endcase
end
// Define the Sensor Manager Memory's clock
//
// Note: This is currently a flow through but this may change in future designs.
//
assign MemClockOut = ClockIn;
// Combine all Wishbone bus acknowledges
//
// Note: Only one acknowledge should happen at a time.
//
assign wb_ack = wb_ack_sm | I2C_wb_ack_i;
// Multiplex the address to the I2C Master IP when performing an I2C read
//
// Note: The address must be switched from the I2C "Control" Register to the I2C "Transmit/Receive" data address.
//
// This only affects the I2C Master IP and does not affect any other device on the Wishbone bus.
//
assign I2C_wb_adr_o = ((MemReadDataIn[7:0] == {I2C_MASTER_ADR, I2C_MASTER_CR}) & MemReadDataIn[13] & (~wb_we))
? I2C_MASTER_TXR : MemReadDataIn[2:0];
//------Instantiate Modules----------------
//
// Instantiate the Sensor Manager Statemachine
//
StateMachine StateMachine_inst (
.CLK_IN ( ClockIn ),
.RESET_IN ( ResetIn ),
.RUNTIME_ADDRESS ( CtrlRunTimeAddressReg ),
.CONTROL_JUMP_REG_DCD ( control_jump_reg_dcd ),
.SAVE_REG_2_MEM ( save_reg_2_mem ),
.MAILBOX_JUMP_INST_CYCLE (CtrlMailBoxJumpInstCycle ),
.MAILBOX_JUMP_INST_PTR (CtrlMailBoxJumpInstPtr ),
.MAILBOX_SEGMENT_CTR (CtrlMailBoxSegmentCtr[3:0] ),
.WB_ACK_I ( wb_ack ),
.WB_BUSY_I ( I2C_tip_i | control_wait_instr_busy ),
.WB_BUSY_POLL_I ( wb_busy_poll ),
.WB_WE_O ( wb_we ),
.WB_STB_O ( wb_stb ),
.WB_CYC_O ( wb_cyc ),
.SM_CNTL_REG_RUN ( RunSM ),
.SM_READ_DATA ( MemReadDataIn ), // Data "Byte" is MemReadDataIn[17:8]
.SM_INSTR_PTR ( StateMachineCtrlMemAddr ),
.SM_READ_SELECT ( MemReadEnableOut ),
.SM_WRITE_SELECT ( MemWriteEnableOut ),
.SM_BUSY ( BusySM )
);
// test points
//
assign TP1 = I2C_tip_i;
assign TP2 = BusyOut;
assign TP3 = 0;
// Logic to generate SmClockSelect_o
wire d_SmClockSelect;
always @(posedge ClockIn or posedge ResetIn)
begin
if (ResetIn)
begin
s1_BusyOut <= 1'b0;
s2_BusyOut <= 1'b0;
SmClockSelect_o <= 1'b0;
end
else
begin
s1_BusyOut <= BusyOut;
s2_BusyOut <= s1_BusyOut;
SmClockSelect_o <= d_SmClockSelect;
end
end
assign d_SmClockSelect = SmClockSelect_o ? ((!s1_BusyOut && s2_BusyOut) ? 1'b0 : 1'b1) : ((StartFromFFE_1ff ^ StartFromFFE_2ff) ? 1'b1: 1'b0);
endmodule

View File

@ -0,0 +1,608 @@
// -----------------------------------------------------------------------------
// title : Sensor Manager Statemachine
// project : ULP Sensor Hub
// -----------------------------------------------------------------------------
// file : StateMachine.v
// author : Glen Gomes
// company : QuickLogic Corp
// created : 2013/12/06
// last update : 2013/12/06
// platform : PolarPro III
// standard : Verilog 2001
// -----------------------------------------------------------------------------
// description: The Sensor Manger Statemachine is responsible for controlling the
// operations of the Sensor Manager. These include performing
// transfers between Sensor Memory and various registers.
// -----------------------------------------------------------------------------
// copyright (c) 2013
// -----------------------------------------------------------------------------
// revisions :
// date version author description
// 2013/12/06 1.0 Glen Gomes created
// 2014/05/27 1.1 Glen Gomes Updated for Tay
// -----------------------------------------------------------------------------
// Comments: This solution is specifically for use with the QuickLogic
// PolarPro III device.
// -----------------------------------------------------------------------------
`timescale 1ns/10ps
module StateMachine (
CLK_IN,
RESET_IN,
RUNTIME_ADDRESS,
CONTROL_JUMP_REG_DCD,
SAVE_REG_2_MEM,
MAILBOX_JUMP_INST_CYCLE,
MAILBOX_JUMP_INST_PTR,
MAILBOX_SEGMENT_CTR,
WB_ACK_I,
WB_BUSY_I,
WB_BUSY_POLL_I,
WB_WE_O,
WB_STB_O,
WB_CYC_O,
SM_CNTL_REG_RUN,
SM_READ_DATA,
SM_INSTR_PTR,
SM_READ_SELECT,
SM_WRITE_SELECT,
SM_BUSY
);
//-----Port Signals--------------------
//
input CLK_IN;
input RESET_IN;
input [9:0] RUNTIME_ADDRESS;
input CONTROL_JUMP_REG_DCD;
input SAVE_REG_2_MEM;
input MAILBOX_JUMP_INST_CYCLE;
input [9:0] MAILBOX_JUMP_INST_PTR;
input [3:0] MAILBOX_SEGMENT_CTR;
input WB_ACK_I;
input WB_BUSY_I;
input WB_BUSY_POLL_I;
output WB_WE_O;
output WB_STB_O;
output WB_CYC_O;
input SM_CNTL_REG_RUN;
input [17:0] SM_READ_DATA;
output [9:0] SM_INSTR_PTR;
output SM_READ_SELECT;
output SM_WRITE_SELECT;
output SM_BUSY;
wire CLK_IN;
wire RESET_IN;
wire [9:0] RUNTIME_ADDRESS;
wire CONTROL_JUMP_REG_DCD;
wire SAVE_REG_2_MEM;
wire MAILBOX_JUMP_INST_CYCLE;
wire [9:0] MAILBOX_JUMP_INST_PTR;
wire [3:0] MAILBOX_SEGMENT_CTR;
wire WB_ACK_I;
wire WB_BUSY_I;
wire WB_BUSY_POLL_I;
reg WB_WE_O;
reg wb_we_o_nxt;
reg WB_STB_O;
reg wb_stb_o_nxt;
reg WB_CYC_O;
reg wb_cyc_o_nxt;
wire SM_CNTL_REG_RUN;
wire [17:0] SM_READ_DATA;
reg [9:0] SM_INSTR_PTR;
reg [9:0] sm_instr_ptr_nxt;
reg SM_READ_SELECT;
reg sm_read_select_nxt;
reg SM_WRITE_SELECT;
reg sm_write_select_nxt;
reg SM_BUSY;
reg sm_busy_nxt;
//-----Internal Signals--------------------
//
//
// Define the Statemachine registers
//
reg [3:0] sensor_manager_sm;
reg [3:0] sensor_manager_sm_nxt;
//
// Define the Instruction Pointer variables
//
reg sm_instr_ptr_ce;
reg sm_instr_ptr_ce_nxt;
reg sm_instr_ptr_ld;
reg sm_instr_ptr_ld_nxt;
//reg sm_instr_ptr_sel;
//reg sm_instr_ptr_sel_nxt;
reg mailbox_jump_inst_ptr_ld;
//------Define Parameters---------
//
//
// Define the Sensor Manager Statemachine States
//
// Note: These states are chosen to allow for overlap of various signals
// during operation. This overlap should help reduce timing
// dependancies.
//
parameter SM_IDLE = 4'h0;
parameter SM_INC_PTR = 4'h1;
parameter SM_INST_RD = 4'h2;
//parameter SM_INST_DCD = 4'h3; // Note: Will be used for TimeStamp Support in a future design
parameter SM_REG_WR = 4'h4;
parameter SM_REG_RD = 4'h5;
parameter SM_WAIT_BUSY_ON = 4'h6;
parameter SM_WAIT_BUSY_OFF = 4'h7;
//
// Sensor Manager Initialization Start Address
//
// Note: The previous IP used the reset of the "RuntimeAddress" register to
// select the sensor initialization code. This value explicity selects
// the value for the start (or re-start) of initialization.
//
parameter SM_INIT_INSTR_ADR = 10'h0; // Address for the start in initialization instructions
//------Logic Operations----------
//
//
// Define the Instruction Pointer
//
// Note: This pointer can start at either the sensor initialization code start
// address or the run-time code start address.
//
always @( SM_INSTR_PTR or
sm_instr_ptr_ld or
sm_instr_ptr_ce or
SM_READ_DATA or
CONTROL_JUMP_REG_DCD or
RUNTIME_ADDRESS or
MAILBOX_JUMP_INST_CYCLE or
MAILBOX_JUMP_INST_PTR
)
begin
case({sm_instr_ptr_ld, sm_instr_ptr_ce})
2'b00: sm_instr_ptr_nxt <= SM_INSTR_PTR; // Hold Current Value
2'b01: sm_instr_ptr_nxt <= SM_INSTR_PTR + 1'b1; // Increment to the next address
2'b10:
begin
case({MAILBOX_JUMP_INST_CYCLE, CONTROL_JUMP_REG_DCD})
2'b00: sm_instr_ptr_nxt <= RUNTIME_ADDRESS; // Run-time Code Address
2'b01: sm_instr_ptr_nxt <= SM_READ_DATA[17:8]; // Jump Address
default: sm_instr_ptr_nxt <= MAILBOX_JUMP_INST_PTR; // Mail Box Jump Address
endcase
end
2'b11: sm_instr_ptr_nxt <= SM_INSTR_PTR; // Hold Current Value
endcase
end
// Select the Mail Box Jump Enable Bit
//
// Note: Mail Box Jump enable bits are spread over 16-bits of the 18-bits from
// SM Memory.
//
always @( MAILBOX_SEGMENT_CTR or
SM_READ_DATA or
mailbox_jump_inst_ptr_ld
)
begin
case(MAILBOX_SEGMENT_CTR)
4'h0: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[0];
4'h1: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[1];
4'h2: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[2];
4'h3: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[3];
4'h4: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[4];
4'h5: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[5];
4'h6: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[6];
4'h7: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[7];
4'h8: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[9];
4'h9: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[10];
4'hA: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[11];
4'hB: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[12];
4'hC: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[13];
4'hD: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[14];
4'hE: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[15];
4'hF: mailbox_jump_inst_ptr_ld <= SM_READ_DATA[16];
endcase
end
// Define the registers associated with the Sensor Manager Statemachine
//
always @(posedge CLK_IN or posedge RESET_IN)
begin
if (RESET_IN)
begin
sensor_manager_sm <= SM_IDLE;
SM_INSTR_PTR <= 10'h0;
sm_instr_ptr_ce <= 1'b0;
sm_instr_ptr_ld <= 1'b0;
WB_WE_O <= 1'b0;
WB_STB_O <= 1'b0;
WB_CYC_O <= 1'b0;
SM_READ_SELECT <= 1'b0;
SM_WRITE_SELECT <= 1'b0;
SM_BUSY <= 1'b0;
end
else
begin
sensor_manager_sm <= sensor_manager_sm_nxt;
SM_INSTR_PTR <= sm_instr_ptr_nxt;
sm_instr_ptr_ce <= sm_instr_ptr_ce_nxt;
sm_instr_ptr_ld <= sm_instr_ptr_ld_nxt;
WB_WE_O <= wb_we_o_nxt;
WB_STB_O <= wb_stb_o_nxt;
WB_CYC_O <= wb_cyc_o_nxt;
SM_READ_SELECT <= sm_read_select_nxt;
SM_WRITE_SELECT <= sm_write_select_nxt;
SM_BUSY <= sm_busy_nxt;
end
end
// Define the Sensor Manager Statemachine
//
always @( sensor_manager_sm or
SM_CNTL_REG_RUN or
CONTROL_JUMP_REG_DCD or
SAVE_REG_2_MEM or
WB_BUSY_I or
WB_BUSY_POLL_I or
WB_ACK_I or
MAILBOX_JUMP_INST_CYCLE or
mailbox_jump_inst_ptr_ld
)
begin
case(sensor_manager_sm)
SM_IDLE:
begin
case(SM_CNTL_REG_RUN)
1'b0: // No Activity
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
end
1'b1: // Start at the Sensor Run-Time Code
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b1;
end
endcase
sm_instr_ptr_ce_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
SM_INC_PTR:
begin
sensor_manager_sm_nxt <= SM_INST_RD;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_read_select_nxt <= 1'b1;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
SM_INST_RD:
begin
sensor_manager_sm_nxt <= SM_REG_WR;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
SM_REG_WR:
begin
sm_read_select_nxt <= 1'b0;
case(SM_CNTL_REG_RUN)
1'b0: // A write of "0" to bit "0" of the Command register at address "0" turns off
// the Sensor Manager's Statemachine
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
1'b1: // Sensor Manager Statemachine is not stopped; continue processing
begin
sm_busy_nxt <= 1'b1;
case({WB_BUSY_POLL_I, WB_ACK_I})
2'b00: // Wait for Wish Bone Acknowledge and no need to wait for transfer complete
begin
sensor_manager_sm_nxt <= SM_REG_WR;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
2'b01: // Wish Bone Acknowledge Received and no need to wait for transfer complete
begin
case(SAVE_REG_2_MEM)
1'b0:
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_instr_ptr_ld_nxt <= CONTROL_JUMP_REG_DCD
| (MAILBOX_JUMP_INST_CYCLE & mailbox_jump_inst_ptr_ld);
sm_instr_ptr_ce_nxt <= ~ CONTROL_JUMP_REG_DCD
& ~ MAILBOX_JUMP_INST_CYCLE;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
1'b1:
begin
sensor_manager_sm_nxt <= SM_REG_RD;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b1;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
endcase
end
2'b10: // Wait for Wish Bone Acknowledge and will need to wait for transfer complete
begin
sensor_manager_sm_nxt <= SM_REG_WR;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
2'b11: // Acknowledge received but need to wait for transfer complete
begin
sensor_manager_sm_nxt <= SM_WAIT_BUSY_ON;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
endcase
end
SM_REG_RD:
begin
sm_busy_nxt <= 1'b1;
sm_read_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
case(WB_ACK_I)
1'b0: // Waiting for Wish Bone Acknowledge
begin
sensor_manager_sm_nxt <= SM_REG_RD;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
1'b1: // Got Wish Bone Acknowledge
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_instr_ptr_ld_nxt <= CONTROL_JUMP_REG_DCD;
sm_instr_ptr_ce_nxt <= ~CONTROL_JUMP_REG_DCD;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
SM_WAIT_BUSY_ON:
begin
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
case(WB_BUSY_I)
1'b0: sensor_manager_sm_nxt <= SM_WAIT_BUSY_ON; // Wait for Busy from I/F
1'b1: sensor_manager_sm_nxt <= SM_WAIT_BUSY_OFF; // Got Busy from I/F
endcase
end
SM_WAIT_BUSY_OFF:
begin
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
case({SAVE_REG_2_MEM, WB_BUSY_I})
2'b00: // Wishbone transfer complete; no need to write anything to Sensor Manager Memory
//
// Note: Writes to the command register do not enter this state.
// Therefore, there is no need to check for the end of processing.
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_instr_ptr_ce_nxt <= 1'b1;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
2'b01: // Wait for Wishbone transfer to complete
begin
sensor_manager_sm_nxt <= SM_WAIT_BUSY_OFF;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
2'b10: // Wishbone transfer complete; Write resulting register value to Sensor Manager Memory
begin
sensor_manager_sm_nxt <= SM_REG_RD;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
2'b11: // Wait for Wishbone transfer to complete
begin
sensor_manager_sm_nxt <= SM_WAIT_BUSY_OFF;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
default:
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
endmodule

View File

@ -0,0 +1,128 @@
`timescale 1ns / 10ps
module SystemClockControl (
OperatingClockRef_i,
Clock32KIn_i,
SPIClock_i,
ResetIn_i,
FfeClkSelect_i,
SmClkSelect_i,
SmSpeedSelect_i,
SpiClkSelect_i,
ClkSourceSelect_i,
Clk32KhzEnable_i,
MainClkEnable_i,
FfeClkEnable_i,
CM_AutoDrain_Busy,
SmClock_o,
FfeClock_o,
FfeClock_x2_o,
clock_32KHz_o,
multiplierClk_o,
ClockGen_State_o,
CM_FIFO_ReadClk,
clk_ringosc_i,
clk_ringosc_x2_i,
enable_i,
clk_cal_value_o,
assp_ringosc_en_o
);
// IO Declaration
input OperatingClockRef_i;
input Clock32KIn_i;
input SPIClock_i;
input ResetIn_i;
input [2:0] FfeClkSelect_i;
input [2:0] SmClkSelect_i;
input SmSpeedSelect_i;
input SpiClkSelect_i;
input ClkSourceSelect_i;
input Clk32KhzEnable_i;
input MainClkEnable_i;
input FfeClkEnable_i;
input CM_AutoDrain_Busy;
output SmClock_o;
output FfeClock_o;
output FfeClock_x2_o;
output clock_32KHz_o;
output multiplierClk_o;
output [3:0] ClockGen_State_o;
output CM_FIFO_ReadClk;
input clk_ringosc_i;
input clk_ringosc_x2_i;
input enable_i;
output [15:0] clk_cal_value_o;
output assp_ringosc_en_o;
reg multiplierClk_o;
wire [3:0] ClockGen_State_o;
wire CM_FIFO_ReadClk;
wire assp_ringosc_en_o;
// Internal Signals Declaration
wire highSpeedClock, highSpeedClock_buff, highSpeedClock_x2_buff;
reg [6:0] ClockDiv;
wire FfeClock;
reg SmClock;
wire RingOscEnable;
wire ring_osc_clk;
wire OperatingClockRef;
// Operations
// Gating the enternal osc
// assign OperatingClockRef = OperatingClockRef_i && MainClkEnable_i;
assign OperatingClockRef = OperatingClockRef_i;
// CM FIFO AutoDrain Read Clock
// assign CM_FIFO_ReadClk = CM_AutoDrain_Busy ? (FfeClock && FfeClkEnable_i): SPIClock_i;
assign CM_FIFO_ReadClk = CM_AutoDrain_Busy ? highSpeedClock_buff : SPIClock_i;
// Ring Osclilator enable when the when weither FFE or SM is busy
// assign RingOscEnable = !ResetIn_i && MainClkEnable_i && ClkSourceSelect_i;
// Logic to gate 32KHz clock when the ULPSH goes to sleep
// Only static power consumption
assign clock_32KHz_o = Clock32KIn_i && Clk32KhzEnable_i;
// Logic to select between the external high speed clock and the internal ring oscillation
// and main clock division
// assign highSpeedClock = ClkSourceSelect_i ? ring_osc_clk : OperatingClockRef;
buff buff_highSpeedClock (.A(clk_ringosc_i), .Q(highSpeedClock_buff)); // don't use a clock network for this
//pragma attribute buff_highSpeedClock dont_touch true
buff buff_highSpeedClock_x2 (.A(clk_ringosc_x2_i), .Q(highSpeedClock_x2_buff)); // don't use a clock network for this
//pragma attribute buff_highSpeedClock_x2 dont_touch true
// FFE CLK and SM CLK select and masking
// assign FfeClock_o = SpiClkSelect_i ? SPIClock_i : FfeClock && FfeClkEnable_i;
// assign SmClock_o = SmSpeedSelect_i ? SmClock : (SpiClkSelect_i ? SPIClock_i : FfeClock);
assign FfeClock_o = SpiClkSelect_i ? SPIClock_i : highSpeedClock_buff;
assign FfeClock_x2_o = SpiClkSelect_i ? SPIClock_i : highSpeedClock_x2_buff;
assign SmClock_o = SpiClkSelect_i ? SPIClock_i : highSpeedClock_buff;
ring_osc_adjust ring_osc_adjust_1 (
.reset_i ( ResetIn_i ),
.clk_ringosc_i ( clk_ringosc_i ),
.clk_32khz_i ( Clock32KIn_i ),
.enable_i ( enable_i ),
.cal_val_o ( clk_cal_value_o )
);
assign assp_ringosc_en_o = ClkSourceSelect_i || MainClkEnable_i;
endmodule

View File

@ -0,0 +1,731 @@
/*------------------------------------------------------------------------------------------
Title: TLC.v
Description:
--------------------------------------------------------------------------------------------
Revision History:
--------------------------------------------------------------------------------------------
To Do:
------------------------------------------------------------------------------------------*/
`timescale 1ns / 10ps
`include "SensorHubDefines.v"
`include "ulpsh_rtl_defines.v"
module TLC (
// General interface
input SPI_SCLK,
input FFE_Clock,
input Clock32KIn,
input ResetIn,
output SW_Reset,
output reg RingOsc_cal_en,
output reg [2:0] RingOsc_select,
input [15:0] RingOsc_cal_value,
input I2C_Master_Error,
input FFEBusyIn,
input SMBusyIn,
input SMOverrunIn,
output StartFFEOut,
// output InitSMOut, // Removed for Rel 0 on 6/18
output StartSMOut,
output reg [15:0] TimeStampOut,
output reg TimeStampOut_Tog,
output UseFastClockOut,
input [7:0] InterruptMsgFromFFEIn,
output InterruptPinOut,
input SensorInterruptIn,
output [31:0] FFE_Mailbox_Out,
input [9:0] CtrlRunTimeAddressReg, // Expanded for Rel 0 on 6/18
output reg [9:0] CtrlRunTimeAddressOut, // Expanded for Rel 0 on 6/18
output reg CtrlRunTimeAddressSM,
// Interface to SPI Slave
input [6:0] RegAddrIn,
input [7:0] RegDataIn,
output reg [7:0] RegDataOut,
input RegWriteEnableIn,
input RegReadDataAckIn,
// Interface to memories
output TLCDrivingFFEControlMem,
output TLCDrivingFFEDataMem1,
output TLCDrivingFFEDataMem2,
output TLCDrivingSMMem,
output TLCDrivingCMMem,
output MemorySelect_en,
output [2:0] MemorySelect,
output [11:0] MemoryAddressOut,
output [35:0] MemoryDataOut,
input [35:0] MemoryDataIn,
output reg MemoryReadEnableOut,
output reg MemoryWriteEnableOut,
output MemoryClockOut,
// Interface to Communication Manager FIFO
output reg CM_FIFO_ReadEnable,
input [8:0] CM_FIFO_ReadData,
input [3:0] CM_FIFO_PopFlags,
input [3:0] CM_FIFO_PushFlags,
input CM_FIFO_Overflow,
output CM_RingBufferMode,
input CM_AutoDrain_Busy,
// test points
output TP1,
output TP2,
// LEDs ON/OFF Control
output reg [2:0] leds_off_o,
// FFE CLock ENable
output reg FFE_CLK_Enable_o,
output reg ClockEnable_o,
output reg clock_32KHz_Enable_o,
output reg [2:0] FFE_Clock_Control_o,
output reg [2:0] SM_Clock_Control_o,
output reg ClkSourceSelect_o
);
parameter CYCLES_PER_MSEC = 33; // number of 32.768KHz clock cycles per millisecond
reg [7:0] CommandReg;
reg [7:0] msecs_per_sample_reg;
reg [7:0] MemSelect_reg;
reg [7:0] MemAddrLow;
reg [7:0] MemAddrHigh;
reg [7:0] MemDataByte0;
reg [7:0] MemDataByte1;
reg [7:0] MemDataByte2;
reg [7:0] MemDataByte3;
reg [3:0] MemDataByte4;
reg [7:0] CM_Control_reg;
reg WaitForMemRead;
reg WaitForMemWrite;
reg IncrementMemAddr;
reg StartFFE_32K, StartFFE_Clkin;
// reg InitSM_Clkin; // Removed for Rel 0 on 6/18
reg StartSM_Clkin;
reg [7:0] clock32K_count; // this needs to be wide enough to accomodate the CYCLES_PER_MSEC constant
reg [7:0] count_msecs;
wire pulse_1ms;
wire pulse_sample_period;
reg pulse_sample_period_reg;
wire FFE_Holdoff; // Used to ensure a full count on the First FFE run
reg FFE_Holdoff_reset;
reg FFE_Holdoff_preset;
wire RunFFEContinuously;
//wire RunFFEOnce;
//wire RunSMOnce;
//wire RunSensorInit;
wire CM_FIFO_Overflow_reg;
reg [3:0] CM_FIFO_PopFlags_r1;
reg [3:0] CM_FIFO_PopFlags_r2;
reg [3:0] CM_FIFO_PopFlags_sync;
wire I2C_Master_Error_reg;
reg [7:0] InterruptCtrl_reg;
reg [7:0] InterruptFFEMsg_clear;
wire Interrupt_En_0;
wire [7:0] InterruptFFEMsg_latched;
wire InterruptFFEMsg_ORed;
reg SW_Reset_Start;
reg SW_Reset_r1;
reg SW_Reset_r2;
reg RunFFEContinuously_r1;
reg RunFFEContinuously_r2;
reg FFEOverrun;
reg [31:0] FFE_Mailbox_reg;
wire i_StartFFEOut;
reg s1_StartFFEOut, s2_StartFFEOut;
reg s3_FFEBusyIn, s2_FFEBusyIn, s1_FFEBusyIn;
reg d_FFE_CLK_Enable;
reg s1_SMBusyIn, s2_SMBusyIn, s3_SMBusyIn;
wire d_ClockEnable;
wire smInit_enable;
// reg s1_InitSM_Clkin, s2_InitSM_Clkin, s3_InitSM_Clkin, s4_InitSM_Clkin, s5_InitSM_Clkin, s6_InitSM_Clkin; // Removed for Rel 0 on 6/18
reg s1_StartSM_Clkin, s2_StartSM_Clkin, s3_StartSM_Clkin, s4_StartSM_Clkin, s5_StartSM_Clkin, s6_StartSM_Clkin;
wire [2:0] FFE_SET, SM_SET;
wire clkSourceSelect;
reg SleepMode, IntInputLevel;
reg sensorInterrupt_s1, sensorInterrupt_s2, sensorInterrupt_s3;
wire sleepModeSet, sleepReset;
assign FFE_Mailbox_Out = {FFE_Mailbox_reg[15:0], FFE_Mailbox_reg[31:16]};
assign MemoryClockOut = SPI_SCLK;
assign RunFFEContinuously = CommandReg[0];
//assign RunFFEOnce = CommandReg[1];
//assign RunSMOnce = CommandReg[2];
//assign RunSensorInit = CommandReg[3];
//assign SW_Reset = CommandReg[6];
assign UseFastClockOut = CommandReg[7];
assign Interrupt_En_0 = InterruptCtrl_reg[0];
assign Interrupt_En_1 = InterruptCtrl_reg[1];
assign TLCDrivingFFEControlMem = MemSelect_reg[7] ? (MemSelect_reg[2:0] == 3'b000) : 1'b0;
assign TLCDrivingFFEDataMem1 = MemSelect_reg[7] ? (MemSelect_reg[2:0] == 3'b001) : 1'b0;
assign TLCDrivingFFEDataMem2 = MemSelect_reg[7] ? (MemSelect_reg[2:0] == 3'b010) : 1'b0;
assign TLCDrivingSMMem = MemSelect_reg[7] ? (MemSelect_reg[2:0] == 3'b011) : 1'b0;
assign TLCDrivingCMMem = 1'b0; // should be removed, since the CMMem is now the CM FIFO
assign MemorySelect_en = MemSelect_reg[7];
assign MemorySelect = MemSelect_reg[2:0];
assign MemoryAddressOut = {MemAddrHigh[3:0],MemAddrLow};
assign MemoryDataOut = {MemDataByte4[3:0],MemDataByte3,MemDataByte2,MemDataByte1,MemDataByte0};
assign CM_RingBufferMode = CM_Control_reg[0];
// requests to run FFE and Sensor Manager
assign pulse_1ms = (clock32K_count == (CYCLES_PER_MSEC - 1)); // 1-clock pulse each time 1ms has elapsed
assign pulse_sample_period = (pulse_1ms && (count_msecs == 1)); // 1-clock pulse @ each sample period
assign StartFFEOut = s2_StartFFEOut;
// Delay starting FFE
always @(posedge Clock32KIn or posedge ResetIn)
begin
if (ResetIn)
begin
s1_StartFFEOut <= 1'b0;
s2_StartFFEOut <= 1'b0;
end
else
begin
s1_StartFFEOut <= i_StartFFEOut;
s2_StartFFEOut <= s1_StartFFEOut;
end
end
// Synchronized FFE Busy input
// & logic to generate FFE_CLK_Enable (active when timer starts and off when busy end)
always @(posedge Clock32KIn or posedge ResetIn)
begin
if (ResetIn)
begin
s1_FFEBusyIn <= 0;
s2_FFEBusyIn <= 0;
s3_FFEBusyIn <= 0;
end
else
begin
s1_FFEBusyIn <= FFEBusyIn;
s2_FFEBusyIn <= s1_FFEBusyIn;
s3_FFEBusyIn <= s2_FFEBusyIn;
end
end
always @*
begin
if (!FFE_CLK_Enable_o)
d_FFE_CLK_Enable = s1_StartFFEOut ^ i_StartFFEOut;
else
if (s3_FFEBusyIn && !s2_FFEBusyIn)
d_FFE_CLK_Enable = 1'b0;
else
d_FFE_CLK_Enable = FFE_CLK_Enable_o;
end
always @(posedge Clock32KIn or posedge ResetIn)
begin
if (ResetIn)
begin
FFE_CLK_Enable_o <= 0;
end
else
begin
FFE_CLK_Enable_o <= d_FFE_CLK_Enable;
end
end
always @(posedge Clock32KIn or posedge ResetIn) begin
if (ResetIn) begin
clock32K_count <= 0;
count_msecs <= 1; // reset to 1 (sample period = 0 does not make sense, and should be invalid)
pulse_sample_period_reg <= 0;
TimeStampOut <= 0;
TimeStampOut_Tog <= 0;
StartFFE_32K <= 0;
FFEOverrun <= 0;
end else begin
pulse_sample_period_reg <= pulse_sample_period; // de-glitch the pulse_sample_period signal, since it's used to asynchronously reset FFE_Holdoff
if (pulse_1ms) begin
clock32K_count <= 0;
TimeStampOut <= TimeStampOut + 1; // the timestamp increments @ 1ms
TimeStampOut_Tog <= ~TimeStampOut_Tog; // the timestamp increments @ 1ms
end else begin
clock32K_count <= clock32K_count + 1;
TimeStampOut <= TimeStampOut;
TimeStampOut_Tog <= TimeStampOut_Tog;
end
if (pulse_sample_period) // sample period boundary
count_msecs <= msecs_per_sample_reg; // reset the msec counter back to the register value
else
if (pulse_1ms)
count_msecs <= count_msecs - 1; // decrement by 1 @ the 1ms boundary
else
count_msecs <= count_msecs;
//if ((clock32K_count == (CYCLES_PER_MSEC - 1)) && (count_msecs == 1)) begin // msec counter about to be reset back to the register value
if (pulse_sample_period && !SleepMode) begin // msec counter about to be reset back to the register value
if (RunFFEContinuously && !FFE_Holdoff) begin // trigger a run only if FFE_Holdoff has been deactivated
if (FFEBusyIn) begin
FFEOverrun <= 1'b1;
end else begin
StartFFE_32K <= ~StartFFE_32K;
//CMBufferBeingWrittenOut <= CMBufferBeingWrittenOut + 1;
//if (!AlternateI2CIsActiveIn) begin // If Alternate I2C is active, then we are reading the buffer
// CMBufferBeingRead <= CMBufferBeingWrittenOut;
//end
end
end
end
end
end
// software-controlled reset, 1-2 clock pulses wide @ the 32K clock
// generate a one-clock pulse @ the SPI_SCLK, to be used to preset a flop running in the 32K clock domain
always @(posedge SPI_SCLK)
if (RegWriteEnableIn && (RegAddrIn == `CommandReg) && RegDataIn[6]) // SW Reset control bit is being written
SW_Reset_Start <= 1;
else
SW_Reset_Start <= 0;
// 32K clock domain, the r1 flop gets preset by the SPI clock pulse above, and only gets deactivated after another 32K clock period (using the r2 flop)
always @(posedge Clock32KIn or posedge SW_Reset_Start)
if (SW_Reset_Start)
SW_Reset_r1 <= 1;
else
if (SW_Reset_r1 && !SW_Reset_r2)
SW_Reset_r1 <= 1;
else
SW_Reset_r1 <= 0;
// r2 flop, used to stretch the generated reset pulse
always @(posedge Clock32KIn)
SW_Reset_r2 <= SW_Reset_r1;
assign SW_Reset = SW_Reset_r2;
// When running the FFE continuously, this logic prevents the FFE from running until the start of a sample period
always @(posedge SPI_SCLK or posedge ResetIn)
if (ResetIn)
FFE_Holdoff_preset <= 0;
else
if (RegWriteEnableIn && (RegAddrIn == `CommandReg) && RegDataIn[0]) // Run FFE Continuously control bit is being written...
FFE_Holdoff_preset <= 1; // ... assert FFE_Holdoff
else
FFE_Holdoff_preset <= 0;
always @(posedge Clock32KIn or posedge ResetIn)
if (ResetIn)
FFE_Holdoff_reset <= 0;
else
if (pulse_sample_period_reg && RunFFEContinuously && FFE_Holdoff) // reset FFE_Holdoff when the first timer expiration occurs, to ensure a full first run
FFE_Holdoff_reset <= 1;
else
FFE_Holdoff_reset <= 0;
dff_pre_clr dff_pre_clr_FFE_Holdoff ( .CLK(1'b0) , .CLR(FFE_Holdoff_reset), .D(1'b0), .PRE(FFE_Holdoff_preset), .Q(FFE_Holdoff) );
// latch the I2C Master Error signal
dff_pre_clr dff_pre_clr_I2C_Master_Error ( .CLK(1'b0) , .CLR(ResetIn), .D(1'b0), .PRE(I2C_Master_Error), .Q(I2C_Master_Error_reg) );
// interrupt logic
// note: InterruptMsgFromFFEIn should be de-glitched externally (currently de-glitched in FFE_Control.v)
// logic to clear the FFE msg interrupts
always @(posedge SPI_SCLK)
if (RegWriteEnableIn && (RegAddrIn == `InterruptFFEMsg))
InterruptFFEMsg_clear <= RegDataIn[7:0];
else
InterruptFFEMsg_clear <= 8'b0;
// latch the interrupt msg from the FFE, clear when the InterruptFFEMsg register is being written
dff_pre_clr dff_pre_clr_InterruptFFEMsg_0 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[0]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[0]), .Q(InterruptFFEMsg_latched[0]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_1 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[1]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[1]), .Q(InterruptFFEMsg_latched[1]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_2 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[2]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[2]), .Q(InterruptFFEMsg_latched[2]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_3 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[3]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[3]), .Q(InterruptFFEMsg_latched[3]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_4 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[4]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[4]), .Q(InterruptFFEMsg_latched[4]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_5 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[5]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[5]), .Q(InterruptFFEMsg_latched[5]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_6 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[6]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[6]), .Q(InterruptFFEMsg_latched[6]) );
dff_pre_clr dff_pre_clr_InterruptFFEMsg_7 ( .CLK(1'b0) , .CLR(InterruptFFEMsg_clear[7]), .D(1'b0), .PRE(InterruptMsgFromFFEIn[7]), .Q(InterruptFFEMsg_latched[7]) );
assign InterruptFFEMsg_ORed = |InterruptFFEMsg_latched[7:0];
// drive the interrupt output pin: active-high, level sensitive
assign InterruptPinOut = (Interrupt_En_0 && InterruptFFEMsg_ORed) ||
(Interrupt_En_1 && (I2C_Master_Error_reg || SMOverrunIn || FFEOverrun));
// overflow detection bit
dff_pre_clr dff_pre_clr_overflow ( .CLK(1'b0) , .CLR(ResetIn), .D(1'b0), .PRE(CM_FIFO_Overflow), .Q(CM_FIFO_Overflow_reg) );
// sync the FIFO flags to the SPI clock domain
always @(posedge SPI_SCLK) begin
CM_FIFO_PopFlags_r1 <= CM_FIFO_PopFlags;
CM_FIFO_PopFlags_r2 <= CM_FIFO_PopFlags_r1;
if (CM_FIFO_PopFlags_r1 == CM_FIFO_PopFlags_r2)
CM_FIFO_PopFlags_sync <= CM_FIFO_PopFlags_r2;
else
CM_FIFO_PopFlags_sync <= CM_FIFO_PopFlags_sync;
end
//Registers for controlling the FFE and memories
always @(posedge SPI_SCLK or posedge ResetIn) begin
if (ResetIn) begin
RegDataOut <= 0;
MemoryReadEnableOut <= 0;
MemoryWriteEnableOut <= 0;
WaitForMemRead <= 0;
WaitForMemWrite <= 0;
IncrementMemAddr <= 0;
CommandReg <= 0;
msecs_per_sample_reg <= 1; // default value is 1 (sample period = 0 should be invalid)
InterruptCtrl_reg <= 0;
MemSelect_reg <= 0;
MemAddrLow <= 0;
MemAddrHigh <= 0;
MemDataByte0 <= 0;
MemDataByte1 <= 0;
MemDataByte2 <= 0;
MemDataByte3 <= 0;
MemDataByte4 <= 0;
StartFFE_Clkin <= 0;
// InitSM_Clkin <= 0; // Removed for Rel 0 on 6/18
StartSM_Clkin <= 0;
CM_FIFO_ReadEnable <= 0;
CM_Control_reg <= 0;
FFE_Mailbox_reg <= 0;
CtrlRunTimeAddressOut <= 0;
CtrlRunTimeAddressSM <= 0;
leds_off_o <= 3'b111;
ClkSourceSelect_o <= 1'b0;
clock_32KHz_Enable_o <= 1'b1;
FFE_Clock_Control_o <= FFE_SET;
SM_Clock_Control_o <= SM_SET;
RingOsc_cal_en <= 0;
RingOsc_select <= 3'h7;
end else begin
if (MemoryWriteEnableOut) begin
if(WaitForMemWrite == 0) begin
WaitForMemWrite <= 1;
end else begin
MemoryWriteEnableOut <= 0;
WaitForMemWrite <= 0;
IncrementMemAddr <= 1;
end
end // if (MemoryWriteEnableOut)
if (IncrementMemAddr) begin
IncrementMemAddr <= 0;
{MemAddrHigh[3:0],MemAddrLow} <= {MemAddrHigh[3:0],MemAddrLow} + 1;
end
if (MemoryReadEnableOut) begin
if (WaitForMemRead == 0) begin
WaitForMemRead <= 1;
end else begin
MemoryReadEnableOut <= 0;
WaitForMemRead <= 0;
MemDataByte4 <= MemoryDataIn[35:32];
MemDataByte3 <= MemoryDataIn[31:24];
MemDataByte2 <= MemoryDataIn[23:16];
MemDataByte1 <= MemoryDataIn[15:8];
MemDataByte0 <= MemoryDataIn[7:0];
end
end
// CM FIFO read control
///// Old Code
/*
if (CM_FIFO_ReadEnable)
CM_FIFO_ReadEnable <= 0;
else
if (RegAddrIn == `CM_FIFO_Data && RegReadDataAckIn)
CM_FIFO_ReadEnable <= 1;
else
CM_FIFO_ReadEnable <= 0;
*/
//// New Code
if (RegAddrIn == `CM_FIFO_Data && RegReadDataAckIn)
CM_FIFO_ReadEnable <= !CM_FIFO_ReadEnable;
else
CM_FIFO_ReadEnable <= CM_FIFO_ReadEnable;
if (RegWriteEnableIn) begin
case (RegAddrIn)
`CommandReg: begin
CommandReg <= RegDataIn;
//FFE_Holdoff <= 1;
end
`milSecSample: msecs_per_sample_reg <= RegDataIn;
`InterruptCtrl: InterruptCtrl_reg <= RegDataIn;
//`InterruptStat: // currently writes to this register does nothing, adding more interrupts may change this.
`MemSelect: MemSelect_reg <= RegDataIn;
`MemAddrLow: MemAddrLow <= RegDataIn;
`MemAddrHigh: begin
MemAddrHigh <= RegDataIn;
WaitForMemRead <= 0; // this is assigned in separate 'if' statements, the logic should be combined into 1.
MemoryReadEnableOut <= 1;
end
`MemDataByte0: MemDataByte0 <= RegDataIn;
`MemDataByte1: MemDataByte1 <= RegDataIn;
`MemDataByte2: MemDataByte2 <= RegDataIn;
`MemDataByte3: MemDataByte3 <= RegDataIn;
`MemDataByte4: begin
MemDataByte4 <= RegDataIn[3:0];
MemoryWriteEnableOut <= 1;
WaitForMemWrite <= 0; // this is assigned in separate 'if' statements, the logic should be combined into 1.
end
`CM_Control: CM_Control_reg <= RegDataIn;
`MailboxToFFE_0: FFE_Mailbox_reg[7:0] <= RegDataIn;
`MailboxToFFE_1: FFE_Mailbox_reg[15:8] <= RegDataIn;
`MailboxToFFE_2: FFE_Mailbox_reg[23:16] <= RegDataIn;
`MailboxToFFE_3: FFE_Mailbox_reg[31:24] <= RegDataIn;
`RunTimeAdrReg: begin
CtrlRunTimeAddressOut[7:0] <= RegDataIn; // Expanded for Rel 0 on 6/18
CtrlRunTimeAddressSM <= ~CtrlRunTimeAddressSM;
end
`DemoLedCtrlReg: begin
leds_off_o <= RegDataIn[2:0];
end
`ClocksControl: begin
FFE_Clock_Control_o <= RegDataIn[2:0];
SM_Clock_Control_o <= RegDataIn[5:3];
ClkSourceSelect_o <= RegDataIn[6];
clock_32KHz_Enable_o <= RegDataIn[7];
end
`RunTimeAdrReg_Upr: begin
CtrlRunTimeAddressOut[9:8] <= RegDataIn[1:0]; // New for Rel 0 on 6/18
end
`SleepControl: begin
RingOsc_cal_en <= RegDataIn[7];
RingOsc_select <= RegDataIn[6:4];
end
endcase
if ((RegAddrIn == `CommandReg) && RegDataIn[1]) // run FFE once
StartFFE_Clkin <= ~StartFFE_Clkin;
//the SM control signals come as a pair because only one should be toggled at a time if both bits are written to in CommandReg
//Initialization takes precedense over Start
// if ((RegAddrIn == `CommandReg) && RegDataIn[3]) // Removed for Rel 0 on 6/18
// InitSM_Clkin <= ~InitSM_Clkin; // Removed for Rel 0 on 6/18
// else if ((RegAddrIn == `CommandReg) && RegDataIn[2]) // Updated for Rel 0 on 6/18
if ((RegAddrIn == `CommandReg) && RegDataIn[2])
StartSM_Clkin <= ~StartSM_Clkin;
end else begin
case (RegAddrIn)
`CommandReg: RegDataOut <= { CommandReg[7], // UseFastClk
1'b0, // SW_Reset, self-clearing
1'b0, // reserved
1'b0, // reserved
1'b0, // RunSensorInit, self-clearing
1'b0, // RunSMOnce, self-clearing
1'b0, // RunFFEOnce, self-clearing
CommandReg[0] // RunFFEContinuously
};
`StatusReg: RegDataOut <= { 3'b0,
I2C_Master_Error_reg,
SMOverrunIn,
FFEOverrun,
SMBusyIn,
FFEBusyIn
}; // Status Reg
`milSecSample: RegDataOut <= msecs_per_sample_reg;
`InterruptCtrl: RegDataOut <= {6'b0, Interrupt_En_1, Interrupt_En_0};
`InterruptStat: RegDataOut <= {7'b0, InterruptFFEMsg_ORed};
`MemSelect: RegDataOut <= {MemSelect_reg[7], 4'b0, MemSelect_reg[2:0]};
`MemAddrLow: RegDataOut <= MemAddrLow;
`MemAddrHigh: RegDataOut <= MemAddrHigh;
`MemDataByte0: RegDataOut <= MemoryDataIn[7:0]; // MemDataByte0;
`MemDataByte1: RegDataOut <= MemoryDataIn[15:8]; // MemDataByte1;
`MemDataByte2: RegDataOut <= MemoryDataIn[23:16]; // MemDataByte2;
`MemDataByte3: RegDataOut <= MemoryDataIn[31:24]; // MemDataByte3;
`MemDataByte4: RegDataOut <= MemoryDataIn[35:32]; // MemDataByte4;
`CM_FIFO_Data: RegDataOut <= CM_FIFO_ReadData[7:0];
`CM_Control: RegDataOut <= {7'b0, CM_RingBufferMode};
`CM_Status: RegDataOut <= {6'b0, CM_FIFO_Overflow_reg, CM_AutoDrain_Busy};
`CM_FIFO_Flags_0: RegDataOut <= {4'b0, CM_FIFO_PopFlags_sync};
`MailboxToFFE_0: RegDataOut <= FFE_Mailbox_reg[7:0];
`MailboxToFFE_1: RegDataOut <= FFE_Mailbox_reg[15:8];
`MailboxToFFE_2: RegDataOut <= FFE_Mailbox_reg[23:16];
`MailboxToFFE_3: RegDataOut <= FFE_Mailbox_reg[31:24];
`InterruptFFEMsg: RegDataOut <= InterruptFFEMsg_latched;
`RunTimeAdrReg: RegDataOut <= CtrlRunTimeAddressReg[7:0]; // Expanded for Rel 0 on 6/18
`DemoLedCtrlReg: RegDataOut <= {5'b0, leds_off_o};
`ClocksControl: RegDataOut <= {clock_32KHz_Enable_o, ClkSourceSelect_o, SM_Clock_Control_o[2:0], FFE_Clock_Control_o[2:0]};
`SleepControl: RegDataOut <= {RingOsc_cal_en, RingOsc_select[2:0], 1'b0, sleepModeSet, IntInputLevel, SleepMode};
`RunTimeAdrReg_Upr: RegDataOut <= {6'h0, CtrlRunTimeAddressReg[9:8]}; // New for Rel 0 on 6/18
`CalValueLow: RegDataOut <= RingOsc_cal_value[7:0];
`CalValueHi: RegDataOut <= RingOsc_cal_value[15:8];
default: RegDataOut <= 8'h21;
endcase
end
end // if (ResetIn)
end // Always
assign i_StartFFEOut = StartFFE_32K ^ StartFFE_Clkin;
//assign InitSMOut = s6_InitSM_Clkin; // Removed for Rel 0 on 6/18
assign StartSMOut = s6_StartSM_Clkin;
// test points
assign TP1 = FFE_Mailbox_reg[0];
assign TP2 = RegWriteEnableIn;
// Logic to drive RIng Osc Clock Enable / Disable
//assign smInit_enable = (s2_InitSM_Clkin ^ s3_InitSM_Clkin) || (s2_StartSM_Clkin ^ s3_StartSM_Clkin); // Removed for Rel 0 on 6/18
assign smInit_enable = (s2_StartSM_Clkin ^ s3_StartSM_Clkin); // Updated for Rel 0 on 6/18
assign d_ClockEnable = ClockEnable_o ? ((!s2_SMBusyIn && s3_SMBusyIn) ? 1'b0 : 1'b1) : (( d_FFE_CLK_Enable || smInit_enable ) ? 1'b1 : 1'b0);
always @(posedge Clock32KIn or posedge ResetIn)
begin
if (ResetIn)
begin
s1_SMBusyIn <= 0;
s2_SMBusyIn <= 0;
s3_SMBusyIn <= 0;
ClockEnable_o <= 0;
// s1_InitSM_Clkin <= 0;
// s2_InitSM_Clkin <= 0;
// s3_InitSM_Clkin <= 0;
// s4_InitSM_Clkin <= 0;
// s5_InitSM_Clkin <= 0;
// s6_InitSM_Clkin <= 0;
s1_StartSM_Clkin <= 0;
s2_StartSM_Clkin <= 0;
s3_StartSM_Clkin <= 0;
s4_StartSM_Clkin <= 0;
s5_StartSM_Clkin <= 0;
s6_StartSM_Clkin <= 0;
end
else
begin
s1_SMBusyIn <= (SMBusyIn || FFEBusyIn);
s2_SMBusyIn <= s1_SMBusyIn;
s3_SMBusyIn <= s2_SMBusyIn;
ClockEnable_o <= d_ClockEnable;
// s1_InitSM_Clkin <= InitSM_Clkin;
// s2_InitSM_Clkin <= s1_InitSM_Clkin;
// s3_InitSM_Clkin <= s2_InitSM_Clkin;
// s4_InitSM_Clkin <= s3_InitSM_Clkin;
// s5_InitSM_Clkin <= s4_InitSM_Clkin;
// s6_InitSM_Clkin <= s5_InitSM_Clkin;
s1_StartSM_Clkin <= StartSM_Clkin;
s2_StartSM_Clkin <= s1_StartSM_Clkin;
s3_StartSM_Clkin <= s2_StartSM_Clkin;
s4_StartSM_Clkin <= s3_StartSM_Clkin;
s5_StartSM_Clkin <= s4_StartSM_Clkin;
s6_StartSM_Clkin <= s5_StartSM_Clkin;
end
end
// Logic to select default reset values for the SM and FFE CLK selection
assign FFE_SET[0] = (`FFE1CLK_FREQ_SLT == 8'b00000001) || (`FFE1CLK_FREQ_SLT == 8'b00000010) || (`FFE1CLK_FREQ_SLT == 8'b00000100) || (`FFE1CLK_FREQ_SLT == 8'b00001000) ||
(`FFE1CLK_FREQ_SLT == 8'b00010000) || (`FFE1CLK_FREQ_SLT == 8'b01000000);
assign FFE_SET[1] = (`FFE1CLK_FREQ_SLT == 8'b00000001) || (`FFE1CLK_FREQ_SLT == 8'b00000010) || (`FFE1CLK_FREQ_SLT == 8'b00000100) || (`FFE1CLK_FREQ_SLT == 8'b00001000) ||
(`FFE1CLK_FREQ_SLT == 8'b00100000) || (`FFE1CLK_FREQ_SLT == 8'b01000000);
assign FFE_SET[2] = (`FFE1CLK_FREQ_SLT == 8'b10000000);
assign SM_SET[0] = (`SM1CLK_FREQ_SLT == 8'b00000010) || (`SM1CLK_FREQ_SLT == 8'b00001000) || (`SM1CLK_FREQ_SLT == 8'b00100000) || (`SM1CLK_FREQ_SLT == 8'b10000000);
assign SM_SET[1] = (`SM1CLK_FREQ_SLT == 8'b00000100) || (`SM1CLK_FREQ_SLT == 8'b00001000) || (`SM1CLK_FREQ_SLT == 8'b01000000) || (`SM1CLK_FREQ_SLT == 8'b10000000);
assign SM_SET[2] = (`SM1CLK_FREQ_SLT == 8'b00010000) || (`SM1CLK_FREQ_SLT == 8'b00100000) || (`SM1CLK_FREQ_SLT == 8'b01000000) || (`SM1CLK_FREQ_SLT == 8'b10000000);
// Logic for Sleep Mode
// Sensor interrupt input is double ring to check for transtion from low to high
// Once detected, the design will enable the sampling period
assign sleepModeSet = sensorInterrupt_s2 && !sensorInterrupt_s3;
always @(posedge Clock32KIn or posedge ResetIn)
begin
if (ResetIn)
begin
sensorInterrupt_s1 <= 0;
sensorInterrupt_s2 <= 0;
sensorInterrupt_s3 <= 0;
end
else
begin
sensorInterrupt_s1 <= (SensorInterruptIn ~^ IntInputLevel) && SleepMode;
sensorInterrupt_s2 <= sensorInterrupt_s1;
sensorInterrupt_s3 <= sensorInterrupt_s2;
end
end
assign sleepReset = ResetIn || sleepModeSet;
always @(posedge SPI_SCLK or posedge sleepReset) begin
if (sleepReset)
begin
SleepMode <= 1'b0;
end
else if ((RegAddrIn == `SleepControl) && RegWriteEnableIn)
begin
SleepMode <= RegDataIn[0];
end
end
always @(posedge SPI_SCLK or posedge ResetIn) begin
if (ResetIn)
begin
IntInputLevel <= 1'b1;
end
else if ((RegAddrIn == `SleepControl) && RegWriteEnableIn)
begin
IntInputLevel <= RegDataIn[1];
end
end
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,126 @@
/***************************************************
Vendor : QuickLogic Corp.
Aurora Version : AU 1.0.0
File Name : primtive_macros.v
Author : Kishor Kumar
Description : Verilog Netlist File (For Synthesis/Pre-Layout Simulation)
*****************************************************/
/*-------------------------------------------------------------------------------
MODULE NAME : ck_buff
DESCRIPTION : Clock tree buffer
--------------------------------------------------------------------------------*/
`ifdef ck_buff
`else
`define ck_buff
module ck_buff ( A , Q )/* synthesis black_box black_box_pad_pin = "A" */;
input A/* synthesis syn_isclock=1 */;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /* ck buff */
`endif
/*-------------------------------------------------------------------------------
MODULE NAME : gclkbuff
DESCRIPTION : Global clock buffer
--------------------------------------------------------------------------------*/
`ifdef GCLKBUFF
`else
`define GCLKBUFF
module GCLKBUFF ( A , Z )/* synthesis black_box */;
input A;
output Z;
//pragma synthesis_off
//pragma synthesis_on
endmodule /* gclk buff */
`endif
/*-------------------------------------------------------------------------------
MODULE NAME : in_buff
DESCRIPTION : Input buffer
--------------------------------------------------------------------------------*/
`ifdef in_buff
`else
`define in_buff
module in_buff ( A , Q )/* synthesis black_box */;
input A;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /* in buff */
`endif
/*-------------------------------------------------------------------------------
MODULE NAME : out_buff
DESCRIPTION : Output buffer
--------------------------------------------------------------------------------*/
`ifdef out_buff
`else
`define out_buff
module out_buff ( A , Q )/* synthesis black_box */;
input A;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /* out buff */
`endif
/*-------------------------------------------------------------------------------
MODULE NAME : inv
DESCRIPTION : Inverter
--------------------------------------------------------------------------------*/
`ifdef inv
`else
`define inv
module inv ( A , Q )/* synthesis black_box */;
input A;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /*inverter*/
`endif
/*-------------------------------------------------------------------------------
MODULE NAME : buff
DESCRIPTION : Buffer
--------------------------------------------------------------------------------*/
`ifdef buff
`else
`define buff
module buff ( A , Q )/* synthesis black_box */;
input A;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /*buffer*/
`endif
/*-------------------------------------------------------------------------------
MODULE NAME : mux2x0
DESCRIPTION : Basic Mux 2:1
--------------------------------------------------------------------------------*/
`ifdef mux2x0
`else
`define mux2x0
module mux2x0 ( A , B, S, Q )/* synthesis black_box */;
input A, B, S;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /*mux2x0*/
`endif
`ifdef LOGIC_Cell
`else
`define LOGIC_Cell
module LOGIC_Cell (T0I0, T0I1, T0I2, T0I3, B0I0, B0I1, B0I2, B0I3,
TB0S, Q0DI, CD0S, Q0EN, QST, QRT, QCK, QCKS, C0Z, Q0Z, B0Z)/* synthesis black_box */;
input T0I0, T0I1, T0I2, T0I3, B0I0, B0I1, B0I2, B0I3;
input TB0S, Q0DI, CD0S, Q0EN;
input QST, QRT, QCK, QCKS;
output C0Z, B0Z, Q0Z;
//pragma synthesis_off
//pragma synthesis_on
endmodule /*LOGIC_Cell*/
`endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
`timescale 1ns / 1ns
module clock_buffer (
input A,
output Z
);
GCLKBUFF gclkbuff_0 (.A(A), .Z(Z));
//pragma attribute gclkbuff_0 ql_pack 1
//pragma attribute gclkbuff_0 hierarchy preserve
endmodule

View File

@ -0,0 +1,18 @@
`timescale 1ns / 1ns
module dff_pre_clr (
input CLK,
input CLR,
input D,
input PRE,
output Q
);
dffpc dffpc_0 ( .CLK(CLK) , .CLR(CLR), .D(D), .PRE(PRE), .Q(Q) )/* synthesis black_box */;
//pragma attribute dffpc_0 dont_touch true
endmodule

View File

@ -0,0 +1,301 @@
/* ------------------------------------------------------------------
ring_osc_adjust.v
Control logic to keep the ring oscillator's frequency within the
desired range.
divider values from ClockDivider_rev2.pdf:
SEL sysclk_x2 sysclk
--------------------------------
000 ? ?
001 2 4
010 3 6
011 4 8
100 5 10
101 6 12
110 7 14
111 8 16
------------------------------------------------------------------ */
`timescale 1ps/1ps
/*
module ring_osc_adjust (
input reset_i, // async reset
input clk_ringosc_i, // the ring oscillator output divided by 2 (this is not clk_main)
input clk_32khz_i, // 32.768KHz reference clock
input enable_i, // enable, can be tied off externally or driven occasionally to force re-calibration
output [2:0] div_sel_o // divider selection control for the ring oscillator divider circuit (in ASSP)
);
reg clk32k_r1, clk32k_r2;
reg clk32k_cycle_start;
reg enable_32k_sync, enable_32k_sync_r1;
reg enable_main_sync, enable_main_sync_r1, enable_main;
reg [10:0] clk_ringosc_div2_cnt;
reg [2:0] ring_osc_div, ring_osc_div_reg;
// divider SEL values
localparam [2:0] DIV2_SEL = 3'b001;
localparam [2:0] DIV3_SEL = 3'b010;
localparam [2:0] DIV4_SEL = 3'b011;
localparam [2:0] DIV5_SEL = 3'b100;
localparam [2:0] DIV6_SEL = 3'b101;
localparam [2:0] DIV7_SEL = 3'b110;
localparam [2:0] DIV8_SEL = 3'b111;
// threshold values for each divider value.
// These are the count values where each divider value will be applied.
// Example: if there are 395 counts on clk_ringosc_div2 within a 32KHz clock period, the ring osc is divided by 5.
// A divider of 5 means that sysclk_x2 = ring_osc/5, and sysclk = ring_osc/10.
// Nomenclature:
// ring_osc = ring oscillator raw clock (not accessible outside of ASSP)
// ring_osc_div2 = ring oscillator divided by 2 (used for calibration)
// sysclk_x2 = ring oscillator divided by SEL
// sysclk = ring oscillator divided by SEL*2 (used as system clock A.K.A. FFE clock)
// Assumptions:
// Ring osc range: 25.2MHz - 53.2MHz (39.7ns to 18.8ns period)
// I2C master will divide clk_main by 9 to produce SCL.
// SCL freq cannot exceed 400KHz.
// Guardband of 10% is added to allow for temperature/voltage variation, in case calibration is only done once at startup.
// A smaller guardband can be used if calibration is performed periodically.
localparam [10:0] DIV4_THRESHOLD = 11'd32; // (the threshold of 32 is arbitrary... just needs to be somewhat larger than 0)
localparam [10:0] DIV5_THRESHOLD = 11'd395;
localparam [10:0] DIV6_THRESHOLD = 11'd494;
localparam [10:0] DIV7_THRESHOLD = 11'd595;
localparam [10:0] DIV8_THRESHOLD = 11'd693;
// synchronize the enable to clk32k (set this FF on the rising edge of enable_i,
// clear it after one full 32KHz period has elapsed)
always @(posedge enable_i or posedge clk_32khz_i)
if (enable_i)
enable_32k_sync <= 1'b1;
else
if (enable_32k_sync_r1)
enable_32k_sync <= 1'b0;
else
enable_32k_sync <= enable_32k_sync;
always @(posedge clk_32khz_i)
enable_32k_sync_r1 <= enable_32k_sync;
assign enable_32k = enable_32k_sync_r1;
// detect rising edge on clk32khz
always @(posedge clk_ringosc_i) begin
if (!enable_i) begin
clk32k_r1 <= 1'b0;
clk32k_r2 <= 1'b0;
clk32k_cycle_start <= 1'b0;
end
else begin
clk32k_r1 <= clk_32khz_i;
clk32k_r2 <= clk32k_r1;
clk32k_cycle_start <= clk32k_r1 && !clk32k_r2;
end
end
// synchronize the stretched enable to the main clk domain,
// turn this enable off when clk32k_cycle_start is active
always @(posedge clk_ringosc_i or posedge reset_i) begin
if (reset_i) begin
enable_main_sync <= 1'b0;
enable_main_sync_r1 <= 1'b0;
enable_main <= 1'b0;
end
else begin
enable_main_sync <= enable_32k;
enable_main_sync_r1 <= enable_main_sync;
case (enable_main)
1'b0: if (clk32k_cycle_start && enable_main_sync_r1)
enable_main <= 1'b1;
else
enable_main <= 1'b0;
1'b1: if (clk32k_cycle_start && !enable_32k)
enable_main <= 1'b0;
else
enable_main <= 1'b1;
endcase
end
end
// count # of clk_ringosc_div2 cycles per 32khz clock period
always @(posedge clk_ringosc_i or posedge reset_i)
if (reset_i)
clk_ringosc_div2_cnt <= 0;
else
if (enable_main)
if (clk32k_cycle_start)
clk_ringosc_div2_cnt <= 0;
else
clk_ringosc_div2_cnt <= clk_ringosc_div2_cnt + 1;
else
clk_ringosc_div2_cnt <= 0;
// set the ring_osc clock divider value
// _div holds the temporary divider SEL valud
// _div_reg gets assigned after a full 32KHz clock period
always @(posedge clk_ringosc_i or posedge reset_i)
if (reset_i) begin
ring_osc_div <= 3'b111; // use the largest divide value by default
ring_osc_div_reg <= 3'b111;
end
else begin
if (enable_main)
case (clk_ringosc_div2_cnt)
DIV4_THRESHOLD: ring_osc_div <= DIV4_SEL;
DIV5_THRESHOLD: ring_osc_div <= DIV5_SEL;
DIV6_THRESHOLD: ring_osc_div <= DIV6_SEL;
DIV7_THRESHOLD: ring_osc_div <= DIV7_SEL;
DIV8_THRESHOLD: ring_osc_div <= DIV8_SEL;
default: ring_osc_div <= ring_osc_div; // hold for all other values
endcase
else
ring_osc_div <= ring_osc_div; // need to retain the old value when enable is off
if (clk32k_cycle_start)
ring_osc_div_reg <= ring_osc_div;
else
ring_osc_div_reg <= ring_osc_div_reg;
end
assign div_sel_o = ring_osc_div_reg;
//// New Logic to produce CNT to system
//// Detect transition of Calibration aneble from Low to Hi
always @(posedge clk_32khz_i or posedge reset_i)
begin
if (reset_i) begin
enable_r1 <= 1'b0;
enable_r2 <= 1'b0;
enable_r3 <= 1'b0;
end
else begin
enable_r1 <= enable_i;
enable_r2 <= enable_r1;
enable_r3 <= enable_r2;
end
end
// Generating enable for Clock Cnt circuit
// Default is is 2 32KHz CLK period
always @(posedge clk_32khz_i or posedge reset_i)
begin
if (reset_i)
downCnt <= 2'b0;
else
if (enable_r2 && !enable_r3)
downCnt <= 2'b11;
else if (downCnt[1] || downCnt[0])
downCnt <= downCnt - 1'b1;
else
downCnt <= downCnt;
end
// Sync to ring osc clk
always @(posedge clk_ringosc_i or posedge reset_i)
if (reset_i)
downCnt1_r1 <= 1'b0;
downCnt1_r2 <= 1'b0;
else
downCnt1_r1 <= downCnt[1];
downCnt1_r2 <= downCnt1_r1;
assign ringosccnt_reset = reset_i && !enable_i;
// Counting # of ringosc cyces in two 32KHz clock
always @(posedge clk_ringosc_i or posedge ringosccnt_reset)
begin
if (ringosccnt_reset)
ringosc_2_cnt <= 16'b0;
else if (downCnt1_r2)
ringosc_2_cnt <= ringosc_2_cnt + 1'b0;
else
ringosc_2_cnt <= ringosc_2_cnt;
end
endmodule
*/
module ring_osc_adjust (
input reset_i, // async reset
input clk_ringosc_i, // the ring oscillator output divided by 2 (this is not clk_main)
input clk_32khz_i, // 32.768KHz reference clock
input enable_i, // enable, can be tied off externally or driven occasionally to force re-calibration
output [15:0] cal_val_o // divider selection control for the ring oscillator divider circuit (in ASSP)
);
reg enable_r1, enable_r2, enable_r3;
reg [2:0] downCnt;
reg downCnt1_r1, downCnt1_r2;
reg [15:0] ringosc_2_cnt;
wire ringosccnt_reset;
//// New Logic to produce CNT to system
//// Detect transition of Calibration aneble from Low to Hi
always @(posedge clk_32khz_i or posedge reset_i)
begin
if (reset_i) begin
enable_r1 <= 1'b0;
enable_r2 <= 1'b0;
enable_r3 <= 1'b0;
end
else begin
enable_r1 <= enable_i;
enable_r2 <= enable_r1;
enable_r3 <= enable_r2;
end
end
// Generating enable for Clock Cnt circuit
// Default is is 2 32KHz CLK period
always @(posedge clk_32khz_i or posedge reset_i)
begin
if (reset_i)
downCnt <= 3'b0;
else
if (enable_r2 && !enable_r3)
downCnt <= 3'b111;
else if (downCnt != 3'b000)
downCnt <= downCnt - 1'b1;
else
downCnt <= downCnt;
end
// Sync to ring osc clk
always @(posedge clk_ringosc_i or posedge reset_i)
if (reset_i)
begin
downCnt1_r1 <= 1'b0;
downCnt1_r2 <= 1'b0;
end
else
begin
downCnt1_r1 <= downCnt[2];
downCnt1_r2 <= downCnt1_r1;
end
assign ringosccnt_reset = reset_i || !enable_i;
// Counting # of ringosc cyces in two 32KHz clock
always @(posedge clk_ringosc_i or posedge ringosccnt_reset)
begin
if (ringosccnt_reset)
ringosc_2_cnt <= 16'b0;
else if (downCnt1_r2)
ringosc_2_cnt <= ringosc_2_cnt + 1'b1;
else
ringosc_2_cnt <= ringosc_2_cnt;
end
assign cal_val_o = ringosc_2_cnt;
endmodule

View File

@ -0,0 +1,26 @@
// -----------------------------------------------------------------------------
// title : ulpsh_rtl_defines.v
// project : ULP Sensor Hub
// description : RTL defines
// -----------------------------------------------------------------------------
// copyright (c) 2014, QuickLogic Corporation
// -----------------------------------------------------------------------------
// Clock Circuit control defines
`define OP_CLK_DIV 8'b01000000
`define FFE1CLK_FREQ_SLT 8'b01000000
`define SM1CLK_FREQ_SLT 8'b00100000
`ifdef SIMULATION
`define OSC_SELECTION 1'b0
`else
`define OSC_SELECTION 1'b1
`endif
`define ENABLE_FFE_F0_SINGLE_DM
`define ENABLE_FFE_F0_EXTENDED_DM
`define FFE_F0_SEG0_OFFSET 9'h095
`define ENABLE_FFE_F0_CM_SIZE_4K

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,162 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// cavlc_fsm ////
//// ////
//// Description ////
//// controls the cavlc parsing process ////
//// ////
//// Author(s): ////
//// - bin qiu, qiubin@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//2011-8-7 18:57 initial revision
`include "defines.v"
module cavlc_fsm
(
clk,
rst_n,
ena,
start,
max_coeff_num,
TotalCoeff,
TotalCoeff_comb,
TrailingOnes,
TrailingOnes_comb,
ZeroLeft,
state,
i,
idle,
valid
);
//------------------------
//ports
//------------------------
input clk;
input rst_n;
input ena;
input start;
input [4:0] max_coeff_num;
input [4:0] TotalCoeff;
input [4:0] TotalCoeff_comb;
input [1:0] TrailingOnes;
input [1:0] TrailingOnes_comb;
input [3:0] ZeroLeft;
output [7:0] state;
output [3:0] i;
output idle;
output valid;
//------------------------
//FFs
//------------------------
reg [7:0] state;
reg [3:0] i;
reg valid;
//------------------------
//state & i & valid
//------------------------
always @(posedge clk or negedge rst_n)
if (!rst_n) begin
state <= `cavlc_idle_s;
i <= 0;
valid <= 0;
end
else if (ena)
case(state)
`cavlc_idle_s : begin
if (start) begin
state <= `cavlc_read_total_coeffs_s;
valid <= 0;
end
else begin
state <= `cavlc_idle_s;
end
end
`cavlc_read_total_coeffs_s : begin
i <= TotalCoeff_comb -1;
if (TrailingOnes_comb > 0 && TotalCoeff_comb > 0)
state <= `cavlc_read_t1s_flags_s;
else if (TotalCoeff_comb > 0)
state <= `cavlc_read_level_prefix_s;
else begin
state <= `cavlc_idle_s;
valid <= 1;
end
end
`cavlc_read_t1s_flags_s : begin
if (TrailingOnes == TotalCoeff)
state <= `cavlc_read_total_zeros_s;
else begin
state <= `cavlc_read_level_prefix_s;
i <= i - TrailingOnes;
end
end
`cavlc_read_level_prefix_s : begin
state <= `cavlc_read_level_suffix_s;
end
`cavlc_read_level_suffix_s : begin
state <= `cavlc_calc_level_s;
end
`cavlc_calc_level_s : begin
if ( i == 0 && TotalCoeff < max_coeff_num)
state <= `cavlc_read_total_zeros_s;
else if (i == 0) begin
state <= `cavlc_read_run_befores_s;
i <= TotalCoeff - 1;
end
else begin
state <= `cavlc_read_level_prefix_s;
i <= i - 1;
end
end
`cavlc_read_total_zeros_s : begin
state <= `cavlc_read_run_befores_s;
i <= TotalCoeff - 1;
end
`cavlc_read_run_befores_s : begin
if (i == 0 || ZeroLeft == 0) begin
state <= `cavlc_idle_s;
valid <= 1;
end
else begin
state <= `cavlc_read_run_befores_s;
i <= i - 1;
end
end
endcase
assign idle = state[`cavlc_idle_bit];
endmodule

View File

@ -0,0 +1,84 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// cavlc_len_gen ////
//// ////
//// Description ////
//// generate the number of bits to forward ////
//// ////
//// Author(s): ////
//// - bin qiu, qiubin@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//2011-8-7 20:19 initial revision
`include "defines.v"
module cavlc_len_gen
(
cavlc_state,
len_read_total_coeffs_comb,
len_read_levels_comb,
len_read_total_zeros_comb,
len_read_run_befores_comb,
len_comb
);
//------------------------
// ports
//------------------------
input [7:0] cavlc_state;
input [4:0] len_read_total_coeffs_comb;
input [4:0] len_read_levels_comb;
input [3:0] len_read_total_zeros_comb;
input [3:0] len_read_run_befores_comb;
output [4:0] len_comb;
//------------------------
// regs
//------------------------
reg [4:0] len_comb; //number of bits comsumed by cavlc in a cycle
//------------------------
// len_comb
//------------------------
always @ (*)
case (1'b1) //synthesis parallel_case
cavlc_state[`cavlc_read_total_coeffs_bit] : len_comb <= len_read_total_coeffs_comb;
cavlc_state[`cavlc_read_t1s_flags_bit],
cavlc_state[`cavlc_read_level_prefix_bit],
cavlc_state[`cavlc_read_level_suffix_bit] : len_comb <= len_read_levels_comb;
cavlc_state[`cavlc_read_total_zeros_bit] : len_comb <= len_read_total_zeros_comb;
cavlc_state[`cavlc_read_run_befores_bit] : len_comb <= len_read_run_befores_comb;
cavlc_state[`cavlc_calc_level_bit],
cavlc_state[`cavlc_idle_bit] : len_comb <= 0;
default : len_comb <= 'bx;
endcase
endmodule

View File

@ -0,0 +1,400 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// cavlc_read_levels ////
//// ////
//// Description ////
//// decode levels for coeffs ////
//// ////
//// Author(s): ////
//// - bin qiu, qiubin@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//2011-8-6 initiial revision
//2011-8-19 reverse the order of level
// include TrailingOnes
`include "defines.v"
module cavlc_read_levels (
clk,
rst_n,
ena,
t1s_sel,
prefix_sel,
suffix_sel,
calc_sel,
TrailingOnes,
TotalCoeff,
rbsp,
i,
level_0,
level_1,
level_2,
level_3,
level_4,
level_5,
level_6,
level_7,
level_8,
level_9,
level_10,
level_11,
level_12,
level_13,
level_14,
level_15,
len_comb
);
//------------------------
// ports
//------------------------
input clk;
input rst_n;
input ena;
input t1s_sel;
input prefix_sel;
input suffix_sel;
input calc_sel;
input [1:0] TrailingOnes;
input [4:0] TotalCoeff;
input [0:15] rbsp;
input [3:0] i;
output [8:0] level_0;
output [8:0] level_1;
output [8:0] level_2;
output [8:0] level_3;
output [8:0] level_4;
output [8:0] level_5;
output [8:0] level_6;
output [8:0] level_7;
output [8:0] level_8;
output [8:0] level_9;
output [8:0] level_10;
output [8:0] level_11;
output [8:0] level_12;
output [8:0] level_13;
output [8:0] level_14;
output [8:0] level_15;
output [4:0] len_comb;
//------------------------
// regs
//------------------------
reg [0:15] rbsp_internal; // reduce toggle rate
reg [3:0] level_prefix_comb;
reg [8:0] level_suffix;
reg [4:0] len_comb;
//------------------------
// FFs
//------------------------
reg [3:0] level_prefix;
reg [2:0] suffixLength; // range from 0 to 6
reg [8:0] level;
reg [8:0] level_abs;
reg [8:0] level_code_tmp;
reg [8:0] level_0, level_1, level_2, level_3, level_4, level_5, level_6, level_7;
reg [8:0] level_8, level_9, level_10, level_11, level_12, level_13, level_14, level_15;
//------------------------
// level_prefix_comb
//------------------------
always @(*)
if ((t1s_sel || prefix_sel || suffix_sel)&& ena)
rbsp_internal <= rbsp;
else
rbsp_internal <= 'hffff;
always @(*)
if (rbsp_internal[0]) level_prefix_comb <= 0;
else if (rbsp_internal[1]) level_prefix_comb <= 1;
else if (rbsp_internal[2]) level_prefix_comb <= 2;
else if (rbsp_internal[3]) level_prefix_comb <= 3;
else if (rbsp_internal[4]) level_prefix_comb <= 4;
else if (rbsp_internal[5]) level_prefix_comb <= 5;
else if (rbsp_internal[6]) level_prefix_comb <= 6;
else if (rbsp_internal[7]) level_prefix_comb <= 7;
else if (rbsp_internal[8]) level_prefix_comb <= 8;
else if (rbsp_internal[9]) level_prefix_comb <= 9;
else if (rbsp_internal[10]) level_prefix_comb <= 10;
else if (rbsp_internal[11]) level_prefix_comb <= 11;
else if (rbsp_internal[12]) level_prefix_comb <= 12;
else if (rbsp_internal[13]) level_prefix_comb <= 13;
else if (rbsp_internal[14]) level_prefix_comb <= 14;
else if (rbsp_internal[15]) level_prefix_comb <= 15;
else level_prefix_comb <= 'bx;
//------------------------
// level_prefix
//------------------------
always @(posedge clk or negedge rst_n)
if (!rst_n)
level_prefix <= 0;
else if (prefix_sel && ena)
level_prefix <= level_prefix_comb;
//------------------------
// suffixLength
//------------------------
wire first_level;
assign first_level = (i == TotalCoeff - TrailingOnes - 1);
always @(posedge clk or negedge rst_n)
if (!rst_n)
suffixLength <= 0;
else if (prefix_sel && ena) begin
if (TotalCoeff > 10 && TrailingOnes < 3 && first_level ) //initialize suffixLength before proceeding first level_suffix
suffixLength <= 1;
else if (first_level)
suffixLength <= 0;
else if (suffixLength == 0 && level_abs > 2'd3)
suffixLength <= 2;
else if (suffixLength == 0)
suffixLength <= 1;
else if ( level_abs > (2'd3 << (suffixLength - 1'b1) ) && suffixLength < 6)
suffixLength <= suffixLength + 1'b1;
end
//------------------------
// level_suffix
//------------------------
always @(*)
if (suffixLength > 0 && level_prefix <= 14)
level_suffix <= {3'b0, rbsp_internal[0:5] >> (3'd6 - suffixLength)};
else if (level_prefix == 14) //level_prefix == 14 && suffixLength == 0
level_suffix <= {3'b0, rbsp_internal[0:3] };
else if (level_prefix == 15)
level_suffix <= rbsp_internal[3:11];
else
level_suffix <= 0;
//------------------------
// level_code_tmp
//------------------------
always @(posedge clk or negedge rst_n)
if (!rst_n) begin
level_code_tmp <= 0;
end
else if (suffix_sel && ena) begin
level_code_tmp <= (level_prefix << suffixLength) + level_suffix +
((suffixLength == 0 && level_prefix == 15) ? 4'd15 : 0);
end
//------------------------
// level
//------------------------
wire [2:0] tmp1;
assign tmp1 = (first_level && TrailingOnes < 3)? 2'd2 : 2'd0;
always @(*)
begin
if (level_code_tmp % 2 == 0) begin
level <= ( level_code_tmp + tmp1 + 2 ) >> 1;
end
else begin
level <= (-level_code_tmp - tmp1 - 1 ) >> 1;
end
end
//------------------------
// level_abs
//------------------------
wire level_abs_refresh;
assign level_abs_refresh = calc_sel && ena;
always @(posedge clk or negedge rst_n)
if (!rst_n) begin
level_abs <= 0;
end
else if (level_abs_refresh) begin
level_abs <= level[8] ? -level : level;
end
//------------------------
// level regfile
//------------------------
always @ (posedge clk or negedge rst_n)
if (!rst_n) begin
level_0 <= 0; level_1 <= 0; level_2 <= 0; level_3 <= 0;
level_4 <= 0; level_5 <= 0; level_6 <= 0; level_7 <= 0;
level_8 <= 0; level_9 <= 0; level_10<= 0; level_11<= 0;
level_12<= 0; level_13<= 0; level_14<= 0; level_15<= 0;
end
else if (t1s_sel && ena)
case (i)
0 : level_0 <= rbsp_internal[0]? -1 : 1;
1 : begin
level_1 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_0 <= rbsp_internal[1]? -1 : 1;
end
2 : begin
level_2 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_1 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_0 <= rbsp_internal[2]? -1 : 1;
end
3 : begin
level_3 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_2 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_1 <= rbsp_internal[2]? -1 : 1;
end
4 : begin
level_4 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_3 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_2 <= rbsp_internal[2]? -1 : 1;
end
5 : begin
level_5 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_4 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_3 <= rbsp_internal[2]? -1 : 1;
end
6 : begin
level_6 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_5 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_4 <= rbsp_internal[2]? -1 : 1;
end
7 : begin
level_7 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_6 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_5 <= rbsp_internal[2]? -1 : 1;
end
8 : begin
level_8 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_7 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_6 <= rbsp_internal[2]? -1 : 1;
end
9 : begin
level_9 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_8 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_7 <= rbsp_internal[2]? -1 : 1;
end
10: begin
level_10 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_9 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_8 <= rbsp_internal[2]? -1 : 1;
end
11: begin
level_11 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_10 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_9 <= rbsp_internal[2]? -1 : 1;
end
12: begin
level_12 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_11 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_10 <= rbsp_internal[2]? -1 : 1;
end
13: begin
level_13 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_12 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_11 <= rbsp_internal[2]? -1 : 1;
end
14: begin
level_14 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_13 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_12 <= rbsp_internal[2]? -1 : 1;
end
15: begin
level_15 <= rbsp_internal[0]? -1 : 1;
if (TrailingOnes[1])
level_14 <= rbsp_internal[1]? -1 : 1;
if (TrailingOnes == 3)
level_13 <= rbsp_internal[2]? -1 : 1;
end
endcase
else if (calc_sel && ena)
case (i)
0 :level_0 <= level;
1 :level_1 <= level;
2 :level_2 <= level;
3 :level_3 <= level;
4 :level_4 <= level;
5 :level_5 <= level;
6 :level_6 <= level;
7 :level_7 <= level;
8 :level_8 <= level;
9 :level_9 <= level;
10:level_10<= level;
11:level_11<= level;
12:level_12<= level;
13:level_13<= level;
14:level_14<= level;
15:level_15<= level;
endcase
always @(*)
if(t1s_sel)
len_comb <= TrailingOnes;
else if(prefix_sel)
len_comb <= level_prefix_comb + 1;
else if(suffix_sel && suffixLength > 0 && level_prefix <= 14)
len_comb <= suffixLength;
else if(suffix_sel && level_prefix == 14)
len_comb <= 4;
else if(suffix_sel && level_prefix == 15)
len_comb <= 12;
else
len_comb <= 0;
endmodule

View File

@ -0,0 +1,368 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// cavlc_read_run_befores ////
//// ////
//// Description ////
//// decode runs and combine them with levels ////
//// ////
//// Author(s): ////
//// - bin qiu, qiubin@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//2011-8-16 initiial revision
`include "defines.v"
module cavlc_read_run_befores
(
clk,
rst_n,
ena,
sel,
clr,
ZeroLeft_init,
rbsp,
i,
TotalZeros_comb,
level_0,
level_1,
level_2,
level_3,
level_4,
level_5,
level_6,
level_7,
level_8,
level_9,
level_10,
level_11,
level_12,
level_13,
level_14,
level_15,
coeff_0,
coeff_1,
coeff_2,
coeff_3,
coeff_4,
coeff_5,
coeff_6,
coeff_7,
coeff_8,
coeff_9,
coeff_10,
coeff_11,
coeff_12,
coeff_13,
coeff_14,
coeff_15,
ZeroLeft,
len_comb
);
//----------------------
//ports
//----------------------
input clk;
input rst_n;
input ena;
input sel;
input clr;
input ZeroLeft_init;
input [0:10] rbsp;
input [3:0] i; //range from TotalCoeff-1 to 0
input [3:0] TotalZeros_comb;
input [8:0] level_0;
input [8:0] level_1;
input [8:0] level_2;
input [8:0] level_3;
input [8:0] level_4;
input [8:0] level_5;
input [8:0] level_6;
input [8:0] level_7;
input [8:0] level_8;
input [8:0] level_9;
input [8:0] level_10;
input [8:0] level_11;
input [8:0] level_12;
input [8:0] level_13;
input [8:0] level_14;
input [8:0] level_15;
output [8:0] coeff_0;
output [8:0] coeff_1;
output [8:0] coeff_2;
output [8:0] coeff_3;
output [8:0] coeff_4;
output [8:0] coeff_5;
output [8:0] coeff_6;
output [8:0] coeff_7;
output [8:0] coeff_8;
output [8:0] coeff_9;
output [8:0] coeff_10;
output [8:0] coeff_11;
output [8:0] coeff_12;
output [8:0] coeff_13;
output [8:0] coeff_14;
output [8:0] coeff_15;
output [3:0] ZeroLeft;
output [3:0] len_comb;
//----------------------
//regs
//----------------------
reg [3:0] run;
reg [3:0] len;
reg [8:0] coeff;
reg [3:0] len_comb;
//----------------------
//FFs
//----------------------
reg [3:0] ZeroLeft;
reg [8:0] coeff_0;
reg [8:0] coeff_1;
reg [8:0] coeff_2;
reg [8:0] coeff_3;
reg [8:0] coeff_4;
reg [8:0] coeff_5;
reg [8:0] coeff_6;
reg [8:0] coeff_7;
reg [8:0] coeff_8;
reg [8:0] coeff_9;
reg [8:0] coeff_10;
reg [8:0] coeff_11;
reg [8:0] coeff_12;
reg [8:0] coeff_13;
reg [8:0] coeff_14;
reg [8:0] coeff_15;
//----------------------
//run & len
//----------------------
always @(rbsp or ZeroLeft or ena or sel)
if (ena && sel)
case(ZeroLeft)
0 : begin len <= 0; run <= 0; end
1 : begin len <= 1; run <= rbsp[0]? 0:1; end
2 : begin if (rbsp[0]) begin
run <= 0;
len <= 1;
end
else if (rbsp[1]) begin
run <= 1;
len <= 2;
end
else begin
run <= 2;
len <= 2;
end
end
3 : begin
run <= 3 - rbsp[0:1];
len <= 2;
end
4 : begin
if (rbsp[0:1] != 0) begin
run <= 3 - rbsp[0:1];
len <= 2;
end
else begin
run <= rbsp[2]? 3:4;
len <= 3;
end
end
5 : begin
if (rbsp[0]) begin
run <= rbsp[1]? 0:1;
len <= 2;
end
else if (rbsp[1]) begin
run <= rbsp[2]? 2:3;
len <= 3;
end
else begin
run <= rbsp[2]? 4:5;
len <= 3;
end
end
6 : begin
if (rbsp[0:1] == 2'b11) begin
run <= 0;
len <= 2;
end
else begin
len <= 3;
case(rbsp[0:2])
3'b000 : run <= 1;
3'b001 : run <= 2;
3'b011 : run <= 3;
3'b010 : run <= 4;
3'b101 : run <= 5;
default: run <= 6;
endcase
end
end
default : begin
if (rbsp[0:2] != 0) begin
run <= 7 - rbsp[0:2];
len <= 3;
end
else begin
case (1'b1)
rbsp[3] : begin run <= 7; len <= 4; end
rbsp[4] : begin run <= 8; len <= 5; end
rbsp[5] : begin run <= 9; len <= 6; end
rbsp[6] : begin run <= 10; len <= 7; end
rbsp[7] : begin run <= 11; len <= 8; end
rbsp[8] : begin run <= 12; len <= 9; end
rbsp[9] : begin run <= 13; len <= 10;end
rbsp[10]: begin run <= 14; len <= 11;end
default : begin run <= 'bx; len <='bx;end
endcase
end
end
endcase
else begin
len <= 0;
run <= 0;
end
//----------------------
//len_comb
//----------------------
always @(*)
if (i > 0)
len_comb <= len;
else
len_comb <= 0;
//----------------------
//ZeroLeft
//----------------------
always @(posedge clk or negedge rst_n)
if (!rst_n)
ZeroLeft <= 0;
else if (ena && clr) //in case TotalCoeff >= max_coeff_num
ZeroLeft <= 0;
else if (ena && ZeroLeft_init)
ZeroLeft <= TotalZeros_comb;
else if (ena && sel )//if ZeroLeft == 0, run will be 0
ZeroLeft <= ZeroLeft - run;
//----------------------
//coeff
//----------------------
always @(*)
if (ena && sel)
case (i)
0 :coeff <= level_0;
1 :coeff <= level_1;
2 :coeff <= level_2;
3 :coeff <= level_3;
4 :coeff <= level_4;
5 :coeff <= level_5;
6 :coeff <= level_6;
7 :coeff <= level_7;
8 :coeff <= level_8;
9 :coeff <= level_9;
10:coeff <= level_10;
11:coeff <= level_11;
12:coeff <= level_12;
13:coeff <= level_13;
14:coeff <= level_14;
15:coeff <= level_15;
endcase
else
coeff <= 0;
//----------------------
//coeff_0 to coeff_15
//----------------------
always @(posedge clk or negedge rst_n)
if (!rst_n) begin
coeff_0 <= 0; coeff_1 <= 0; coeff_2 <= 0; coeff_3 <= 0;
coeff_4 <= 0; coeff_5 <= 0; coeff_6 <= 0; coeff_7 <= 0;
coeff_8 <= 0; coeff_9 <= 0; coeff_10<= 0; coeff_11<= 0;
coeff_12<= 0; coeff_13<= 0; coeff_14<= 0; coeff_15<= 0;
end
else if (ena && clr) begin
coeff_0 <= 0; coeff_1 <= 0; coeff_2 <= 0; coeff_3 <= 0;
coeff_4 <= 0; coeff_5 <= 0; coeff_6 <= 0; coeff_7 <= 0;
coeff_8 <= 0; coeff_9 <= 0; coeff_10<= 0; coeff_11<= 0;
coeff_12<= 0; coeff_13<= 0; coeff_14<= 0; coeff_15<= 0;
end
else if (ena && sel && ZeroLeft > 0)
case (ZeroLeft+i)
1 :coeff_1 <= coeff;
2 :coeff_2 <= coeff;
3 :coeff_3 <= coeff;
4 :coeff_4 <= coeff;
5 :coeff_5 <= coeff;
6 :coeff_6 <= coeff;
7 :coeff_7 <= coeff;
8 :coeff_8 <= coeff;
9 :coeff_9 <= coeff;
10:coeff_10 <= coeff;
11:coeff_11 <= coeff;
12:coeff_12 <= coeff;
13:coeff_13 <= coeff;
14:coeff_14 <= coeff;
default:
coeff_15 <= coeff;
endcase
else if (ena && sel) begin
if (i >= 0) coeff_0 <= level_0;
if (i >= 1) coeff_1 <= level_1;
if (i >= 2) coeff_2 <= level_2;
if (i >= 3) coeff_3 <= level_3;
if (i >= 4) coeff_4 <= level_4;
if (i >= 5) coeff_5 <= level_5;
if (i >= 6) coeff_6 <= level_6;
if (i >= 7) coeff_7 <= level_7;
if (i >= 8) coeff_8 <= level_8;
if (i >= 9) coeff_9 <= level_9;
if (i >= 10)coeff_10 <= level_10;
if (i >= 11)coeff_11 <= level_11;
if (i >= 12)coeff_12 <= level_12;
if (i >= 13)coeff_13 <= level_13;
if (i >= 14)coeff_14 <= level_14;
if (i == 15)coeff_15 <= level_15;
end
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,716 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// cavlc_read_total_zeros ////
//// ////
//// Description ////
//// decode total_zeros ////
//// ////
//// Author(s): ////
//// - bin qiu, qiubin@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//2011-8-14 initial version
`include "defines.v"
module cavlc_read_total_zeros
(
ena,
sel,
chroma_DC_sel,
rbsp,
TotalCoeff,
TotalZeros_comb,
len_comb
);
//------------------------
//ports
//------------------------
input ena;
input sel;
input chroma_DC_sel;
input [0:8] rbsp;
input [3:0] TotalCoeff;
output [3:0] TotalZeros_comb;
output [3:0] len_comb;
//-------------------------
//rregs
//-------------------------
reg [3:0] TotalZeros_comb; //TotalZeros will be saved as ZeroLeft in module cavlc_read_run_befores
reg [3:0] len_comb;
//for chroma_DC
reg [0:2] rbsp_chroma_DC;
reg [1:0] TotalZeros_chroma_DC;
reg [1:0] len_chroma_DC;
//for TotalCoeff <= 3
reg [0:8] rbsp_LE3;
reg [3:0] TotalZeros_LE3;
reg [3:0] len_LE3;
//for TotalCoeff > 3
reg [0:5] rbsp_G3;
reg [3:0] TotalZeros_G3;
reg [2:0] len_G3;
//----------------------------------------
//input mux
//----------------------------------------
always @(*)
if (ena && sel && chroma_DC_sel) begin
rbsp_chroma_DC <= rbsp[0:2];
rbsp_LE3 <= 'hffff;
rbsp_G3 <= 'hffff;
end
else if (ena && sel && TotalCoeff[3:2] == 2'b00) begin
rbsp_chroma_DC <= 'hffff;
rbsp_LE3 <= rbsp[0:8];
rbsp_G3 <= 'hffff;
end
else if (ena && sel)begin
rbsp_chroma_DC <= 'hffff;
rbsp_LE3 <= 'hffff;
rbsp_G3 <= rbsp[0:5];
end
else begin
rbsp_chroma_DC <= 'hffff;
rbsp_LE3 <= 'hffff;
rbsp_G3 <= 'hffff;
end
//----------------------------------------
//TotalZeros_chroma_DC & len_chroma_DC
//----------------------------------------
always @(*)
if ( TotalCoeff == 1 && rbsp_chroma_DC[0] ) begin
TotalZeros_chroma_DC <= 0;
len_chroma_DC <= 1;
end
else if ( TotalCoeff == 1 && rbsp_chroma_DC[1] ) begin
TotalZeros_chroma_DC <= 1;
len_chroma_DC <= 2;
end
else if ( TotalCoeff == 1 && rbsp_chroma_DC[2] ) begin
TotalZeros_chroma_DC <= 2;
len_chroma_DC <= 3;
end
else if ( TotalCoeff == 1 ) begin
TotalZeros_chroma_DC <= 3;
len_chroma_DC <= 3;
end
else if ( TotalCoeff == 2 && rbsp_chroma_DC[0] ) begin
TotalZeros_chroma_DC <= 0;
len_chroma_DC <= 1;
end
else if ( TotalCoeff == 2 && rbsp_chroma_DC[1] ) begin
TotalZeros_chroma_DC <= 1;
len_chroma_DC <= 2;
end
else if ( TotalCoeff == 2 ) begin
TotalZeros_chroma_DC <= 2;
len_chroma_DC <= 2;
end
else if ( rbsp_chroma_DC[0] ) begin
TotalZeros_chroma_DC <= 0;
len_chroma_DC <= 1;
end
else begin
TotalZeros_chroma_DC <= 1;
len_chroma_DC <= 1;
end
//---------------------------------
//TotalZeros_LE3 & len_LE3
//---------------------------------
always @(rbsp_LE3 or TotalCoeff)
case (TotalCoeff[1:0])
1 :begin
case(1'b1)
rbsp_LE3[0] : begin
TotalZeros_LE3 <= 0;
len_LE3 <= 1;
end
rbsp_LE3[1] : begin
len_LE3 <= 3;
if (rbsp_LE3[2])
TotalZeros_LE3 <= 1;
else
TotalZeros_LE3 <= 2;
end
rbsp_LE3[2] : begin
len_LE3 <= 4;
if (rbsp_LE3[3])
TotalZeros_LE3 <= 3;
else
TotalZeros_LE3 <= 4;
end
rbsp_LE3[3] : begin
len_LE3 <= 5;
if (rbsp_LE3[4])
TotalZeros_LE3 <= 5;
else
TotalZeros_LE3 <= 6;
end
rbsp_LE3[4] : begin
len_LE3 <= 6;
if (rbsp_LE3[5])
TotalZeros_LE3 <= 7;
else
TotalZeros_LE3 <= 8;
end
rbsp_LE3[5] : begin
len_LE3 <= 7;
if (rbsp_LE3[6])
TotalZeros_LE3 <= 9;
else
TotalZeros_LE3 <= 10;
end
rbsp_LE3[6] : begin
len_LE3 <= 8;
if (rbsp_LE3[7])
TotalZeros_LE3 <= 11;
else
TotalZeros_LE3 <= 12;
end
rbsp_LE3[7] : begin
len_LE3 <= 9;
if (rbsp_LE3[8])
TotalZeros_LE3 <= 13;
else
TotalZeros_LE3 <= 14;
end
default : begin
len_LE3 <= 9;
TotalZeros_LE3 <= 15;
end
endcase
end
2 : begin
case(1'b1)
rbsp_LE3[0] : begin
len_LE3 <= 3;
case(rbsp_LE3[1:2])
'b11 : TotalZeros_LE3 <= 0;
'b10 : TotalZeros_LE3 <= 1;
'b01 : TotalZeros_LE3 <= 2;
'b00 : TotalZeros_LE3 <= 3;
endcase
end
rbsp_LE3[1] : begin
if (rbsp_LE3[2]) begin
TotalZeros_LE3 <= 4;
len_LE3 <= 3;
end
else begin
len_LE3 <= 4;
if (rbsp_LE3[3])
TotalZeros_LE3 <= 5;
else
TotalZeros_LE3 <= 6;
end
end
rbsp_LE3[2] : begin
len_LE3 <= 4;
if (rbsp_LE3[3])
TotalZeros_LE3 <= 7;
else
TotalZeros_LE3 <= 8;
end
rbsp_LE3[3] : begin
len_LE3 <= 5;
if (rbsp_LE3[4])
TotalZeros_LE3 <= 9;
else
TotalZeros_LE3 <= 10;
end
default : begin
len_LE3 <= 6;
case(rbsp_LE3[4:5])
'b11 : TotalZeros_LE3 <= 11;
'b10 : TotalZeros_LE3 <= 12;
'b01 : TotalZeros_LE3 <= 13;
'b00 : TotalZeros_LE3 <= 14;
endcase
end
endcase
end
3 : begin
case(1'b1)
rbsp_LE3[0] : begin
len_LE3 <= 3;
case(rbsp_LE3[1:2])
'b11 : TotalZeros_LE3 <= 1;
'b10 : TotalZeros_LE3 <= 2;
'b01 : TotalZeros_LE3 <= 3;
'b00 : TotalZeros_LE3 <= 6;
endcase
end
rbsp_LE3[1] : begin
if (rbsp_LE3[2]) begin
TotalZeros_LE3 <= 7;
len_LE3 <= 3;
end
else begin
len_LE3 <= 4;
if (rbsp_LE3[3])
TotalZeros_LE3 <= 0;
else
TotalZeros_LE3 <= 4;
end
end
rbsp_LE3[2] : begin
len_LE3 <= 4;
if (rbsp_LE3[3])
TotalZeros_LE3 <= 5;
else
TotalZeros_LE3 <= 8;
end
rbsp_LE3[3] : begin
len_LE3 <= 5;
if (rbsp_LE3[4])
TotalZeros_LE3 <= 9;
else
TotalZeros_LE3 <= 10;
end
rbsp_LE3[4] : begin
len_LE3 <= 5;
TotalZeros_LE3 <= 12;
end
default : begin
len_LE3 <= 6;
if(rbsp_LE3[5])
TotalZeros_LE3 <= 11;
else
TotalZeros_LE3 <= 13;
end
endcase
end
default : begin
len_LE3 <= 'bx;
TotalZeros_LE3 <= 'bx;
end
endcase
//---------------------------------
//TotalZeros_G3 & len_G3
//---------------------------------
always @(rbsp_G3 or TotalCoeff)
case (TotalCoeff)
4 : begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 3;
case(rbsp_G3[1:2])
'b11 : TotalZeros_G3 <= 1;
'b10 : TotalZeros_G3 <= 4;
'b01 : TotalZeros_G3 <= 5;
'b00 : TotalZeros_G3 <= 6;
endcase
end
rbsp_G3[1] : begin
if (rbsp_G3[2]) begin
TotalZeros_G3 <= 8;
len_G3 <= 3;
end
else begin
len_G3 <= 4;
if (rbsp_G3[3])
TotalZeros_G3 <= 2;
else
TotalZeros_G3 <= 3;
end
end
rbsp_G3[2] : begin
len_G3 <= 4;
if (rbsp_G3[3])
TotalZeros_G3 <= 7;
else
TotalZeros_G3 <= 9;
end
default : begin
len_G3 <= 5;
case(rbsp_G3[3:4])
'b11 : TotalZeros_G3 <= 0;
'b10 : TotalZeros_G3 <= 10;
'b01 : TotalZeros_G3 <= 11;
'b00 : TotalZeros_G3 <= 12;
endcase
end
endcase
end
5 :begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 3;
case(rbsp_G3[1:2])
'b11 : TotalZeros_G3 <= 3;
'b10 : TotalZeros_G3 <= 4;
'b01 : TotalZeros_G3 <= 5;
'b00 : TotalZeros_G3 <= 6;
endcase
end
rbsp_G3[1] : begin
if (rbsp_G3[2]) begin
TotalZeros_G3 <= 7;
len_G3 <= 3;
end
else begin
len_G3 <= 4;
if (rbsp_G3[3])
TotalZeros_G3 <= 0;
else
TotalZeros_G3 <= 1;
end
end
rbsp_G3[2] : begin
len_G3 <= 4;
if (rbsp_G3[3])
TotalZeros_G3 <= 2;
else
TotalZeros_G3 <= 8;
end
rbsp_G3[3] : begin
len_G3 <= 4;
TotalZeros_G3 <= 10;
end
default : begin
len_G3 <= 5;
if (rbsp_G3[4])
TotalZeros_G3 <= 9;
else
TotalZeros_G3 <= 11;
end
endcase
end
6 : begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 3;
case(rbsp_G3[1:2])
'b11 : TotalZeros_G3 <= 2;
'b10 : TotalZeros_G3 <= 3;
'b01 : TotalZeros_G3 <= 4;
'b00 : TotalZeros_G3 <= 5;
endcase
end
rbsp_G3[1] : begin
len_G3 <= 3;
if (rbsp_G3[2])
TotalZeros_G3 <= 6;
else
TotalZeros_G3 <= 7;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 9;
end
rbsp_G3[3] : begin
len_G3 <= 4;
TotalZeros_G3 <= 8;
end
rbsp_G3[4] : begin
len_G3 <= 5;
TotalZeros_G3 <= 1;
end
default : begin
len_G3 <= 6;
if (rbsp_G3[5])
TotalZeros_G3 <= 0;
else
TotalZeros_G3 <= 10;
end
endcase
end
7 :begin
case(1'b1)
rbsp_G3[0] : begin
if (rbsp_G3[1]) begin
TotalZeros_G3 <= 5;
len_G3 <= 2;
end
else begin
len_G3 <= 3;
if (rbsp_G3[2])
TotalZeros_G3 <= 2;
else
TotalZeros_G3 <= 3;
end
end
rbsp_G3[1] : begin
len_G3 <= 3;
if (rbsp_G3[2])
TotalZeros_G3 <= 4;
else
TotalZeros_G3 <= 6;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 8;
end
rbsp_G3[3] : begin
len_G3 <= 4;
TotalZeros_G3 <= 7;
end
rbsp_G3[4] : begin
len_G3 <= 5;
TotalZeros_G3 <= 1;
end
default : begin
len_G3 <= 6;
if (rbsp_G3[5])
TotalZeros_G3 <= 0;
else
TotalZeros_G3 <= 9;
end
endcase
end
8 :begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 2;
if (rbsp_G3[1])
TotalZeros_G3 <= 4;
else
TotalZeros_G3 <= 5;
end
rbsp_G3[1] : begin
len_G3 <= 3;
if (rbsp_G3[2])
TotalZeros_G3 <= 3;
else
TotalZeros_G3 <= 6;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 7;
end
rbsp_G3[3] : begin
len_G3 <= 4;
TotalZeros_G3 <= 1;
end
rbsp_G3[4] : begin
len_G3 <= 5;
TotalZeros_G3 <= 2;
end
default : begin
len_G3 <= 6;
if (rbsp_G3[5])
TotalZeros_G3 <= 0;
else
TotalZeros_G3 <= 8;
end
endcase
end
9 : begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 2;
if (rbsp_G3[1])
TotalZeros_G3 <= 3;
else
TotalZeros_G3 <= 4;
end
rbsp_G3[1] : begin
len_G3 <= 2;
TotalZeros_G3 <= 6;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 5;
end
rbsp_G3[3] : begin
len_G3 <= 4;
TotalZeros_G3 <= 2;
end
rbsp_G3[4] : begin
len_G3 <= 5;
TotalZeros_G3 <= 7;
end
default : begin
len_G3 <= 6;
if (rbsp_G3[5])
TotalZeros_G3 <= 0;
else
TotalZeros_G3 <= 1;
end
endcase
end
10 : begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 2;
if (rbsp_G3[1])
TotalZeros_G3 <= 3;
else
TotalZeros_G3 <= 4;
end
rbsp_G3[1] : begin
len_G3 <= 2;
TotalZeros_G3 <= 5;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 2;
end
rbsp_G3[3] : begin
len_G3 <= 4;
TotalZeros_G3 <= 6;
end
default : begin
len_G3 <= 5;
if (rbsp_G3[4])
TotalZeros_G3 <= 0;
else
TotalZeros_G3 <= 1;
end
endcase
end
11 : begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 1;
TotalZeros_G3 <= 4;
end
rbsp_G3[1] : begin
len_G3 <= 3;
if (rbsp_G3[2])
TotalZeros_G3 <= 5;
else
TotalZeros_G3 <= 3;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 2;
end
default : begin
len_G3 <= 4;
if (rbsp_G3[3])
TotalZeros_G3 <= 1;
else
TotalZeros_G3 <= 0;
end
endcase
end
12 : begin
case(1'b1)
rbsp_G3[0] : begin
len_G3 <= 1;
TotalZeros_G3 <= 3;
end
rbsp_G3[1] : begin
len_G3 <= 2;
TotalZeros_G3 <= 2;
end
rbsp_G3[2] : begin
len_G3 <= 3;
TotalZeros_G3 <= 4;
end
default : begin
len_G3 <= 4;
if (rbsp_G3[3])
TotalZeros_G3 <= 1;
else
TotalZeros_G3 <= 0;
end
endcase
end
13 :begin
if (rbsp_G3[0]) begin
TotalZeros_G3 <= 2;
len_G3 <= 1;
end
else if (rbsp_G3[1]) begin
TotalZeros_G3 <= 3;
len_G3 <= 2;
end
else if (rbsp_G3[2]) begin
TotalZeros_G3 <= 1;
len_G3 <= 3;
end
else begin
TotalZeros_G3 <= 0;
len_G3 <= 3;
end
end
14 : begin
if (rbsp_G3[0]) begin
TotalZeros_G3 <= 2;
len_G3 <= 1;
end
else if (rbsp_G3[1]) begin
TotalZeros_G3 <= 1;
len_G3 <= 2;
end
else begin
TotalZeros_G3 <= 0;
len_G3 <= 2;
end
end
15 : begin
len_G3 <= 1;
if (rbsp_G3[0])
TotalZeros_G3 <= 1;
else
TotalZeros_G3 <= 0;
end
default : begin
len_G3 <= 'bx;
TotalZeros_G3 <= 'bx;
end
endcase
//---------------------------------
//TotalZeros_comb & len_comb
//---------------------------------
always @(*)
if (ena && sel && chroma_DC_sel) begin
TotalZeros_comb <= TotalZeros_chroma_DC;
len_comb <= len_chroma_DC;
end
else if (ena && sel && TotalCoeff[3:2] == 2'b00) begin
TotalZeros_comb <= TotalZeros_LE3;
len_comb <= len_LE3;
end
else if (ena && sel)begin
TotalZeros_comb <= TotalZeros_G3;
len_comb <= len_G3;
end
else begin
TotalZeros_comb <= 0;
len_comb <= 0;
end
endmodule

View File

@ -0,0 +1,294 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// cavlc_top ////
//// ////
//// Description ////
//// top module of cavlc decoder ////
//// ////
//// Author(s): ////
//// - bin qiu, qiubin@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//2011-8-7 initial version
`include "defines.v"
module cavlc_top
(
clk,
rst_n,
ena,
start,
rbsp,
nC,
max_coeff_num,
coeff_0,
coeff_1,
coeff_2,
coeff_3,
coeff_4,
coeff_5,
coeff_6,
coeff_7,
coeff_8,
coeff_9,
coeff_10,
coeff_11,
coeff_12,
coeff_13,
coeff_14,
coeff_15,
TotalCoeff,
len_comb,
idle,
valid
);
//------------------------
// ports
//------------------------
input clk, rst_n;
input ena;
input start;
input [0:15] rbsp;
input signed [5:0] nC;
input [4:0] max_coeff_num;
output signed [8:0] coeff_0;
output signed [8:0] coeff_1;
output signed [8:0] coeff_2;
output signed [8:0] coeff_3;
output signed [8:0] coeff_4;
output signed [8:0] coeff_5;
output signed [8:0] coeff_6;
output signed [8:0] coeff_7;
output signed [8:0] coeff_8;
output signed [8:0] coeff_9;
output signed [8:0] coeff_10;
output signed [8:0] coeff_11;
output signed [8:0] coeff_12;
output signed [8:0] coeff_13;
output signed [8:0] coeff_14;
output signed [8:0] coeff_15;
output [4:0] TotalCoeff;
output [4:0] len_comb;
output idle;
output valid;
//------------------------
// cavlc_read_total_coeffs
//------------------------
wire [1:0] TrailingOnes;
wire [4:0] TotalCoeff;
wire [1:0] TrailingOnes_comb;
wire [4:0] TotalCoeff_comb;
wire [4:0] len_read_total_coeffs_comb;
wire [7:0] cavlc_state;
cavlc_read_total_coeffs cavlc_read_total_coeffs(
.clk(clk),
.rst_n(rst_n),
.ena(ena),
.start(start),
.sel(cavlc_state[`cavlc_read_total_coeffs_bit]),
.rbsp(rbsp),
.nC(nC),
.TrailingOnes(TrailingOnes),
.TotalCoeff(TotalCoeff),
.TrailingOnes_comb(TrailingOnes_comb),
.TotalCoeff_comb(TotalCoeff_comb),
.len_comb(len_read_total_coeffs_comb)
);
//------------------------
// cavlc_read_levels
//------------------------
wire [4:0] len_read_levels_comb;
wire [3:0] i;
wire [8:0] level_0;
wire [8:0] level_1;
wire [8:0] level_2;
wire [8:0] level_3;
wire [8:0] level_4;
wire [8:0] level_5;
wire [8:0] level_6;
wire [8:0] level_7;
wire [8:0] level_8;
wire [8:0] level_9;
wire [8:0] level_10;
wire [8:0] level_11;
wire [8:0] level_12;
wire [8:0] level_13;
wire [8:0] level_14;
wire [8:0] level_15;
cavlc_read_levels cavlc_read_levels(
.clk(clk),
.rst_n(rst_n),
.ena(ena),
.t1s_sel(cavlc_state[`cavlc_read_t1s_flags_bit]),
.prefix_sel(cavlc_state[`cavlc_read_level_prefix_bit]),
.suffix_sel(cavlc_state[`cavlc_read_level_suffix_bit]),
.calc_sel(cavlc_state[`cavlc_calc_level_bit]),
.TrailingOnes(TrailingOnes),
.TotalCoeff(TotalCoeff),
.i(i),
.rbsp(rbsp),
.level_0(level_0),
.level_1(level_1),
.level_2(level_2),
.level_3(level_3),
.level_4(level_4),
.level_5(level_5),
.level_6(level_6),
.level_7(level_7),
.level_8(level_8),
.level_9(level_9),
.level_10(level_10),
.level_11(level_11),
.level_12(level_12),
.level_13(level_13),
.level_14(level_14),
.level_15(level_15),
.len_comb(len_read_levels_comb)
);
//------------------------
// cavlc_read_total_zeros
//------------------------
wire [3:0] TotalZeros_comb;
wire [3:0] len_read_total_zeros_comb;
cavlc_read_total_zeros cavlc_read_total_zeros(
.ena(ena),
.sel(cavlc_state[`cavlc_read_total_zeros_bit]),
.chroma_DC_sel(nC[5]),
.rbsp(rbsp[0:8]),
.TotalCoeff(TotalCoeff[3:0]),
.TotalZeros_comb(TotalZeros_comb),
.len_comb(len_read_total_zeros_comb)
);
//------------------------
// read_run_before
//------------------------
wire [3:0] ZeroLeft;
wire [3:0] len_read_run_befores_comb;
cavlc_read_run_befores cavlc_read_run_befores(
.clk(clk),
.rst_n(rst_n),
.ena(ena),
.clr(cavlc_state[`cavlc_read_total_coeffs_bit]),
.sel(cavlc_state[`cavlc_read_run_befores_bit]),
.ZeroLeft_init(cavlc_state[`cavlc_read_total_zeros_bit]),
.rbsp(rbsp[0:10]),
.i(i),
.TotalZeros_comb(TotalZeros_comb),
.level_0(level_0),
.level_1(level_1),
.level_2(level_2),
.level_3(level_3),
.level_4(level_4),
.level_5(level_5),
.level_6(level_6),
.level_7(level_7),
.level_8(level_8),
.level_9(level_9),
.level_10(level_10),
.level_11(level_11),
.level_12(level_12),
.level_13(level_13),
.level_14(level_14),
.level_15(level_15),
.coeff_0(coeff_0),
.coeff_1(coeff_1),
.coeff_2(coeff_2),
.coeff_3(coeff_3),
.coeff_4(coeff_4),
.coeff_5(coeff_5),
.coeff_6(coeff_6),
.coeff_7(coeff_7),
.coeff_8(coeff_8),
.coeff_9(coeff_9),
.coeff_10(coeff_10),
.coeff_11(coeff_11),
.coeff_12(coeff_12),
.coeff_13(coeff_13),
.coeff_14(coeff_14),
.coeff_15(coeff_15),
.ZeroLeft(ZeroLeft),
.len_comb(len_read_run_befores_comb)
);
//------------------------
// cavlc_len_gen
//------------------------
wire [4:0] len_comb;
cavlc_len_gen cavlc_len_gen(
.cavlc_state(cavlc_state),
.len_read_total_coeffs_comb(len_read_total_coeffs_comb),
.len_read_levels_comb(len_read_levels_comb),
.len_read_total_zeros_comb(len_read_total_zeros_comb),
.len_read_run_befores_comb(len_read_run_befores_comb),
.len_comb(len_comb)
);
//------------------------
// fsm
//------------------------
cavlc_fsm cavlc_fsm(
.clk(clk),
.rst_n(rst_n),
.ena(ena),
.start(start),
.max_coeff_num(max_coeff_num),
.TotalCoeff(TotalCoeff),
.TotalCoeff_comb(TotalCoeff_comb),
.TrailingOnes(TrailingOnes),
.TrailingOnes_comb(TrailingOnes_comb),
.ZeroLeft(ZeroLeft),
.state(cavlc_state),
.i(i),
.idle(idle),
.valid(valid)
);
endmodule

View File

@ -0,0 +1,22 @@
`timescale 1ns / 1ns // timescale time_unit/time_presicion
`define cavlc_idle_bit 0
`define cavlc_read_total_coeffs_bit 1
`define cavlc_read_t1s_flags_bit 2
`define cavlc_read_level_prefix_bit 3
`define cavlc_read_level_suffix_bit 4
`define cavlc_calc_level_bit 5
`define cavlc_read_total_zeros_bit 6
`define cavlc_read_run_befores_bit 7
`define cavlc_idle_s 8'b00000001
`define cavlc_read_total_coeffs_s 8'b00000010
`define cavlc_read_t1s_flags_s 8'b00000100
`define cavlc_read_level_prefix_s 8'b00001000
`define cavlc_read_level_suffix_s 8'b00010000
`define cavlc_calc_level_s 8'b00100000
`define cavlc_read_total_zeros_s 8'b01000000
`define cavlc_read_run_befores_s 8'b10000000

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,102 @@
// 5 counter with 5 clock domain
// each counter has 130 bits
// each counter has 21 output
// test: placement , routing and performace for each clock domain
module counter120bitx5(clk1,clk2,clk3,clk4,clk5,out1x,out2x,out3x,out4x,out5x,reset);
input clk1,clk2,clk3,clk4,clk5,reset;
output [13:0] out1x;
output [13:0] out2x;
output [13:0] out3x;
output [13:0] out4x;
output [13:0] out5x;
reg [120:0] cnt1;
reg [120:0] cnt2;
reg [120:0] cnt3;
reg [120:0] cnt4;
reg [120:0] cnt5;
assign out1x = {cnt1[120:115],cnt1[7:0]};
assign out2x = {cnt2[120:115],cnt2[7:0]};
assign out3x = {cnt3[120:115],cnt3[7:0]};
assign out4x = {cnt4[120:115],cnt4[7:0]};
assign out5x = {cnt5[120:115],cnt5[7:0]};
always @(posedge clk1)
begin
if (reset)
cnt1 <=1'b0;
else
cnt1 <= cnt1+1;
end
always @(posedge clk2)
begin
if (reset)
cnt2 <=1'b0;
else
cnt2 <= cnt2 +1;
end
always @(posedge clk3)
begin
if (reset)
cnt3 <=1'b0;
else
cnt3 <= cnt3 +1;
end
always @(posedge clk4)
begin
if (reset)
cnt4 <=1'b0;
else
cnt4 <= cnt4 +1;
end
always @(posedge clk5)
begin
if (reset)
cnt5 <=1'b0;
else
cnt5 <= cnt5 +1;
end
endmodule

View File

@ -0,0 +1,246 @@
# Generated by Yosys 0.9+2406 (git sha1 470f9532, gcc 9.3.0 -fPIC -Os)
.model top
.inputs clk reset enable
.outputs count(0) count(1) count(2) count(3) count(4) count(5) count(6) count(7) count(8) count(9) count(10) count(11) count(12) count(13) count(14) count(15)
.names $false
.names $true
1
.names $undef
.subckt logic_0 a=$auto$hilomap.cc:47:hilomap_worker$708
.subckt in_buff A=clk Q=$iopadmap$clk
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:12.13-12.45"
.subckt out_buff A=$iopadmap$count(0) Q=count(0)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(1) Q=count(1)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(10) Q=count(10)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(11) Q=count(11)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(12) Q=count(12)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(13) Q=count(13)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(14) Q=count(14)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(15) Q=count(15)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(2) Q=count(2)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(3) Q=count(3)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(4) Q=count(4)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(5) Q=count(5)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(6) Q=count(6)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(7) Q=count(7)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(8) Q=count(8)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt out_buff A=$iopadmap$count(9) Q=count(9)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:5.14-5.46"
.subckt in_buff A=enable Q=$iopadmap$enable
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:12.13-12.45"
.subckt in_buff A=reset Q=$iopadmap$reset
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_io_map.v:12.13-12.45"
.subckt ff CQZ=$iopadmap$count(15) D=count_ff_CQZ_D(15) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(14) D=count_ff_CQZ_D(14) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(5) D=count_ff_CQZ_D(5) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(4) D=count_ff_CQZ_D(4) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(3) D=count_ff_CQZ_D(3) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(2) D=count_ff_CQZ_D(2) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(1) D=count_ff_CQZ_D(1) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(0) D=count_ff_CQZ_D(0) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(13) D=count_ff_CQZ_D(13) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(12) D=count_ff_CQZ_D(12) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(11) D=count_ff_CQZ_D(11) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(10) D=count_ff_CQZ_D(10) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(9) D=count_ff_CQZ_D(9) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(8) D=count_ff_CQZ_D(8) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(7) D=count_ff_CQZ_D(7) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt ff CQZ=$iopadmap$count(6) D=count_ff_CQZ_D(6) QCK=$iopadmap$clk QEN=enable_LUT4_I2_O QRT=$auto$hilomap.cc:47:hilomap_worker$708 QST=$auto$hilomap.cc:47:hilomap_worker$708
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/git/yosys-testing/Designs/counter_16bit/rtl/counter_16bit.v:14.1-19.4|/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_ffs_map.v:120.8-120.84"
.subckt LUT4 I0=$auto$hilomap.cc:47:hilomap_worker$708 I1=$auto$hilomap.cc:47:hilomap_worker$708 I2=$iopadmap$enable I3=$iopadmap$reset O=enable_LUT4_I2_O
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:16.41-16.110"
.param EQN "(I0*~I1*I2*I3)+(~I0*I1*I2*I3)+(I0*I1*I2*I3)"
.param INIT 1110
.subckt LUT4 I0=$auto$hilomap.cc:47:hilomap_worker$708 I1=$auto$hilomap.cc:47:hilomap_worker$708 I2=$iopadmap$reset I3=reset_LUT4_I2_I3 O=count_ff_CQZ_D(15)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:16.41-16.110"
.param EQN "(~I0*~I1*I2*I3)"
.param INIT 0001
.subckt LUT4 I0=reset_LUT4_I3_I2 I1=$iopadmap$count(13) I2=$iopadmap$reset I3=$iopadmap$count(14) O=count_ff_CQZ_D(14)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(I0*I1*~I2*~I3)+(~I0*~I1*~I2*I3)+(I0*~I1*~I2*I3)+(~I0*I1*~I2*I3)"
.param INIT 0000011100001000
.subckt LUT4 I0=$auto$hilomap.cc:47:hilomap_worker$708 I1=$auto$hilomap.cc:47:hilomap_worker$708 I2=$iopadmap$reset I3=reset_LUT4_I2_2_I3 O=count_ff_CQZ_D(12)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:16.41-16.110"
.param EQN "(~I0*~I1*I2*I3)"
.param INIT 0001
.subckt LUT4 I0=reset_LUT4_I3_1_I2 I1=$iopadmap$count(10) I2=$iopadmap$count(11) I3=$iopadmap$count(12) O=reset_LUT4_I2_2_I3
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(~I0*~I1*~I2*~I3)+(I0*~I1*~I2*~I3)+(~I0*I1*~I2*~I3)+(I0*I1*~I2*~I3)+(~I0*~I1*I2*~I3)+(I0*~I1*I2*~I3)+(~I0*I1*I2*~I3)+(I0*I1*I2*I3)"
.param INIT 1000000001111111
.subckt LUT4 I0=reset_LUT4_I3_1_I2 I1=$iopadmap$count(10) I2=$iopadmap$reset I3=$iopadmap$count(11) O=count_ff_CQZ_D(11)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(I0*I1*~I2*~I3)+(~I0*~I1*~I2*I3)+(I0*~I1*~I2*I3)+(~I0*I1*~I2*I3)"
.param INIT 0000011100001000
.subckt LUT4 I0=$auto$hilomap.cc:47:hilomap_worker$708 I1=$auto$hilomap.cc:47:hilomap_worker$708 I2=$iopadmap$reset I3=reset_LUT4_I2_4_I3 O=count_ff_CQZ_D(9)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:16.41-16.110"
.param EQN "(~I0*~I1*I2*I3)"
.param INIT 0001
.subckt LUT4 I0=reset_LUT4_I3_2_I2 I1=$iopadmap$count(7) I2=$iopadmap$count(8) I3=$iopadmap$count(9) O=reset_LUT4_I2_4_I3
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(~I0*~I1*~I2*~I3)+(I0*~I1*~I2*~I3)+(~I0*I1*~I2*~I3)+(I0*I1*~I2*~I3)+(~I0*~I1*I2*~I3)+(I0*~I1*I2*~I3)+(~I0*I1*I2*~I3)+(I0*I1*I2*I3)"
.param INIT 1000000001111111
.subckt LUT4 I0=reset_LUT4_I3_2_I2 I1=$iopadmap$count(7) I2=$iopadmap$reset I3=$iopadmap$count(8) O=count_ff_CQZ_D(8)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(I0*I1*~I2*~I3)+(~I0*~I1*~I2*I3)+(I0*~I1*~I2*I3)+(~I0*I1*~I2*I3)"
.param INIT 0000011100001000
.subckt LUT4 I0=$auto$hilomap.cc:47:hilomap_worker$708 I1=$auto$hilomap.cc:47:hilomap_worker$708 I2=$iopadmap$reset I3=reset_LUT4_I2_6_I3 O=count_ff_CQZ_D(6)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:16.41-16.110"
.param EQN "(~I0*~I1*I2*I3)"
.param INIT 0001
.subckt LUT4 I0=reset_LUT4_I3_3_I2 I1=$iopadmap$count(4) I2=$iopadmap$count(5) I3=$iopadmap$count(6) O=reset_LUT4_I2_6_I3
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(~I0*~I1*~I2*~I3)+(I0*~I1*~I2*~I3)+(~I0*I1*~I2*~I3)+(I0*I1*~I2*~I3)+(~I0*~I1*I2*~I3)+(I0*~I1*I2*~I3)+(~I0*I1*I2*~I3)+(I0*I1*I2*I3)"
.param INIT 1000000001111111
.subckt LUT4 I0=reset_LUT4_I3_3_I2 I1=$iopadmap$count(4) I2=$iopadmap$reset I3=$iopadmap$count(5) O=count_ff_CQZ_D(5)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(I0*I1*~I2*~I3)+(~I0*~I1*~I2*I3)+(I0*~I1*~I2*I3)+(~I0*I1*~I2*I3)"
.param INIT 0000011100001000
.subckt LUT4 I0=$auto$hilomap.cc:47:hilomap_worker$708 I1=$auto$hilomap.cc:47:hilomap_worker$708 I2=$iopadmap$reset I3=reset_LUT4_I2_8_I3 O=count_ff_CQZ_D(3)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:16.41-16.110"
.param EQN "(~I0*~I1*I2*I3)"
.param INIT 0001
.subckt LUT4 I0=$iopadmap$count(0) I1=$iopadmap$count(1) I2=$iopadmap$count(2) I3=$iopadmap$count(3) O=reset_LUT4_I2_8_I3
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(~I0*~I1*~I2*~I3)+(I0*~I1*~I2*~I3)+(~I0*I1*~I2*~I3)+(I0*I1*~I2*~I3)+(~I0*~I1*I2*~I3)+(I0*~I1*I2*~I3)+(~I0*I1*I2*~I3)+(I0*I1*I2*I3)"
.param INIT 1000000001111111
.subckt LUT4 I0=$iopadmap$count(0) I1=$iopadmap$count(1) I2=$iopadmap$reset I3=$iopadmap$count(2) O=count_ff_CQZ_D(2)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(I0*I1*~I2*~I3)+(~I0*~I1*~I2*I3)+(I0*~I1*~I2*I3)+(~I0*I1*~I2*I3)"
.param INIT 0000011100001000
.subckt LUT4 I0=reset_LUT4_I3_I2 I1=$iopadmap$count(13) I2=$iopadmap$count(14) I3=$iopadmap$count(15) O=reset_LUT4_I2_I3
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(~I0*~I1*~I2*~I3)+(I0*~I1*~I2*~I3)+(~I0*I1*~I2*~I3)+(I0*I1*~I2*~I3)+(~I0*~I1*I2*~I3)+(I0*~I1*I2*~I3)+(~I0*I1*I2*~I3)+(I0*I1*I2*I3)"
.param INIT 1000000001111111
.subckt LUT4 I0=$auto$hilomap.cc:47:hilomap_worker$708 I1=$iopadmap$count(13) I2=reset_LUT4_I3_I2 I3=$iopadmap$reset O=count_ff_CQZ_D(13)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:20.41-20.110"
.param EQN "(~I0*I1*~I2*I3)+(~I0*~I1*I2*I3)"
.param INIT 00010100
.subckt LUT4 I0=$auto$hilomap.cc:47:hilomap_worker$708 I1=$iopadmap$count(10) I2=reset_LUT4_I3_1_I2 I3=$iopadmap$reset O=count_ff_CQZ_D(10)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:20.41-20.110"
.param EQN "(~I0*I1*~I2*I3)+(~I0*~I1*I2*I3)"
.param INIT 00010100
.subckt LUT4 I0=reset_LUT4_I3_2_I2 I1=$iopadmap$count(7) I2=$iopadmap$count(8) I3=$iopadmap$count(9) O=reset_LUT4_I3_1_I2
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(I0*I1*I2*I3)"
.param INIT 1000000000000000
.subckt LUT4 I0=$auto$hilomap.cc:47:hilomap_worker$708 I1=$iopadmap$count(7) I2=reset_LUT4_I3_2_I2 I3=$iopadmap$reset O=count_ff_CQZ_D(7)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:20.41-20.110"
.param EQN "(~I0*I1*~I2*I3)+(~I0*~I1*I2*I3)"
.param INIT 00010100
.subckt LUT4 I0=reset_LUT4_I3_3_I2 I1=$iopadmap$count(4) I2=$iopadmap$count(5) I3=$iopadmap$count(6) O=reset_LUT4_I3_2_I2
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(I0*I1*I2*I3)"
.param INIT 1000000000000000
.subckt LUT4 I0=$auto$hilomap.cc:47:hilomap_worker$708 I1=$iopadmap$count(4) I2=reset_LUT4_I3_3_I2 I3=$iopadmap$reset O=count_ff_CQZ_D(4)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:20.41-20.110"
.param EQN "(~I0*I1*~I2*I3)+(~I0*~I1*I2*I3)"
.param INIT 00010100
.subckt LUT4 I0=$iopadmap$count(0) I1=$iopadmap$count(1) I2=$iopadmap$count(2) I3=$iopadmap$count(3) O=reset_LUT4_I3_3_I2
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(I0*I1*I2*I3)"
.param INIT 1000000000000000
.subckt LUT4 I0=$auto$hilomap.cc:47:hilomap_worker$708 I1=$iopadmap$count(1) I2=$iopadmap$count(0) I3=$iopadmap$reset O=count_ff_CQZ_D(1)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:20.41-20.110"
.param EQN "(~I0*I1*~I2*I3)+(~I0*~I1*I2*I3)"
.param INIT 00010100
.subckt LUT4 I0=$auto$hilomap.cc:47:hilomap_worker$708 I1=$auto$hilomap.cc:47:hilomap_worker$708 I2=$iopadmap$count(0) I3=$iopadmap$reset O=count_ff_CQZ_D(0)
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:16.41-16.110"
.param EQN "(~I0*~I1*I2*I3)"
.param INIT 0001
.subckt LUT4 I0=reset_LUT4_I3_1_I2 I1=$iopadmap$count(10) I2=$iopadmap$count(11) I3=$iopadmap$count(12) O=reset_LUT4_I3_I2
.attr module_not_derived 00000000000000000000000000000001
.attr src "/home/tpagarani/antmicro_install/bin/../share/yosys/quicklogic/ap3_lut_map.v:23.41-23.109"
.param EQN "(I0*I1*I2*I3)"
.param INIT 1000000000000000
.end

View File

@ -0,0 +1,21 @@
//
// Copyright (c) 2020 QuickLogic Corporation. All Rights Reserved.
//
// Description :
// Example of asimple 16 bit up counter in Verilog HDL
//
// Version 1.0 : Initial Creation
//
module top (clk, reset, enable, count);
input clk, reset, enable;
output [15:0] count;
reg [15:0] count;
always @ (posedge clk)
if (reset == 1'b1) begin
count <= 0;
end else if ( enable == 1'b1) begin
count <= count + 1;
end
endmodule

File diff suppressed because it is too large Load Diff

311
BENCHMARK/dct_mac/rtl/dct.v Normal file
View File

@ -0,0 +1,311 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Discrete Cosine Transform, Parallel implementation ////
//// ////
//// 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: dct.v,v 1.3 2002-10-31 12:50:03 rherveille Exp $
//
// $Date: 2002-10-31 12:50:03 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:06:59 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module dct(
clk,
ena,
rst,
dstrb,
din,
dout_00, dout_01, dout_02, dout_03, dout_04, dout_05, dout_06, dout_07,
dout_10, dout_11, dout_12, dout_13, dout_14, dout_15, dout_16, dout_17,
dout_20, dout_21, dout_22, dout_23, dout_24, dout_25, dout_26, dout_27,
dout_30, dout_31, dout_32, dout_33, dout_34, dout_35, dout_36, dout_37,
dout_40, dout_41, dout_42, dout_43, dout_44, dout_45, dout_46, dout_47,
dout_50, dout_51, dout_52, dout_53, dout_54, dout_55, dout_56, dout_57,
dout_60, dout_61, dout_62, dout_63, dout_64, dout_65, dout_66, dout_67,
dout_70, dout_71, dout_72, dout_73, dout_74, dout_75, dout_76, dout_77,
douten
);
//
// parameters
//
// Worst case errors (Din = 64* -128) remain in decimal bit
// when using 13bit coefficients
//
// For ultra-high
parameter coef_width = 11;
parameter di_width = 8;
parameter do_width = 12;
//
// inputs & outputs
//
input clk;
input ena;
input rst; // active low asynchronous reset
input dstrb; // data-strobe. Present dstrb 1clk-cycle before data block
input [di_width:1] din;
output [do_width:1]
dout_00, dout_01, dout_02, dout_03, dout_04, dout_05, dout_06, dout_07,
dout_10, dout_11, dout_12, dout_13, dout_14, dout_15, dout_16, dout_17,
dout_20, dout_21, dout_22, dout_23, dout_24, dout_25, dout_26, dout_27,
dout_30, dout_31, dout_32, dout_33, dout_34, dout_35, dout_36, dout_37,
dout_40, dout_41, dout_42, dout_43, dout_44, dout_45, dout_46, dout_47,
dout_50, dout_51, dout_52, dout_53, dout_54, dout_55, dout_56, dout_57,
dout_60, dout_61, dout_62, dout_63, dout_64, dout_65, dout_66, dout_67,
dout_70, dout_71, dout_72, dout_73, dout_74, dout_75, dout_76, dout_77;
output douten; // data-out enable
reg douten;
//
// variables
//
reg go, dgo, ddgo, ddcnt, dddcnt;
reg [di_width:1] ddin;
//
// module body
//
// generate sample counter
reg [5:0] sample_cnt;
wire dcnt = &sample_cnt;
always @(posedge clk or negedge rst)
if (~rst)
sample_cnt <= #1 6'h0;
else if (ena)
if(dstrb)
sample_cnt <= #1 6'h0;
else if(~dcnt)
sample_cnt <= #1 sample_cnt + 6'h1;
// internal signals
always @(posedge clk or negedge rst)
if (~rst)
begin
go <= #1 1'b0;
dgo <= #1 1'b0;
ddgo <= #1 1'b0;
ddin <= #1 0;
douten <= #1 1'b0;
ddcnt <= #1 1'b1;
dddcnt <= #1 1'b1;
end
else if (ena)
begin
go <= #1 dstrb;
dgo <= #1 go;
ddgo <= #1 dgo;
ddin <= #1 din;
ddcnt <= #1 dcnt;
dddcnt <= #1 ddcnt;
douten <= #1 ddcnt & ~dddcnt;
end
// Hookup DCT units
// V = 0
dctub #(coef_width, di_width, 3'h0)
dct_block_0 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_00), // (U,V) = (0,0)
.dout1(dout_01), // (U,V) = (0,1)
.dout2(dout_02), // (U,V) = (0,2)
.dout3(dout_03), // (U,V) = (0,3)
.dout4(dout_04), // (U,V) = (0,4)
.dout5(dout_05), // (U,V) = (0,5)
.dout6(dout_06), // (U,V) = (0,6)
.dout7(dout_07) // (U,V) = (0,7)
);
// V = 1
dctub #(coef_width, di_width, 3'h1)
dct_block_1 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_10), // (U,V) = (1,0)
.dout1(dout_11), // (U,V) = (1,1)
.dout2(dout_12), // (U,V) = (1,2)
.dout3(dout_13), // (U,V) = (1,3)
.dout4(dout_14), // (U,V) = (1,4)
.dout5(dout_15), // (U,V) = (1,5)
.dout6(dout_16), // (U,V) = (1,6)
.dout7(dout_17) // (U,V) = (1,7)
);
// V = 2
dctub #(coef_width, di_width, 3'h2)
dct_block_2 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_20), // (U,V) = (2,0)
.dout1(dout_21), // (U,V) = (2,1)
.dout2(dout_22), // (U,V) = (2,2)
.dout3(dout_23), // (U,V) = (2,3)
.dout4(dout_24), // (U,V) = (2,4)
.dout5(dout_25), // (U,V) = (2,5)
.dout6(dout_26), // (U,V) = (2,6)
.dout7(dout_27) // (U,V) = (2,7)
);
// V = 3
dctub #(coef_width, di_width, 3'h3)
dct_block_3 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_30), // (U,V) = (3,0)
.dout1(dout_31), // (U,V) = (3,1)
.dout2(dout_32), // (U,V) = (3,2)
.dout3(dout_33), // (U,V) = (3,3)
.dout4(dout_34), // (U,V) = (3,4)
.dout5(dout_35), // (U,V) = (3,5)
.dout6(dout_36), // (U,V) = (3,6)
.dout7(dout_37) // (U,V) = (3,7)
);
// V = 4
dctub #(coef_width, di_width, 3'h4)
dct_block_4 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_40), // (U,V) = (4,0)
.dout1(dout_41), // (U,V) = (4,1)
.dout2(dout_42), // (U,V) = (4,2)
.dout3(dout_43), // (U,V) = (4,3)
.dout4(dout_44), // (U,V) = (4,4)
.dout5(dout_45), // (U,V) = (4,5)
.dout6(dout_46), // (U,V) = (4,6)
.dout7(dout_47) // (U,V) = (4,7)
);
// V = 5
dctub #(coef_width, di_width, 3'h5)
dct_block_5 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_50), // (U,V) = (5,0)
.dout1(dout_51), // (U,V) = (5,1)
.dout2(dout_52), // (U,V) = (5,2)
.dout3(dout_53), // (U,V) = (5,3)
.dout4(dout_54), // (U,V) = (5,4)
.dout5(dout_55), // (U,V) = (5,5)
.dout6(dout_56), // (U,V) = (5,6)
.dout7(dout_57) // (U,V) = (5,7)
);
// V = 6
dctub #(coef_width, di_width, 3'h6)
dct_block_6 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_60), // (U,V) = (6,0)
.dout1(dout_61), // (U,V) = (6,1)
.dout2(dout_62), // (U,V) = (6,2)
.dout3(dout_63), // (U,V) = (6,3)
.dout4(dout_64), // (U,V) = (6,4)
.dout5(dout_65), // (U,V) = (6,5)
.dout6(dout_66), // (U,V) = (6,6)
.dout7(dout_67) // (U,V) = (6,7)
);
// V = 7
dctub #(coef_width, di_width, 3'h7)
dct_block_7 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(sample_cnt[2:0]),
.y(sample_cnt[5:3]),
.ddin(ddin),
.dout0(dout_70), // (U,V) = (7,0)
.dout1(dout_71), // (U,V) = (7,1)
.dout2(dout_72), // (U,V) = (7,2)
.dout3(dout_73), // (U,V) = (7,3)
.dout4(dout_74), // (U,V) = (7,4)
.dout5(dout_75), // (U,V) = (7,5)
.dout6(dout_76), // (U,V) = (7,6)
.dout7(dout_77) // (U,V) = (7,7)
);
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,123 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Discrete Cosine Transform, MAC unit ////
//// ////
//// Virtex-II: Block-Multiplier is used ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// 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: dct_mac.v,v 1.3 2002-10-31 12:50:03 rherveille Exp $
//
// $Date: 2002-10-31 12:50:03 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:06:59 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module dct_mac(clk, ena, dclr, din, coef, result);
//
// parameters
//
parameter dwidth = 8;
parameter cwidth = 16;
parameter mwidth = dwidth + cwidth; // multiplier result
parameter rwidth = mwidth +3; // add 3 bits for growth
//
// inputs & outputs
//
input clk; // clock input
input ena; // clock enable
input dclr; // start new mac (delayed 1 cycle)
input [dwidth-1:0] din; // data input
input [cwidth-1:0] coef; // coefficient input
output [rwidth-1:0] result; // mac-result
reg [rwidth -1:0] result;
//
// variables
//
wire [mwidth-1:0] idin;
wire [mwidth-1:0] icoef;
reg [mwidth -1:0] mult_res /* synthesis syn_multstyle="block_mult" syn_pipeline=1*/ ;
wire [rwidth -1:0] ext_mult_res;
//
// module body
//
assign icoef = { {(mwidth-cwidth){coef[cwidth-1]}}, coef};
assign idin = { {(mwidth-dwidth){din[dwidth-1]}}, din};
// generate multiplier structure
always @(posedge clk)
if(ena)
mult_res <= #1 icoef * idin;
assign ext_mult_res = { {3{mult_res[mwidth-1]}}, mult_res};
// generate adder structure
always @(posedge clk)
if(ena)
if(dclr)
result <= #1 ext_mult_res;
else
result <= #1 ext_mult_res + result;
endmodule

View File

@ -0,0 +1,95 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Discrete Cosine Transform Synthesis Test ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
//// Synthesis results: ////
//// ////
//// ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// 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: dct_syn.v,v 1.3 2002-10-31 12:50:03 rherveille Exp $
//
// $Date: 2002-10-31 12:50:03 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:06:59 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//
// synopsys translate_off
`include "timescale.v"
// synopsys translate_on
module dct_syn(clk, ena, rst, dstrb, din, dout, den);
input clk;
input ena;
input rst;
input dstrb;
input [7:0] din;
output [11:0] dout;
output den;
//
// DCT unit
//
// As little as 11bits coefficients can be used while
// all errors remain in the decimal bit range (dout[0])
// total errors = 5(14bit resolution)
// = 12(13bit resolution)
// = 26(12bit resolution)
// = 54(11bit resolution)
fdct #(13) dut (
.clk(clk),
.ena(1'b1),
.rst(rst),
.dstrb(dstrb),
.din(din),
.dout(dout),
.douten(den)
);
endmodule

View File

@ -0,0 +1,106 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Discrete Cosine Transform Unit ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// 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: dctu.v,v 1.3 2002-10-31 12:50:03 rherveille Exp $
//
// $Date: 2002-10-31 12:50:03 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:06:59 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module dctu(clk, ena, ddgo, x, y, ddin, dout);
parameter coef_width = 16;
parameter di_width = 8;
parameter [2:0] v = 0;
parameter [2:0] u = 0;
//
// inputs & outputs
//
input clk;
input ena;
input ddgo; // double delayed go signal
input [2:0] x, y;
input [di_width:1] ddin; // delayed data input
output [11:0] dout;
//
// variables
//
reg [ 31:0] coef;
wire [coef_width +10:0] result;
`include "dct_cos_table.v"
//
// module body
//
// hookup cosine-table
always @(posedge clk)
if(ena)
coef <= #1 dct_cos_table(x, y, u, v);
// hookup dct-mac unit
dct_mac #(8, coef_width)
macu (
.clk(clk),
.ena(ena),
.dclr(ddgo),
.din(ddin),
.coef( coef[31:31 -coef_width +1] ),
.result(result)
);
assign dout = result[coef_width +10: coef_width -1];
endmodule

View File

@ -0,0 +1,169 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Discrete Cosine Transform, DCT unit block ////
//// ////
//// Author: Richard Herveille ////
//// richard@asics.ws ////
//// www.asics.ws ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// 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: dctub.v,v 1.3 2002-10-31 12:50:03 rherveille Exp $
//
// $Date: 2002-10-31 12:50:03 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:06:59 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module dctub(clk, ena, ddgo, x, y, ddin,
dout0, dout1, dout2, dout3, dout4, dout5, dout6, dout7);
parameter coef_width = 16;
parameter di_width = 8;
parameter [2:0] v = 3'h0;
//
// inputs & outputs
//
input clk;
input ena;
input ddgo; // double delayed go strobe
input [2:0] x, y;
input [di_width:1] ddin; // delayed data input
output [11:0] dout0, dout1, dout2, dout3, dout4, dout5, dout6, dout7;
//
// module body
//
// Hookup DCT units
dctu #(coef_width, di_width, v, 3'h0)
dct_unit_0 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout0)
);
dctu #(coef_width, di_width, v, 3'h1)
dct_unit_1 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout1)
);
dctu #(coef_width, di_width, v, 3'h2)
dct_unit_2 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout2)
);
dctu #(coef_width, di_width, v, 3'h3)
dct_unit_3 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout3)
);
dctu #(coef_width, di_width, v, 3'h4)
dct_unit_4 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout4)
);
dctu #(coef_width, di_width, v, 3'h5)
dct_unit_5 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout5)
);
dctu #(coef_width, di_width, v, 3'h6)
dct_unit_6 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout6)
);
dctu #(coef_width, di_width, v, 3'h7)
dct_unit_7 (
.clk(clk),
.ena(ena),
.ddgo(ddgo),
.x(x),
.y(y),
.ddin(ddin),
.dout(dout7)
);
endmodule

View File

@ -0,0 +1,292 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Forward Discrete Cosine Transform and ZigZag unit ////
//// ////
//// 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: fdct.v,v 1.3 2002-10-31 12:50:03 rherveille Exp $
//
// $Date: 2002-10-31 12:50:03 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:06:59 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module fdct(clk, ena, rst, dstrb, din, dout, douten);
//
// parameters
//
////////////////////////////////////////////////////////////////////
// //
// ITU-T.81, ITU-T.83 & Coefficient resolution notes //
// //
////////////////////////////////////////////////////////////////////
// //
// Worst case error (all input values -128) is //
// zero (i.e. no errors) when using 15bit coefficients //
// //
// Using less bits for the coefficients produces a biterror //
// approx. equal to (15 - used_coefficient-bits). //
// i.e. 14bit coefficients, errors in dout-bit[0] only //
// 13bit coefficients, errors in dout-bits[1:0] //
// 12bit coefficients, errors in dout-bits[2:0] etc. //
// Tests with real non-continous tone image data have shown that //
// even when using 13bit coefficients errors remain in the lsb //
// only (i.e. dout-bit[0] //
// //
// The amount of coefficient-bits needed is dependent on the //
// desired quality. //
// The JPEG-standard compliance specs.(ITU-T.83) prescribe //
// that the output of the combined DCT AND Quantization unit //
// shall not exceed 1 for the desired quality. //
// //
// This means for high quantization levels, lesser bits //
// for the DCT unit can be used. //
// //
// Looking at the recommended "quantization tables for generic //
// compliance testing of DCT-based processes" (ITU-T.83 annex B) //
// it can be noticed that relatively large quantization values //
// are being used. Errors in the lower-order bits should //
// therefore not be visible. //
// For certain applications some of the lower-order bits could //
// actually be discarded. When looking at the luminance and //
// chrominance example quantization tables (ITU-T.81 annex K) //
// it can be seen that the smallest quantization value is ten //
// (qnt_val_min = 10). This means that the lowest 2bits can be //
// discarded (set to zero '0') without having any effect on the //
// final result. In this example 11 bit or 12 bit coefficients //
// would be sufficient. //
// //
////////////////////////////////////////////////////////////////////
parameter coef_width = 11;
parameter di_width = 8;
parameter do_width = 12;
//
// inputs & outputs
//
input clk; // system clock
input ena; // clock enable
input rst; // active low asynchronous reset
input dstrb; // data-strobe. Present dstrb 1clk-cycle before data block
input [di_width-1:0] din;
output [do_width-1:0] dout;
output douten; // data-out enable
//
// variables
//
wire doe;
wire [do_width -1:0] // results from DCT module
res00, res01, res02, res03, res04, res05, res06, res07,
res10, res11, res12, res13, res14, res15, res16, res17,
res20, res21, res22, res23, res24, res25, res26, res27,
res30, res31, res32, res33, res34, res35, res36, res37,
res40, res41, res42, res43, res44, res45, res46, res47,
res50, res51, res52, res53, res54, res55, res56, res57,
res60, res61, res62, res63, res64, res65, res66, res67,
res70, res71, res72, res73, res74, res75, res76, res77;
//
// module body
//
// Hookup DCT module
dct #(coef_width, di_width, do_width)
dct_mod(
.clk(clk),
.ena(ena),
.rst(rst),
.dstrb(dstrb),
.din(din),
.dout_00(res00),
.dout_01(res01),
.dout_02(res02),
.dout_03(res03),
.dout_04(res04),
.dout_05(res05),
.dout_06(res06),
.dout_07(res07),
.dout_10(res10),
.dout_11(res11),
.dout_12(res12),
.dout_13(res13),
.dout_14(res14),
.dout_15(res15),
.dout_16(res16),
.dout_17(res17),
.dout_20(res20),
.dout_21(res21),
.dout_22(res22),
.dout_23(res23),
.dout_24(res24),
.dout_25(res25),
.dout_26(res26),
.dout_27(res27),
.dout_30(res30),
.dout_31(res31),
.dout_32(res32),
.dout_33(res33),
.dout_34(res34),
.dout_35(res35),
.dout_36(res36),
.dout_37(res37),
.dout_40(res40),
.dout_41(res41),
.dout_42(res42),
.dout_43(res43),
.dout_44(res44),
.dout_45(res45),
.dout_46(res46),
.dout_47(res47),
.dout_50(res50),
.dout_51(res51),
.dout_52(res52),
.dout_53(res53),
.dout_54(res54),
.dout_55(res55),
.dout_56(res56),
.dout_57(res57),
.dout_60(res60),
.dout_61(res61),
.dout_62(res62),
.dout_63(res63),
.dout_64(res64),
.dout_65(res65),
.dout_66(res66),
.dout_67(res67),
.dout_70(res70),
.dout_71(res71),
.dout_72(res72),
.dout_73(res73),
.dout_74(res74),
.dout_75(res75),
.dout_76(res76),
.dout_77(res77),
.douten(doe)
);
// Hookup ZigZag unit
zigzag zigzag_mod(
.clk(clk),
.ena(ena),
.dstrb(doe),
.din_00(res00),
.din_01(res01),
.din_02(res02),
.din_03(res03),
.din_04(res04),
.din_05(res05),
.din_06(res06),
.din_07(res07),
.din_10(res10),
.din_11(res11),
.din_12(res12),
.din_13(res13),
.din_14(res14),
.din_15(res15),
.din_16(res16),
.din_17(res17),
.din_20(res20),
.din_21(res21),
.din_22(res22),
.din_23(res23),
.din_24(res24),
.din_25(res25),
.din_26(res26),
.din_27(res27),
.din_30(res30),
.din_31(res31),
.din_32(res32),
.din_33(res33),
.din_34(res34),
.din_35(res35),
.din_36(res36),
.din_37(res37),
.din_40(res40),
.din_41(res41),
.din_42(res42),
.din_43(res43),
.din_44(res44),
.din_45(res45),
.din_46(res46),
.din_47(res47),
.din_50(res50),
.din_51(res51),
.din_52(res52),
.din_53(res53),
.din_54(res54),
.din_55(res55),
.din_56(res56),
.din_57(res57),
.din_60(res60),
.din_61(res61),
.din_62(res62),
.din_63(res63),
.din_64(res64),
.din_65(res65),
.din_66(res66),
.din_67(res67),
.din_70(res70),
.din_71(res71),
.din_72(res72),
.din_73(res73),
.din_74(res74),
.din_75(res75),
.din_76(res76),
.din_77(res77),
.dout(dout),
.douten(douten)
);
endmodule

View File

@ -0,0 +1,201 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Zig-Zag Unit ////
//// Performs zigzag-ing, as used by many DCT based encoders ////
//// ////
//// 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: zigzag.v,v 1.2 2002-10-23 09:06:59 rherveille Exp $
//
// $Date: 2002-10-23 09:06:59 $
// $Revision: 1.2 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// synopsys translate_off
`include "timescale.v"
// synopsys translate_on
module zigzag(
clk,
ena,
dstrb,
din_00, din_01, din_02, din_03, din_04, din_05, din_06, din_07,
din_10, din_11, din_12, din_13, din_14, din_15, din_16, din_17,
din_20, din_21, din_22, din_23, din_24, din_25, din_26, din_27,
din_30, din_31, din_32, din_33, din_34, din_35, din_36, din_37,
din_40, din_41, din_42, din_43, din_44, din_45, din_46, din_47,
din_50, din_51, din_52, din_53, din_54, din_55, din_56, din_57,
din_60, din_61, din_62, din_63, din_64, din_65, din_66, din_67,
din_70, din_71, din_72, din_73, din_74, din_75, din_76, din_77,
dout,
douten
);
//
// inputs & outputs
//
input clk; // system clock
input ena; // clock enable
input dstrb; // data-strobe. Present dstrb 1clk-cycle before data block
input [11:0]
din_00, din_01, din_02, din_03, din_04, din_05, din_06, din_07,
din_10, din_11, din_12, din_13, din_14, din_15, din_16, din_17,
din_20, din_21, din_22, din_23, din_24, din_25, din_26, din_27,
din_30, din_31, din_32, din_33, din_34, din_35, din_36, din_37,
din_40, din_41, din_42, din_43, din_44, din_45, din_46, din_47,
din_50, din_51, din_52, din_53, din_54, din_55, din_56, din_57,
din_60, din_61, din_62, din_63, din_64, din_65, din_66, din_67,
din_70, din_71, din_72, din_73, din_74, din_75, din_76, din_77;
output [11:0] dout;
output douten; // data-out enable
//
// variables
//
reg ld_zigzag;
reg [11:0] sresult [63:0]; // store results for zig-zagging
//
// module body
//
always @(posedge clk)
if(ena)
ld_zigzag <= #1 dstrb;
assign douten = ld_zigzag;
//
// Generate zig-zag structure
//
// This implicates that the quantization step be performed after
// the zig-zagging.
//
// 0: 1: 2: 3: 4: 5: 6: 7: 0: 1: 2: 3: 4: 5: 6: 7:
// 0: 63 62 58 57 49 48 36 35 3f 3e 3a 39 31 30 24 23
// 1: 61 59 56 50 47 37 34 21 3d 3b 38 32 2f 25 22 15
// 2: 60 55 51 46 38 33 22 20 3c 37 33 2e 26 21 16 14
// 3: 54 52 45 39 32 23 19 10 36 34 2d 27 20 17 13 0a
// 4: 53 44 40 31 24 18 11 09 35 2c 28 1f 18 12 0b 09
// 5: 43 41 30 25 17 12 08 03 2b 29 1e 19 11 0c 08 03
// 6: 42 29 26 16 13 07 04 02 2a 1d 1a 10 0d 07 04 02
// 7: 28 27 15 14 06 05 01 00 1c 1b 0f 0e 06 05 01 00
//
// zig-zag the DCT results
integer n;
always @(posedge clk)
if(ena)
if(ld_zigzag) // reload results-register file
begin
sresult[63] <= #1 din_00;
sresult[62] <= #1 din_01;
sresult[61] <= #1 din_10;
sresult[60] <= #1 din_20;
sresult[59] <= #1 din_11;
sresult[58] <= #1 din_02;
sresult[57] <= #1 din_03;
sresult[56] <= #1 din_12;
sresult[55] <= #1 din_21;
sresult[54] <= #1 din_30;
sresult[53] <= #1 din_40;
sresult[52] <= #1 din_31;
sresult[51] <= #1 din_22;
sresult[50] <= #1 din_13;
sresult[49] <= #1 din_04;
sresult[48] <= #1 din_05;
sresult[47] <= #1 din_14;
sresult[46] <= #1 din_23;
sresult[45] <= #1 din_32;
sresult[44] <= #1 din_41;
sresult[43] <= #1 din_50;
sresult[42] <= #1 din_60;
sresult[41] <= #1 din_51;
sresult[40] <= #1 din_42;
sresult[39] <= #1 din_33;
sresult[38] <= #1 din_24;
sresult[37] <= #1 din_15;
sresult[36] <= #1 din_06;
sresult[35] <= #1 din_07;
sresult[34] <= #1 din_16;
sresult[33] <= #1 din_25;
sresult[32] <= #1 din_34;
sresult[31] <= #1 din_43;
sresult[30] <= #1 din_52;
sresult[29] <= #1 din_61;
sresult[28] <= #1 din_70;
sresult[27] <= #1 din_71;
sresult[26] <= #1 din_62;
sresult[25] <= #1 din_53;
sresult[24] <= #1 din_44;
sresult[23] <= #1 din_35;
sresult[22] <= #1 din_26;
sresult[21] <= #1 din_17;
sresult[20] <= #1 din_27;
sresult[19] <= #1 din_36;
sresult[18] <= #1 din_45;
sresult[17] <= #1 din_54;
sresult[16] <= #1 din_63;
sresult[15] <= #1 din_72;
sresult[14] <= #1 din_73;
sresult[13] <= #1 din_64;
sresult[12] <= #1 din_55;
sresult[11] <= #1 din_46;
sresult[10] <= #1 din_37;
sresult[09] <= #1 din_47;
sresult[08] <= #1 din_56;
sresult[07] <= #1 din_65;
sresult[06] <= #1 din_74;
sresult[05] <= #1 din_75;
sresult[04] <= #1 din_66;
sresult[03] <= #1 din_57;
sresult[02] <= #1 din_67;
sresult[01] <= #1 din_76;
sresult[00] <= #1 din_77;
end
else // shift results out
for (n=1; n<=63; n=n+1) // do not change sresult[0]
sresult[n] <= #1 sresult[n -1];
assign dout = sresult[63];
endmodule

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,63 @@
/*--------------------------------------------------------------------------
--------------------------------------------------------------------------
-- File Name : diffeq.v
-- Author(s) : P. Sridhar
-- Affiliation : Laboratory for Digital Design Environments
-- Department of Electrical & Computer Engineering
-- University of Cincinnati
-- Date Created : June 1991.
-- Introduction : Behavioral description of a differential equation
-- solver written in a synthesizable subset of VHDL.
-- Source : Written in HardwareC by Rajesh Gupta, Stanford Univ.
-- Obtained from the Highlevel Synthesis Workshop
-- Repository.
--
-- Modified For Synthesis by Jay(anta) Roy, University of Cincinnati.
-- Date Modified : Sept, 91.
--
-- Disclaimer : This comes with absolutely no guarantees of any
-- kind (just stating the obvious ...)
--
-- Acknowledgement : The Distributed Synthesis Systems research at
-- the Laboratory for Digital Design Environments,
-- University of Cincinnati, is sponsored in part
-- by the Defense Advanced Research Projects Agency
-- under order number 7056 monitored by the Federal
-- Bureau of Investigation under contract number
-- J-FBI-89-094.
--
--------------------------------------------------------------------------
-------------------------------------------------------------------------*/
module diffeq_f_systemC(aport, dxport, xport, yport, uport, clk, reset);
input clk;
input reset;
input [31:0]aport;
input [31:0]dxport;
output [31:0]xport;
output [31:0]yport;
output [31:0]uport;
reg [31:0]xport;
reg [31:0]yport;
reg [31:0]uport;
wire [31:0]temp;
assign temp = uport * dxport;
always @(posedge clk )
begin
if (reset == 1'b1)
begin
xport <= 0;
yport <= 0;
uport <= 0;
end
else
if (xport < aport)
begin
xport <= xport + dxport;
yport <= yport + temp;//(uport * dxport);
uport <= (uport - (temp/*(uport * dxport)*/ * (5 * xport))) - (dxport * (3 * yport));
end
end
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,589 @@
// -----------------------------------------------------------------------------
// title : Sensor Manager Statemachine
// project : ULP Sensor Hub
// -----------------------------------------------------------------------------
// file : StateMachine.v
// author : Glen Gomes
// company : QuickLogic Corp
// created : 2013/12/06
// last update : 2013/12/06
// platform : PolarPro III
// standard : Verilog 2001
// -----------------------------------------------------------------------------
// description: The Sensor Manger Statemachine is responsible for controlling the
// operations of the Sensor Manager. These include performing
// transfers between Sensor Memory and various registers.
// -----------------------------------------------------------------------------
// copyright (c) 2013
// -----------------------------------------------------------------------------
// revisions :
// date version author description
// 2013/12/06 1.0 Glen Gomes created
// -----------------------------------------------------------------------------
// Comments: This solution is specifically for use with the QuickLogic
// PolarPro III device.
// -----------------------------------------------------------------------------
`timescale 1ns/10ps
module StateMachine (
CLK_IN,
RESET_IN,
RUNTIME_ADDRESS,
CONTROL_JUMP_REG_DCD,
SAVE_REG_2_MEM,
WB_ACK_I,
WB_BUSY_I,
WB_BUSY_POLL_I,
WB_WE_O,
WB_STB_O,
WB_CYC_O,
SM_CNTL_REG_RUN,
SM_CNTL_INIT_SEQ,
SM_READ_DATA,
SM_INSTR_PTR,
SM_READ_SELECT,
SM_WRITE_SELECT,
SM_BUSY
);
//-----Port Signals--------------------
//
input CLK_IN;
input RESET_IN;
input [7:0] RUNTIME_ADDRESS;
input CONTROL_JUMP_REG_DCD;
input SAVE_REG_2_MEM;
input WB_ACK_I;
input WB_BUSY_I;
input WB_BUSY_POLL_I;
output WB_WE_O;
output WB_STB_O;
output WB_CYC_O;
input SM_CNTL_REG_RUN;
input SM_CNTL_INIT_SEQ;
input [7:0] SM_READ_DATA;
output [7:0] SM_INSTR_PTR;
output SM_READ_SELECT;
output SM_WRITE_SELECT;
output SM_BUSY;
wire CLK_IN;
wire RESET_IN;
wire [7:0] RUNTIME_ADDRESS;
wire CONTROL_JUMP_REG_DCD;
wire SAVE_REG_2_MEM;
wire WB_ACK_I;
wire WB_BUSY_I;
wire WB_BUSY_POLL_I;
reg WB_WE_O;
reg wb_we_o_nxt;
reg WB_STB_O;
reg wb_stb_o_nxt;
reg WB_CYC_O;
reg wb_cyc_o_nxt;
wire SM_CNTL_REG_RUN;
wire SM_CNTL_INIT_SEQ;
wire [7:0] SM_READ_DATA;
reg [7:0] SM_INSTR_PTR;
reg [7:0] sm_instr_ptr_nxt;
reg SM_READ_SELECT;
reg sm_read_select_nxt;
reg SM_WRITE_SELECT;
reg sm_write_select_nxt;
reg SM_BUSY;
reg sm_busy_nxt;
//-----Internal Signals--------------------
//
//
// Define the Statemachine registers
//
reg [3:0] sensor_manager_sm;
reg [3:0] sensor_manager_sm_nxt;
//
// Define the Instruction Pointer variables
//
reg sm_instr_ptr_ce;
reg sm_instr_ptr_ce_nxt;
reg sm_instr_ptr_ld;
reg sm_instr_ptr_ld_nxt;
reg sm_instr_ptr_sel;
reg sm_instr_ptr_sel_nxt;
//------Define Parameters---------
//
//
// Define the Sensor Manager Statemachine States
//
// Note: These states are chosen to allow for overlap of various signals
// during operation. This overlap should help reduce timing
// dependancies.
//
parameter SM_IDLE = 4'h0;
parameter SM_INC_PTR = 4'h1;
parameter SM_INST_RD = 4'h2;
//parameter SM_INST_DCD = 4'h3; // Note: Will be used for TimeStamp Support in a future design
parameter SM_REG_WR = 4'h4;
parameter SM_REG_RD = 4'h5;
parameter SM_WAIT_BUSY_ON = 4'h6;
parameter SM_WAIT_BUSY_OFF = 4'h7;
//
// Sensor Manager Initialization Start Address
//
// Note: The previous IP used the reset of the "RuntimeAddress" register to
// select the sensor initialization code. This value explicity selects
// the value for the start (or re-start) of initialization.
//
parameter SM_INIT_INSTR_ADR = 8'h0; // Address for the start in initialization instructions
//------Logic Operations----------
//
//
// Define the Instruction Pointer
//
// Note: This pointer can start at either the sensor initialization code start
// address or the run-time code start address.
//
always @( SM_INSTR_PTR or
sm_instr_ptr_ld or
sm_instr_ptr_ce or
sm_instr_ptr_sel or
SM_READ_DATA or
CONTROL_JUMP_REG_DCD or
RUNTIME_ADDRESS
)
begin
case({sm_instr_ptr_ld, sm_instr_ptr_ce})
2'b00: sm_instr_ptr_nxt <= SM_INSTR_PTR; // Hold Current Value
2'b01: sm_instr_ptr_nxt <= SM_INSTR_PTR + 1'b1; // Increment to the next address
2'b10:
begin
case({CONTROL_JUMP_REG_DCD, sm_instr_ptr_sel})
2'b00: sm_instr_ptr_nxt <= SM_INIT_INSTR_ADR; // Initialization Code Address
2'b01: sm_instr_ptr_nxt <= RUNTIME_ADDRESS; // Run-time Code Address
2'b10: sm_instr_ptr_nxt <= SM_READ_DATA[7:0]; // Jump Address
2'b11: sm_instr_ptr_nxt <= SM_READ_DATA[7:0]; // Jump Address
endcase
end
2'b11: sm_instr_ptr_nxt <= SM_INSTR_PTR; // Hold Current Value
endcase
end
// Define the registers associated with the Sensor Manager Statemachine
//
always @(posedge CLK_IN or posedge RESET_IN)
begin
if (RESET_IN)
begin
sensor_manager_sm <= SM_IDLE;
SM_INSTR_PTR <= 8'h0;
sm_instr_ptr_ce <= 1'b0;
sm_instr_ptr_ld <= 1'b0;
sm_instr_ptr_sel <= 1'b0;
WB_WE_O <= 1'b0;
WB_STB_O <= 1'b0;
WB_CYC_O <= 1'b0;
SM_READ_SELECT <= 1'b0;
SM_WRITE_SELECT <= 1'b0;
SM_BUSY <= 1'b0;
end
else
begin
sensor_manager_sm <= sensor_manager_sm_nxt;
SM_INSTR_PTR <= sm_instr_ptr_nxt;
sm_instr_ptr_ce <= sm_instr_ptr_ce_nxt;
sm_instr_ptr_ld <= sm_instr_ptr_ld_nxt;
sm_instr_ptr_sel <= sm_instr_ptr_sel_nxt;
WB_WE_O <= wb_we_o_nxt;
WB_STB_O <= wb_stb_o_nxt;
WB_CYC_O <= wb_cyc_o_nxt;
SM_READ_SELECT <= sm_read_select_nxt;
SM_WRITE_SELECT <= sm_write_select_nxt;
SM_BUSY <= sm_busy_nxt;
end
end
// Define the Sensor Manager Statemachine
//
always @( sensor_manager_sm or
SM_CNTL_INIT_SEQ or
SM_CNTL_REG_RUN or
CONTROL_JUMP_REG_DCD or
SAVE_REG_2_MEM or
WB_BUSY_I or
WB_BUSY_POLL_I or
WB_ACK_I
)
begin
case(sensor_manager_sm)
SM_IDLE:
begin
case({SM_CNTL_INIT_SEQ, SM_CNTL_REG_RUN})
2'b00: // No Activity
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
end
2'b01: // Start at the Sensor Run-Time Code
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b1;
sm_instr_ptr_sel_nxt <= 1'b1;
end
2'b10: // No Activity
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
end
2'b11: // Start at the Sensor Initialization Code
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b1;
sm_instr_ptr_sel_nxt <= 1'b0;
end
endcase
sm_instr_ptr_ce_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
SM_INC_PTR:
begin
sensor_manager_sm_nxt <= SM_INST_RD;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b1;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
SM_INST_RD:
begin
sensor_manager_sm_nxt <= SM_REG_WR;
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
SM_REG_WR:
begin
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
case(SM_CNTL_REG_RUN)
1'b0: // A write of "0" to bit "0" of the Command register at address "0" turns off
// the Sensor Manager's Statemachine
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
1'b1: // Sensor Manager Statemachine is not stopped; continue processing
begin
sm_busy_nxt <= 1'b1;
case({WB_BUSY_POLL_I, WB_ACK_I})
2'b00: // Wait for Wish Bone Acknowledge and no need to wait for transfer complete
begin
sensor_manager_sm_nxt <= SM_REG_WR;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
2'b01: // Wish Bone Acknowledge Received and no need to wait for transfer complete
begin
case(SAVE_REG_2_MEM)
1'b0:
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_instr_ptr_ld_nxt <= CONTROL_JUMP_REG_DCD;
sm_instr_ptr_ce_nxt <= ~CONTROL_JUMP_REG_DCD;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
1'b1:
begin
sensor_manager_sm_nxt <= SM_REG_RD;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b1;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
endcase
end
2'b10: // Wait for Wish Bone Acknowledge and will need to wait for transfer complete
begin
sensor_manager_sm_nxt <= SM_REG_WR;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
2'b11: // Acknowledge received but need to wait for transfer complete
begin
sensor_manager_sm_nxt <= SM_WAIT_BUSY_ON;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
endcase
end
SM_REG_RD:
begin
sm_busy_nxt <= 1'b1;
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
case(WB_ACK_I)
1'b0: // Waiting for Wish Bone Acknowledge
begin
sensor_manager_sm_nxt <= SM_REG_RD;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
1'b1: // Got Wish Bone Acknowledge
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_instr_ptr_ld_nxt <= CONTROL_JUMP_REG_DCD;
sm_instr_ptr_ce_nxt <= ~CONTROL_JUMP_REG_DCD;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
SM_WAIT_BUSY_ON:
begin
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
case(WB_BUSY_I)
1'b0: sensor_manager_sm_nxt <= SM_WAIT_BUSY_ON; // Wait for Busy from I/F
1'b1: sensor_manager_sm_nxt <= SM_WAIT_BUSY_OFF; // Got Busy from I/F
endcase
end
SM_WAIT_BUSY_OFF:
begin
sm_busy_nxt <= 1'b1;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
case({SAVE_REG_2_MEM, WB_BUSY_I})
2'b00: // Wishbone transfer complete; no need to write anything to Sensor Manager Memory
//
// Note: Writes to the command register do not enter this state.
// Therefore, there is no need to check for the end of processing.
begin
sensor_manager_sm_nxt <= SM_INC_PTR;
sm_instr_ptr_ce_nxt <= 1'b1;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
2'b01: // Wait for Wishbone transfer to complete
begin
sensor_manager_sm_nxt <= SM_WAIT_BUSY_OFF;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
2'b10: // Wishbone transfer complete; Write resulting register value to Sensor Manager Memory
begin
sensor_manager_sm_nxt <= SM_REG_RD;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b1;
wb_stb_o_nxt <= 1'b1;
wb_cyc_o_nxt <= 1'b1;
end
2'b11: // Wait for Wishbone transfer to complete
begin
sensor_manager_sm_nxt <= SM_WAIT_BUSY_OFF;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
default:
begin
sensor_manager_sm_nxt <= SM_IDLE;
sm_busy_nxt <= 1'b0;
sm_instr_ptr_ld_nxt <= 1'b0;
sm_instr_ptr_ce_nxt <= 1'b0;
sm_instr_ptr_sel_nxt <= 1'b0;
sm_read_select_nxt <= 1'b0;
sm_write_select_nxt <= 1'b0;
wb_we_o_nxt <= 1'b0;
wb_stb_o_nxt <= 1'b0;
wb_cyc_o_nxt <= 1'b0;
end
endcase
end
endmodule

View File

@ -0,0 +1,598 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// 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
//
///////////////////////////////////////////////////////////////////////
// QuickLogic Change History:
//
// Date: February 11, 2014
// Engineer: Anthony Le
// Issue: i2c master generates back to back stop conditions that violate i2c protocol
// Change:
// 1. Move the generation of cmd_ack to one clock earlier in stop_c state
// 2. Change the condition to unset (set to 0) for cmd_ack in stop_d state
//
// synopsys translate_off
// synopsys translate_on
`timescale 1ns / 10ps
`include "i2c_master_defines.v"
module i2c_master_bit_ctrl (
input clk, // system clock
input rst, // synchronous active high reset
input Reset, // 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)
output TP1,
output TP2
);
//
// 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
assign TP1 = cnt[0];
assign TP2 = cnt[1];
// 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 <= #1 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 posedge Reset)
if (Reset) 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 posedge Reset)
if (Reset)
begin
cnt <= #1 16'h0;
clk_en <= #1 1'b1;
end
else if (rst || ~|cnt || !ena || scl_sync)
begin
cnt <= #1 clk_cnt;
clk_en <= #1 1'b1;
end
else if (slave_wait)
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
// capture SDA and SCL
// reduce metastability risk
always @(posedge clk or posedge Reset)
if (Reset)
begin
cSCL <= #1 2'b00;
cSDA <= #1 2'b00;
end
else if (rst)
begin
cSCL <= #1 2'b00;
cSDA <= #1 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 posedge Reset)
if (Reset ) filter_cnt <= 14'h0;
else if (rst || !ena ) filter_cnt <= 14'h0;
else if (~|filter_cnt) filter_cnt <= clk_cnt >> 2; //16x I2C bus frequency
else filter_cnt <= filter_cnt -1;
always @(posedge clk or posedge Reset)
if (Reset)
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 posedge Reset)
if (Reset)
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 &fSCL[2:1] | &fSCL[1:0] | (fSCL[2] & fSCL[0]);
sSDA <= #1 &fSDA[2:1] | &fSDA[1:0] | (fSDA[2] & fSDA[0]);
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
reg sta_condition;
reg sto_condition;
always @(posedge clk or posedge Reset)
if (Reset)
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 posedge Reset)
if (Reset) 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 posedge Reset)
if (Reset)
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 posedge Reset)
if (Reset)
al <= #1 1'b0;
else if (rst)
al <= #1 1'b0;
else
al <= 0;
// 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 [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 posedge Reset)
if (Reset)
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
if(clk_cnt == 0) cmd_ack <= #1 1'b1;
end
start_e:
begin
c_state <= #1 idle;
if(clk_cnt == 0) cmd_ack <= #1 1'b0;
else 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;
cmd_ack <= #1 1'b1;
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'b0;
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
if (clk_cnt == 0) cmd_ack <= #1 1'b1;
end
rd_d:
begin
c_state <= #1 idle;
if (clk_cnt == 0) cmd_ack <= #1 0;
else cmd_ack <= #1 1;
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'b0; // don't check SDA output yet
// allow some time for SDA and SCL to settle
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
if (clk_cnt == 0) cmd_ack <= #1 1'b1;
end
wr_d:
begin
c_state <= #1 idle;
if (clk_cnt == 0) cmd_ack <= #1 0;
else cmd_ack <= #1 1;
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

View File

@ -0,0 +1,386 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// 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.
//
///////////////////////////////////////////////////////////////////////
// QuickLogic Change History:
//
// Date: February 12, 2014
// Engineer: Anthony Le
// Issue: i2c SDA to SCL timing violation
// Change:
// 1. Generate LD during IDLE to speed up the input data to SR
//
// synopsys translate_off
// synopsys translate_on
`timescale 1ns / 10ps
`include "i2c_master_defines.v"
module i2c_master_byte_ctrl (
clk, rst, Reset, 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, DrivingI2cBusOut,
TP1,
TP2 );
//
// inputs & outputs
//
input clk; // master clock
input rst; // synchronous active high reset
input Reset; // asynchronous active high 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;
// control signals
output DrivingI2cBusOut;
// test signals
output TP1;
output TP2;
//
// Variable declarations
//
// statemachine
parameter [5:0] ST_IDLE = 6'b00_0000;
parameter [5:0] ST_START = 6'b00_0001;
parameter [5:0] ST_READ = 6'b00_0010;
parameter [5:0] ST_WRITE = 6'b00_0100;
parameter [5:0] ST_ACK = 6'b00_1000;
parameter [5:0] ST_STOP = 6'b01_0000;
parameter [5:0] ST_DLWR = 6'b10_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
//
assign DrivingI2cBusOut = (core_cmd != `I2C_CMD_READ);
// hookup bit_controller
i2c_master_bit_ctrl bit_controller (
.clk ( clk ),
.rst ( rst ),
.Reset ( Reset ),
.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 ),
.TP1 ( TP1 ),
.TP2 ( TP2 )
);
// generate go-signal
assign go = (read | write | stop) & ~cmd_ack;
// assign dout output to shift-register
assign dout = sr;
//
// state machine
//
reg [5:0] c_state; // synopsys enum_state
// generate shift register
// always @(posedge clk or posedge Reset)
// if (Reset)
// sr <= #1 8'h0;
// else if (rst)
// sr <= #1 8'h0;
// else if (ld)
// sr <= #1 din;
// else if (shift && clk_cnt !=0)
// sr <= #1 {sr[6:0], core_rxd};
// else if (shift && c_state != ST_WRITE)
// sr <= #1 {sr[6:0], core_rxd};
// generate counter
always @(posedge clk or posedge Reset)
if (Reset)
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);
always @(posedge clk or posedge Reset)
if (Reset)
begin
sr <= #1 8'h0;
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
sr <= #1 8'h0;
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
if (ld)
sr <= #1 din;
else if (shift && clk_cnt !=0)
sr <= #1 {sr[6:0], core_rxd};
else if (shift && c_state != ST_WRITE)
sr <= #1 {sr[6:0], core_rxd};
// 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_DLWR;
core_cmd <= #1 `I2C_CMD_NOP;
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_DLWR:
begin
c_state <= #1 ST_WRITE;
core_cmd <= #1 `I2C_CMD_WRITE;
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;
if (clk_cnt == 0) sr <= #1 {sr[6:0], core_rxd};
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;
//sr <= #1 {sr[6:0], core_rxd};
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;
if (clk_cnt == 0) shift <= #1 1;
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

View File

@ -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

View File

@ -0,0 +1,323 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// 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. ////
//// ////
/////////////////////////////////////////////////////////////////////
// 1.12 2012-12-17 Tim Saxe
// Changed wb_ack_o to be derived from in internal version
// wb_ack_i
// 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
// synopsys translate_on
`timescale 1ns / 10ps
`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, tip_o, DrivingI2cBusOut,
TP1,
TP2);
// parameters
//
// 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
inout wb_ack_o; // bus cycle acknowledge output
output wb_inta_o; // interrupt request signal output
// control signals
output tip_o; // transfer in progress
output DrivingI2cBusOut; // master is driving i2c bus
reg [7:0] wb_dat_o;
reg wb_ack_i;
wire wb_ack_o = wb_ack_i;
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)
// test signal
output TP1;
output TP2;
//
// 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
//
assign tip_o = tip;
// generate internal reset
wire rst_i = arst_i;
// generate wishbone signals
wire wb_wacc = wb_we_i & wb_ack_i;
// generate acknowledge output signal
always @(posedge wb_clk_i)
wb_ack_i <= #1 wb_cyc_i & wb_stb_i & ~wb_ack_i; // 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 <= #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 posedge rst_i)
if (rst_i)
begin
// prer <= #1 16'hffff;
// ctr <= #1 8'h0;
prer <= #1 16'h0000;
ctr <= #1 8'h80;
txr <= #1 8'h0;
end
else if (wb_rst_i)
begin
// prer <= #1 16'hffff;
// ctr <= #1 8'h0;
prer <= #1 16'h0000;
ctr <= #1 8'h80;
txr <= #1 8'h0;
end
else
if (wb_wacc)
case (wb_adr_i) // synopsys 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 posedge 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 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 ),
.Reset ( 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 ),
.DrivingI2cBusOut (DrivingI2cBusOut),
.TP1 ( TP1 ),
.TP2 ( TP2 )
);
// status register block + interrupt request signal
always @(posedge wb_clk_i or posedge 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 posedge 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

14847
BENCHMARK/iir/iir_yosys.blif Normal file

File diff suppressed because it is too large Load Diff

238
BENCHMARK/iir/rtl/iir.v Normal file
View File

@ -0,0 +1,238 @@
module iir (clk, reset, start, din, params, dout, ready,iir_start,iir_done);
input clk, reset, start;
input [7:0] din;
input [15:0] params;
output [7:0] dout;
reg [7:0] dout;
output ready;
reg ready;
reg temp_ready;
reg [6:0] finite_counter;
wire count0;
input iir_start;
output iir_done;
wire iir_done;
reg del_count0;
reg [15:0] a1, a2, b0, b1, b2, yk1, yk2;
reg [7:0] uk, uk1, uk2 ;
reg [28:0] ysum ;
reg [26:0] yk ;
reg [22:0] utmp;
reg [3:0] wait_counter ;
// temporary variable
wire [31:0] yo1, yo2;
//wire [23:0] b0t, b1t, b2t;
wire [22:0] b0t, b1t, b2t;
wire [22:0] b0tpaj, b1tpaj, b2tpaj;
reg [3:0] obf_state, obf_next_state ;
reg [7:0] temp_uk, temp_uk1, temp_uk2 ;
reg [15:0] temp_a1, temp_a2, temp_b0, temp_b1, temp_b2, temp_yk1, temp_yk2;
reg [28:0] temp_ysum ;
reg [26:0] temp_yk ;
reg [22:0] temp_utmp;
reg [7:0] temp_dout;
reg [3:0] temp_wait_counter ;
parameter
idle = 4'b0001 ,
load_a2 = 4'b0010 ,
load_b0 = 4'b0011 ,
load_b1 = 4'b0100 ,
load_b2 = 4'b0101 ,
wait4_start = 4'b0110 ,
latch_din = 4'b0111 ,
compute_a = 4'b1000 ,
compute_b = 4'b1001 ,
compute_yk = 4'b1010 ,
wait4_count = 4'b1011 ,
latch_dout = 4'b1100 ;
always @(obf_state or start or din or wait_counter or iir_start or count0)
begin
case (obf_state )
idle :
begin
if (iir_start)
obf_next_state = load_a2 ;
else
obf_next_state = idle;
temp_a1 = params ;
end
load_a2 :
begin
obf_next_state = load_b0 ;
temp_a2 = params ;
end
load_b0 :
begin
obf_next_state = load_b1 ;
temp_b0 = params ;
end
load_b1 :
begin
obf_next_state = load_b2 ;
temp_b1 = params ;
end
load_b2 :
begin
obf_next_state = wait4_start ;
temp_b2 = params ;
end
wait4_start :
begin
if (start)
begin
obf_next_state = latch_din ;
temp_uk = din ;
end
else
begin
obf_next_state = wait4_start ;
temp_uk = uk;
end
temp_ready = wait4_start;
end
latch_din :
begin
obf_next_state = compute_a ;
end
compute_a :
begin
obf_next_state = compute_b ;
temp_ysum = yo1[31:3] + yo2[31:3];
end
compute_b :
begin
obf_next_state = compute_yk ;
// temp_utmp = b0t[23:0] + b1t[23:0] + b2t[23:0];
temp_utmp = b0t + b1t + b2t;
end
compute_yk :
begin
obf_next_state = wait4_count ;
temp_uk1 = uk ;
temp_uk2 = uk1 ;
temp_yk = ysum[26:0] + {utmp[22], utmp[22], utmp[22], utmp[22], utmp};
temp_wait_counter = 4 ;
end
wait4_count :
begin
if (wait_counter==0 )
begin
obf_next_state = latch_dout ;
temp_dout = yk[26:19];
temp_yk1 = yk[26:11] ;
temp_yk2 = yk1 ;
end
else
begin
obf_next_state = wait4_count ;
temp_dout = dout;
temp_yk1 = yk1;
//temp_yk2 = yk2;
end
temp_wait_counter = wait_counter - 1;
end
latch_dout :
if (count0)
obf_next_state = idle;
else
obf_next_state = wait4_start ;
endcase
end
//assign yo1 = mul_tc_16_16(yk1, a1, clk);
assign yo1 = yk1 * a1;
//assign yo2 = mul_tc_16_16(yk2, a2, clk);
assign yo2 = yk2*a2;
//assign b0t = mul_tc_8_16(uk, b0, clk);
//assign b1t = mul_tc_8_16(uk1, b1, clk);
//assign b2t = mul_tc_8_16(uk2, b2, clk);
assign b0t = uk*b0;
assign b1t = uk1*b1;
assign b2t = uk2*b2;
// paj added to solve unused high order bit
assign b0tpaj = b0t;
assign b1tpaj = b1t;
assign b2tpaj = b2t;
// A COEFFICENTS
always @(posedge clk or posedge reset) begin
if (reset ) begin
uk <= 0 ;
uk1 <= 0 ;
uk2 <= 0 ;
yk1 <= 0 ;
yk2 <= 0 ;
yk <= 0 ;
ysum <= 0 ;
utmp <= 0 ;
a1 <= 0 ;
a2 <= 0 ;
b0 <= 0 ;
b1 <= 0 ;
b2 <= 0 ;
dout <= 0 ;
obf_state <= idle ;
ready <= 0;
end
else begin
obf_state <= obf_next_state ;
uk1 <= temp_uk1;
uk2 <= temp_uk2;
yk <= temp_yk;
uk <= temp_uk ;
a1 <= temp_a1 ;
a2 <= temp_a2 ;
b0 <= temp_b0 ;
b1 <= temp_b1 ;
b2 <= temp_b2 ;
ysum <= temp_ysum;
utmp <= temp_utmp;
dout <= temp_dout;
yk1 <= temp_yk1;
yk2 <= temp_yk2;
ready <= temp_ready;
end
end
// wait counter, count 4 clock after sum is calculated, to
// time outputs are ready, and filter is ready to accept next
// input
always @(posedge clk or posedge reset ) begin
if (reset )
wait_counter <= 0 ;
else begin
wait_counter <= temp_wait_counter ;
end
end
always @(posedge clk) begin
if (reset)
finite_counter<=100;
else
if (iir_start)
finite_counter<=finite_counter -1;
else
finite_counter<=finite_counter;
end
assign count0=finite_counter==7'b0;
always @(posedge clk) begin
del_count0 <= count0;
end
assign iir_done = (count0 && ~del_count0);
endmodule

22
BENCHMARK/io_reg/io_reg.v Normal file
View File

@ -0,0 +1,22 @@
module io_reg(clk, in, out);
input clk;
input in;
output out;
reg out;
//reg temp;
always @(posedge clk)
begin
out <= in;
end
/*always @(posedge clk)
begin
out <= temp ;
end*/
endmodule

View File

@ -0,0 +1,21 @@
module io_reg_tb;
reg clk_gen, in_gen;
wire out;
io_reg inst(.clk(clk_gen), .in(in_gen), .out(out));
initial begin
#0 in_gen = 1'b1; clk_gen = 1'b0;
#100 in_gen = 1'b0;
end
always begin
#10 clk_gen = ~clk_gen;
end
initial begin
#5000 $stop;
end
endmodule

View File

@ -0,0 +1,106 @@
module demux_1x512 (in,sel,out);
input in;
input [8:0] sel;
output [511:0] out;
wire [1:0] out_w;
demux_1x2 d512_0(.in(in),.sel(sel[8]),.out(out_w[1:0]));
demux_1x256 d512_1(.in(out_w[0]),.sel(sel[7:0]),.out(out[255:0]));
demux_1x256 d512_2(.in(out_w[1]),.sel(sel[7:0]),.out(out[511:256]));
endmodule
module demux_1x256 (in,sel,out);
input in;
input [7:0] sel;
output [255:0] out;
wire [1:0] out_w;
demux_1x2 d256_0(.in(in),.sel(sel[7]),.out(out_w[1:0]));
demux_1x128 d256_1(.in(out_w[0]),.sel(sel[6:0]),.out(out[127:0]));
demux_1x128 d256_2(.in(out_w[1]),.sel(sel[6:0]),.out(out[255:128]));
endmodule
module demux_1x128 (in,sel,out);
input in;
input [6:0] sel;
output [127:0] out;
wire [1:0] out_w;
demux_1x2 d128_0(.in(in),.sel(sel[6]),.out(out_w[1:0]));
demux_1x64 d128_1(.in(out_w[0]),.sel(sel[5:0]),.out(out[63:0]));
demux_1x64 d128_2(.in(out_w[1]),.sel(sel[5:0]),.out(out[127:64]));
endmodule
module demux_1x64 (in,sel,out);
input in;
input [5:0] sel;
output [63:0] out;
wire [1:0] out_w;
demux_1x2 d64_0(.in(in),.sel(sel[5]),.out(out_w[1:0]));
demux_1x32 d64_1(.in(out_w[0]),.sel(sel[4:0]),.out(out[31:0]));
demux_1x32 d64_2(.in(out_w[1]),.sel(sel[4:0]),.out(out[63:32]));
endmodule
module demux_1x32 (in,sel,out);
input in;
input [4:0] sel;
output [31:0] out;
wire [1:0] out_w;
demux_1x2 d32_0(.in(in),.sel(sel[4]),.out(out_w[1:0]));
demux_1x16 d32_1(.in(out_w[0]),.sel(sel[3:0]),.out(out[15:0]));
demux_1x16 d32_2(.in(out_w[1]),.sel(sel[3:0]),.out(out[31:16]));
endmodule
module demux_1x16 (in,sel,out);
input in;
input [3:0] sel;
output [15:0] out;
wire [1:0] out_w;
demux_1x2 d16_0(.in(in),.sel(sel[3]),.out(out_w[1:0]));
demux_1x8 d16_1(.in(out_w[0]),.sel(sel[2:0]),.out(out[7:0]));
demux_1x8 d16_2(.in(out_w[1]),.sel(sel[2:0]),.out(out[15:8]));
endmodule
module demux_1x8 (in,sel,out);
input in;
input [2:0] sel;
output [7:0] out;
wire [1:0] out_w;
demux_1x2 d8_0(.in(in),.sel(sel[2]),.out(out_w[1:0]));
demux_1x4 d8_1(.in(out_w[0]),.sel(sel[1:0]),.out(out[3:0]));
demux_1x4 d8_2(.in(out_w[1]),.sel(sel[1:0]),.out(out[7:4]));
endmodule
module demux_1x4 (in,sel,out);
input in;
input [1:0] sel;
output [3:0] out;
wire [1:0]out_w;
demux_1x2 d4_0(.in(in),.sel(sel[1]),.out(out_w));
demux_1x2 d4_1(.in(out_w[0]),.sel(sel[0]),.out(out[1:0]));
demux_1x2 d4_2(.in(out_w[1]),.sel(sel[0]),.out(out[3:2]));
endmodule
module demux_1x2 (in,sel,out);
input in,sel;
output [1:0] out;
assign out[0] = (sel==0) ? in :0;
assign out[1] = (sel==1) ? in :0;
endmodule

View File

@ -0,0 +1,11 @@
module io_tc1 (mux_in, demux_out,mux_sel, demux_sel);
input [0:511] mux_in;
input [8:0]mux_sel;
input [8:0]demux_sel;
output [511:0]demux_out;
mux_512x1 mux0 (.in(mux_in),.sel(mux_sel),.out(mux_out));
demux_1x512 demux0 (.in(mux_out),.sel(demux_sel),.out(demux_out));
endmodule

104
BENCHMARK/io_tc1/rtl/mux.v Normal file
View File

@ -0,0 +1,104 @@
module mux_512x1 (in,sel,out);
input [511:0] in;
input [8:0]sel;
output out;
wire out0_w, out1_w;
mux_256x1 m512_0(.in(in[255:0]),.sel(sel[7:0]),.out(out0_w));
mux_256x1 m512_1(.in(in[511:256]),.sel(sel[7:0]),.out(out1_w));
mux_2x1 m512_2(.a(out0_w),.b(out1_w),.sel(sel[8]),.out(out));
endmodule
module mux_256x1 (in,sel,out);
input [255:0] in;
input [7:0]sel;
output out;
wire out0_w, out1_w;
mux_128x1 m256_0(.in(in[127:0]),.sel(sel[6:0]),.out(out0_w));
mux_128x1 m256_1(.in(in[255:128]),.sel(sel[6:0]),.out(out1_w));
mux_2x1 m256_2(.a(out0_w),.b(out1_w),.sel(sel[7]),.out(out));
endmodule
module mux_128x1 (in,sel,out);
input [127:0] in;
input [6:0]sel;
output out;
wire out0_w, out1_w;
mux_64x1 m128_0(.in(in[63:0]),.sel(sel[5:0]),.out(out0_w));
mux_64x1 m128_1(.in(in[127:64]),.sel(sel[5:0]),.out(out1_w));
mux_2x1 m128_2(.a(out0_w),.b(out1_w),.sel(sel[6]),.out(out));
endmodule
module mux_64x1 (in,sel,out);
input [63:0] in;
input [5:0]sel;
output out;
wire out0_w, out1_w;
mux_32x1 m64_0(.in(in[31:0]),.sel(sel[4:0]),.out(out0_w));
mux_32x1 m64_1(.in(in[63:32]),.sel(sel[4:0]),.out(out1_w));
mux_2x1 m64_2(.a(out0_w),.b(out1_w),.sel(sel[5]),.out(out));
endmodule
module mux_32x1 (in,sel,out);
input [31:0] in;
input [4:0]sel;
output out;
wire out0_w, out1_w;
mux_16x1 m32_0(.in(in[15:0]),.sel(sel[3:0]),.out(out0_w));
mux_16x1 m32_1(.in(in[31:16]),.sel(sel[3:0]),.out(out1_w));
mux_2x1 m32_2(.a(out0_w),.b(out1_w),.sel(sel[4]),.out(out));
endmodule
module mux_16x1 (in,sel,out);
input [15:0] in;
input [3:0]sel;
output out;
wire out0_w, out1_w;
mux_8x1 m16_0(.in(in[7:0]),.sel(sel[2:0]),.out(out0_w));
mux_8x1 m16_1(.in(in[15:8]),.sel(sel[2:0]),.out(out1_w));
mux_2x1 m16_2(.a(out0_w),.b(out1_w),.sel(sel[3]),.out(out));
endmodule
module mux_8x1 (in,sel,out);
input [7:0] in;
input [2:0]sel;
output out;
wire out0_w, out1_w;
mux_4x1 m8_0(.in(in[3:0]),.sel(sel[1:0]),.out(out0_w));
mux_4x1 m8_1(.in(in[7:4]),.sel(sel[1:0]),.out(out1_w));
mux_2x1 m8_2(.a(out0_w),.b(out1_w),.sel(sel[2]),.out(out));
endmodule
module mux_4x1 (in,sel,out);
input [3:0] in;
input [1:0]sel;
output out;
wire out0_w, out1_w;
mux_2x1 m4_0(.a(in[0]),.b(in[1]),.sel(sel[0]),.out(out0_w));
mux_2x1 m4_1(.a(in[2]),.b(in[3]),.sel(sel[0]),.out(out1_w));
mux_2x1 m4_2(.a(out0_w),.b(out1_w),.sel(sel[1]),.out(out));
endmodule
module mux_2x1 (a,b,sel,out);
input a,b;
input sel;
output out;
assign out = sel ? b : a;
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,157 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Non-restoring signed by unsigned divider ////
//// Uses the non-restoring unsigned by unsigned divider ////
//// ////
//// 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: div_su.v,v 1.3 2002-10-31 12:52:54 rherveille Exp $
//
// $Date: 2002-10-31 12:52:54 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:07:03 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module div_su(clk, ena, z, d, q, s, div0, ovf);
//
// parameters
//
parameter z_width = 16;
parameter d_width = z_width /2;
//
// inputs & outputs
//
input clk; // system clock
input ena; // clock enable
input [z_width-1:0] z; // divident
input [d_width-1:0] d; // divisor
output [d_width :0] q; // quotient
output [d_width-1:0] s; // remainder
output div0;
output ovf;
reg [d_width :0] q;
reg [d_width-1:0] s;
reg div0;
reg ovf;
//
// variables
//
reg [z_width -1:0] iz;
reg [d_width -1:0] id;
reg [d_width +1:0] spipe;
wire [d_width -1:0] iq, is;
wire idiv0, iovf;
//
// module body
//
// delay d
always @(posedge clk)
if (ena)
id <= #1 d;
// check z, take abs value
always @(posedge clk)
if (ena)
if (z[z_width-1])
iz <= #1 ~z +1'h1;
else
iz <= #1 z;
// generate spipe (sign bit pipe)
integer n;
always @(posedge clk)
if(ena)
begin
spipe[0] <= #1 z[z_width-1];
for(n=1; n <= d_width+1; n=n+1)
spipe[n] <= #1 spipe[n-1];
end
// hookup non-restoring divider
div_uu #(z_width, d_width)
divider (
.clk(clk),
.ena(ena),
.z(iz),
.d(id),
.q(iq),
.s(is),
.div0(idiv0),
.ovf(iovf)
);
// correct divider results if 'd' was negative
always @(posedge clk)
if(ena)
if(spipe[d_width+1])
begin
q <= #1 (~iq) + 1'h1;
s <= #1 (~is) + 1'h1;
end
else
begin
q <= #1 {1'b0, iq};
s <= #1 {1'b0, is};
end
// delay flags same as results
always @(posedge clk)
if(ena)
begin
div0 <= #1 idiv0;
ovf <= #1 iovf;
end
endmodule

View File

@ -0,0 +1,202 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Non-restoring unsinged divider ////
//// ////
//// 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: div_uu.v,v 1.3 2002-10-31 12:52:55 rherveille Exp $
//
// $Date: 2002-10-31 12:52:55 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:07:03 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module div_uu(clk, ena, z, d, q, s, div0, ovf);
//
// parameters
//
parameter z_width = 16;
parameter d_width = z_width /2;
//
// inputs & outputs
//
input clk; // system clock
input ena; // clock enable
input [z_width -1:0] z; // divident
input [d_width -1:0] d; // divisor
output [d_width -1:0] q; // quotient
reg [d_width-1:0] q;
output [d_width -1:0] s; // remainder
reg [d_width-1:0] s;
output div0;
reg div0;
output ovf;
reg ovf;
//
// functions
//
function [z_width:0] gen_s;
input [z_width:0] si;
input [z_width:0] di;
begin
if(si[z_width])
gen_s = {si[z_width-1:0], 1'b0} + di;
else
gen_s = {si[z_width-1:0], 1'b0} - di;
end
endfunction
function [d_width-1:0] gen_q;
input [d_width-1:0] qi;
input [z_width:0] si;
begin
gen_q = {qi[d_width-2:0], ~si[z_width]};
end
endfunction
function [d_width-1:0] assign_s;
input [z_width:0] si;
input [z_width:0] di;
reg [z_width:0] tmp;
begin
if(si[z_width])
tmp = si + di;
else
tmp = si;
assign_s = tmp[z_width-1:z_width-4];
end
endfunction
//
// variables
//
reg [d_width-1:0] q_pipe [d_width-1:0];
reg [z_width:0] s_pipe [d_width:0];
reg [z_width:0] d_pipe [d_width:0];
reg [d_width:0] div0_pipe, ovf_pipe;
//
// perform parameter checks
//
// synopsys translate_off
initial
begin
if(d_width !== z_width / 2)
$display("div.v parameter error (d_width != z_width/2).");
end
// synopsys translate_on
integer n0, n1, n2, n3;
// generate divisor (d) pipe
always @(d)
d_pipe[0] <= {1'b0, d, {(z_width-d_width){1'b0}} };
always @(posedge clk)
if(ena)
for(n0=1; n0 <= d_width; n0=n0+1)
d_pipe[n0] <= #1 d_pipe[n0-1];
// generate internal remainder pipe
always @(z)
s_pipe[0] <= z;
always @(posedge clk)
if(ena)
for(n1=1; n1 <= d_width; n1=n1+1)
s_pipe[n1] <= #1 gen_s(s_pipe[n1-1], d_pipe[n1-1]);
// generate quotient pipe
always @(posedge clk)
q_pipe[0] <= #1 0;
always @(posedge clk)
if(ena)
for(n2=1; n2 < d_width; n2=n2+1)
q_pipe[n2] <= #1 gen_q(q_pipe[n2-1], s_pipe[n2]);
// flags (divide_by_zero, overflow)
always @(z or d)
begin
ovf_pipe[0] <= !(z[z_width-1:d_width] < d);
div0_pipe[0] <= ~|d;
end
always @(posedge clk)
if(ena)
for(n3=1; n3 <= d_width; n3=n3+1)
begin
ovf_pipe[n3] <= #1 ovf_pipe[n3-1];
div0_pipe[n3] <= #1 div0_pipe[n3-1];
end
// assign outputs
always @(posedge clk)
if(ena)
ovf <= #1 ovf_pipe[d_width];
always @(posedge clk)
if(ena)
div0 <= #1 div0_pipe[d_width];
always @(posedge clk)
if(ena)
q <= #1 gen_q(q_pipe[d_width-1], s_pipe[d_width]);
always @(posedge clk)
if(ena)
s <= #1 assign_s(s_pipe[d_width], d_pipe[d_width]);
endmodule

View File

@ -0,0 +1,149 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// JPEG Quantization & Rounding Core ////
//// ////
//// 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: jpeg_qnr.v,v 1.3 2002-10-31 12:52:55 rherveille Exp $
//
// $Date: 2002-10-31 12:52:55 $
// $Revision: 1.3 $
// $Author: rherveille $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/10/23 09:07:03 rherveille
// Improved many files.
// Fixed some bugs in Run-Length-Encoder.
// Removed dependency on ud_cnt and ro_cnt.
// Started (Motion)JPEG hardware encoder project.
//
//synopsys translate_off
`include "timescale.v"
//synopsys translate_on
module jpeg_qnr(clk, ena, rst, dstrb, din, qnt_val, qnt_cnt, dout, douten);
//
// parameters
//
parameter d_width = 12;
parameter z_width = 2 * d_width;
//
// inputs & outputs
//
input clk; // system clock
input ena; // clock enable
input rst; // asynchronous active low reset
input dstrb; // present dstrb 1clk cycle before din
input [d_width-1:0] din; // data input
input [ 7:0] qnt_val; // quantization value
output [ 5:0] qnt_cnt; // sample number (get quantization value qnt_cnt)
output [10:0] dout; // data output
output douten;
//
// variables
//
wire [z_width-1:0] iz; // intermediate divident value
wire [d_width-1:0] id; // intermediate dividor value
wire [d_width :0] iq; // intermediate result divider
reg [d_width :0] rq; // rounded q-value
reg [d_width+3:0] dep;// data enable pipeline
// generate sample counter
reg [5:0] qnt_cnt;
wire dcnt = &qnt_cnt;
always @(posedge clk or negedge rst)
if (~rst)
qnt_cnt <= #1 6'h0;
else if (dstrb)
qnt_cnt <= #1 6'h0;
else if (ena)
qnt_cnt <= #1 qnt_cnt + 6'h1;
// generate intermediate dividor/divident values
assign id = { {(d_width - 8){1'b0}}, qnt_val};
assign iz = { {(z_width - d_width){din[d_width-1]}}, din};
// hookup division unit
div_su #(z_width)
divider (
.clk(clk),
.ena(ena),
.z(iz),
.d(id),
.q(iq),
.s(),
.div0(),
.ovf()
);
// round result to the nearest integer
always @(posedge clk)
if (ena)
if (iq[0])
if (iq[d_width])
rq <= #1 iq - 1'h1;
else
rq <= #1 iq + 1'h1;
else
rq <= #1 iq;
// assign dout signal
assign dout = rq[d_width -1: d_width-11];
// generate data-out enable signal
// This is a pipeline, data is not dependant on sample-count
integer n;
always @(posedge clk or negedge rst)
if (!rst)
dep <= #1 0;
else if(ena)
begin
dep[0] <= #1 dstrb;
for (n=1; n <= d_width +3; n = n +1)
dep[n] <= #1 dep[n-1];
end
assign douten = dep[d_width +3];
endmodule

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,110 @@
//////////////////////////////////////////////////////////////////////
// Created by SmartDesign Tue Jan 16 17:22:21 2018
// Version: v11.8 11.8.0.26
//////////////////////////////////////////////////////////////////////
`timescale 1ns / 100ps
// TOP_multi_enc_decx2x4
module multi_enc_decx2x4(
// Inputs
clock,
datain,
datain1,
datain1_0,
datain_0,
reset,
// Outputs
dataout,
dataout1,
dataout1_0,
dataout_0
);
//--------------------------------------------------------------------
// Input
//--------------------------------------------------------------------
input clock;
input [127:0] datain;
input [127:0] datain1;
input [127:0] datain1_0;
input [127:0] datain_0;
input reset;
//--------------------------------------------------------------------
// Output
//--------------------------------------------------------------------
output [127:0] dataout;
output [127:0] dataout1;
output [127:0] dataout1_0;
output [127:0] dataout_0;
//--------------------------------------------------------------------
// Nets
//--------------------------------------------------------------------
wire clock;
wire [127:0] datain;
wire [127:0] datain1;
wire [127:0] datain1_0;
wire [127:0] datain_0;
wire [127:0] dataout_net_0;
wire [127:0] dataout1_net_0;
wire [127:0] dataout1_0_net_0;
wire [127:0] dataout_0_net_0;
wire reset;
wire [127:0] top_0_dataout;
wire [127:0] top_1_dataout1;
wire [127:0] dataout_net_1;
wire [127:0] dataout1_net_1;
wire [127:0] dataout1_0_net_1;
wire [127:0] dataout_0_net_1;
//--------------------------------------------------------------------
// Top level output port assignments
//--------------------------------------------------------------------
assign dataout_net_1 = dataout_net_0;
assign dataout[127:0] = dataout_net_1;
assign dataout1_net_1 = dataout1_net_0;
assign dataout1[127:0] = dataout1_net_1;
assign dataout1_0_net_1 = dataout1_0_net_0;
assign dataout1_0[127:0] = dataout1_0_net_1;
assign dataout_0_net_1 = dataout_0_net_0;
assign dataout_0[127:0] = dataout_0_net_1;
//--------------------------------------------------------------------
// Component instances
//--------------------------------------------------------------------
//--------top
top top_0(
// Inputs
.clock ( clock ),
.reset ( reset ),
.datain ( datain ),
.datain1 ( datain1 ),
// Outputs
.dataout ( top_0_dataout ),
.dataout1 ( dataout1_0_net_0 )
);
//--------top
top top_1(
// Inputs
.clock ( clock ),
.reset ( reset ),
.datain ( datain_0 ),
.datain1 ( datain1_0 ),
// Outputs
.dataout ( dataout_0_net_0 ),
.dataout1 ( top_1_dataout1 )
);
//--------top
top top_2(
// Inputs
.clock ( clock ),
.reset ( reset ),
.datain ( top_0_dataout ),
.datain1 ( top_1_dataout1 ),
// Outputs
.dataout ( dataout_net_0 ),
.dataout1 ( dataout1_net_0 )
);
endmodule

View File

@ -0,0 +1,147 @@
module decoder128(datain,dataout);
input [6:0] datain;
output [127:0] dataout;
reg [127:0] dataout;
always @(datain)
begin
case (datain)
7'b0000000: dataout <= 128'h00000000000000000000000000000001;
7'b0000001: dataout <= 128'h00000000000000000000000000000002;
7'b0000010: dataout <= 128'h00000000000000000000000000000004;
7'b0000011: dataout <= 128'h00000000000000000000000000000008;
7'b0000100: dataout <= 128'h00000000000000000000000000000010;
7'b0000101: dataout <= 128'h00000000000000000000000000000020;
7'b0000110: dataout <= 128'h00000000000000000000000000000040;
7'b0000111: dataout <= 128'h00000000000000000000000000000080;
7'b0001000: dataout <= 128'h00000000000000000000000000000100;
7'b0001001: dataout <= 128'h00000000000000000000000000000200;
7'b0001010: dataout <= 128'h00000000000000000000000000000400;
7'b0001011: dataout <= 128'h00000000000000000000000000000800;
7'b0001100: dataout <= 128'h00000000000000000000000000001000;
7'b0001101: dataout <= 128'h00000000000000000000000000002000;
7'b0001110: dataout <= 128'h00000000000000000000000000004000;
7'b0001111: dataout <= 128'h00000000000000000000000000008000;
7'b0010000: dataout <= 128'h00000000000000000000000000010000;
7'b0010001: dataout <= 128'h00000000000000000000000000020000;
7'b0010010: dataout <= 128'h00000000000000000000000000040000;
7'b0010011: dataout <= 128'h00000000000000000000000000080000;
7'b0010100: dataout <= 128'h00000000000000000000000000100000;
7'b0010101: dataout <= 128'h00000000000000000000000000200000;
7'b0010110: dataout <= 128'h00000000000000000000000000400000;
7'b0010111: dataout <= 128'h00000000000000000000000000800000;
7'b0011000: dataout <= 128'h00000000000000000000000001000000;
7'b0011001: dataout <= 128'h00000000000000000000000002000000;
7'b0011010: dataout <= 128'h00000000000000000000000004000000;
7'b0011011: dataout <= 128'h00000000000000000000000008000000;
7'b0011100: dataout <= 128'h00000000000000000000000010000000;
7'b0011101: dataout <= 128'h00000000000000000000000020000000;
7'b0011110: dataout <= 128'h00000000000000000000000040000000;
7'b0011111: dataout <= 128'h00000000000000000000000080000000;
7'b0100000: dataout <= 128'h00000000000000000000000100000000;
7'b0100001: dataout <= 128'h00000000000000000000000200000000;
7'b0100010: dataout <= 128'h00000000000000000000000400000000;
7'b0100011: dataout <= 128'h00000000000000000000000800000000;
7'b0100100: dataout <= 128'h00000000000000000000001000000000;
7'b0100101: dataout <= 128'h00000000000000000000002000000000;
7'b0100110: dataout <= 128'h00000000000000000000004000000000;
7'b0100111: dataout <= 128'h00000000000000000000008000000000;
7'b0101000: dataout <= 128'h00000000000000000000010000000000;
7'b0101001: dataout <= 128'h00000000000000000000020000000000;
7'b0101010: dataout <= 128'h00000000000000000000040000000000;
7'b0101011: dataout <= 128'h00000000000000000000080000000000;
7'b0101100: dataout <= 128'h00000000000000000000100000000000;
7'b0101101: dataout <= 128'h00000000000000000000200000000000;
7'b0101110: dataout <= 128'h00000000000000000000400000000000;
7'b0101111: dataout <= 128'h00000000000000000000800000000000;
7'b0110000: dataout <= 128'h00000000000000000001000000000000;
7'b0110001: dataout <= 128'h00000000000000000002000000000000;
7'b0110010: dataout <= 128'h00000000000000000004000000000000;
7'b0110011: dataout <= 128'h00000000000000000008000000000000;
7'b0110100: dataout <= 128'h00000000000000000010000000000000;
7'b0110101: dataout <= 128'h00000000000000000020000000000000;
7'b0110110: dataout <= 128'h00000000000000000040000000000000;
7'b0110111: dataout <= 128'h00000000000000000080000000000000;
7'b0111000: dataout <= 128'h00000000000000000100000000000000;
7'b0111001: dataout <= 128'h00000000000000000200000000000000;
7'b0111010: dataout <= 128'h00000000000000000400000000000000;
7'b0111011: dataout <= 128'h00000000000000000800000000000000;
7'b0111100: dataout <= 128'h00000000000000001000000000000000;
7'b0111101: dataout <= 128'h00000000000000002000000000000000;
7'b0111110: dataout <= 128'h00000000000000004000000000000000;
7'b0111111: dataout <= 128'h00000000000000008000000000000000;
7'b1000000: dataout <= 128'h00000000000000010000000000000000;
7'b1000001: dataout <= 128'h00000000000000020000000000000000;
7'b1000010: dataout <= 128'h00000000000000040000000000000000;
7'b1000011: dataout <= 128'h00000000000000080000000000000000;
7'b1000100: dataout <= 128'h00000000000000100000000000000000;
7'b1000101: dataout <= 128'h00000000000000200000000000000000;
7'b1000110: dataout <= 128'h00000000000000400000000000000000;
7'b1000111: dataout <= 128'h00000000000000800000000000000000;
7'b1001000: dataout <= 128'h00000000000001000000000000000000;
7'b1001001: dataout <= 128'h00000000000002000000000000000000;
7'b1001010: dataout <= 128'h00000000000004000000000000000000;
7'b1001011: dataout <= 128'h00000000000008000000000000000000;
7'b1001100: dataout <= 128'h00000000000010000000000000000000;
7'b1001101: dataout <= 128'h00000000000020000000000000000000;
7'b1001110: dataout <= 128'h00000000000040000000000000000000;
7'b1001111: dataout <= 128'h00000000000080000000000000000000;
7'b1010000: dataout <= 128'h00000000000100000000000000000000;
7'b1010001: dataout <= 128'h00000000000200000000000000000000;
7'b1010010: dataout <= 128'h00000000000400000000000000000000;
7'b1010011: dataout <= 128'h00000000000800000000000000000000;
7'b1010100: dataout <= 128'h00000000001000000000000000000000;
7'b1010101: dataout <= 128'h00000000002000000000000000000000;
7'b1010110: dataout <= 128'h00000000004000000000000000000000;
7'b1010111: dataout <= 128'h00000000008000000000000000000000;
7'b1011000: dataout <= 128'h00000000010000000000000000000000;
7'b1011001: dataout <= 128'h00000000020000000000000000000000;
7'b1011010: dataout <= 128'h00000000040000000000000000000000;
7'b1011011: dataout <= 128'h00000000080000000000000000000000;
7'b1011100: dataout <= 128'h00000000100000000000000000000000;
7'b1011101: dataout <= 128'h00000000200000000000000000000000;
7'b1011110: dataout <= 128'h00000000400000000000000000000000;
7'b1011111: dataout <= 128'h00000000800000000000000000000000;
7'b1100000: dataout <= 128'h00000001000000000000000000000000;
7'b1100001: dataout <= 128'h00000002000000000000000000000000;
7'b1100010: dataout <= 128'h00000004000000000000000000000000;
7'b1100011: dataout <= 128'h00000008000000000000000000000000;
7'b1100100: dataout <= 128'h00000010000000000000000000000000;
7'b1100101: dataout <= 128'h00000020000000000000000000000000;
7'b1100110: dataout <= 128'h00000040000000000000000000000000;
7'b1100111: dataout <= 128'h00000080000000000000000000000000;
7'b1101000: dataout <= 128'h00000100000000000000000000000000;
7'b1101001: dataout <= 128'h00000200000000000000000000000000;
7'b1101010: dataout <= 128'h00000400000000000000000000000000;
7'b1101011: dataout <= 128'h00000800000000000000000000000000;
7'b1101100: dataout <= 128'h00001000000000000000000000000000;
7'b1101101: dataout <= 128'h00002000000000000000000000000000;
7'b1101110: dataout <= 128'h00004000000000000000000000000000;
7'b1101111: dataout <= 128'h00008000000000000000000000000000;
7'b1110000: dataout <= 128'h00010000000000000000000000000000;
7'b1110001: dataout <= 128'h00020000000000000000000000000000;
7'b1110010: dataout <= 128'h00040000000000000000000000000000;
7'b1110011: dataout <= 128'h00080000000000000000000000000000;
7'b1110100: dataout <= 128'h00100000000000000000000000000000;
7'b1110101: dataout <= 128'h00200000000000000000000000000000;
7'b1110110: dataout <= 128'h00400000000000000000000000000000;
7'b1110111: dataout <= 128'h00800000000000000000000000000000;
7'b1111000: dataout <= 128'h01000000000000000000000000000000;
7'b1111001: dataout <= 128'h02000000000000000000000000000000;
7'b1111010: dataout <= 128'h04000000000000000000000000000000;
7'b1111011: dataout <= 128'h08000000000000000000000000000000;
7'b1111100: dataout <= 128'h10000000000000000000000000000000;
7'b1111101: dataout <= 128'h20000000000000000000000000000000;
7'b1111110: dataout <= 128'h40000000000000000000000000000000;
7'b1111111: dataout <= 128'h80000000000000000000000000000000;
default: dataout<=128'h0;
endcase
end
endmodule

View File

@ -0,0 +1,149 @@
module encoder128(datain,dataout);
input [127:0] datain;
output [6:0] dataout;
reg [6:0] dataout;
always @(datain)
begin
case (datain)
128'h00000000000000000000000000000001 : dataout<=7'b0000000;
128'h00000000000000000000000000000002 : dataout<=7'b0000001;
128'h00000000000000000000000000000004 : dataout<=7'b0000010;
128'h00000000000000000000000000000008 : dataout<=7'b0000011;
128'h00000000000000000000000000000010 : dataout<=7'b0000100;
128'h00000000000000000000000000000020 : dataout<=7'b0000101;
128'h00000000000000000000000000000040 : dataout<=7'b0000110;
128'h00000000000000000000000000000080 : dataout<=7'b0000111;
128'h00000000000000000000000000000100 : dataout<=7'b0001000;
128'h00000000000000000000000000000200 : dataout<=7'b0001001;
128'h00000000000000000000000000000400 : dataout<=7'b0001010;
128'h00000000000000000000000000000800 : dataout<=7'b0001011;
128'h00000000000000000000000000001000 : dataout<=7'b0001000;
128'h00000000000000000000000000002000 : dataout<=7'b0001101;
128'h00000000000000000000000000004000 : dataout<=7'b0001110;
128'h00000000000000000000000000008000 : dataout<=7'b0001111;
128'h00000000000000000000000000010000 : dataout<=7'b0010000;
128'h00000000000000000000000000020000 : dataout<=7'b0010001;
128'h00000000000000000000000000040000 : dataout<=7'b0010010;
128'h00000000000000000000000000080000 : dataout<=7'b0010011;
128'h00000000000000000000000000100000 : dataout<=7'b0010100;
128'h00000000000000000000000000200000 : dataout<=7'b0010101;
128'h00000000000000000000000000400000 : dataout<=7'b0010110;
128'h00000000000000000000000000800000 : dataout<=7'b0010111;
128'h00000000000000000000000001000000 : dataout<=7'b0011000;
128'h00000000000000000000000002000000 : dataout<=7'b0011001;
128'h00000000000000000000000004000000 : dataout<=7'b0011010;
128'h00000000000000000000000008000000 : dataout<=7'b0011011;
128'h00000000000000000000000010000000 : dataout<=7'b0011000;
128'h00000000000000000000000020000000 : dataout<=7'b0011101;
128'h00000000000000000000000040000000 : dataout<=7'b0011110;
128'h00000000000000000000000080000000 : dataout<=7'b0011111;
128'h00000000000000000000000100000000 : dataout<=7'b0100000;
128'h00000000000000000000000200000000 : dataout<=7'b0100001;
128'h00000000000000000000000400000000 : dataout<=7'b0100010;
128'h00000000000000000000000800000000 : dataout<=7'b0100011;
128'h00000000000000000000001000000000 : dataout<=7'b0100100;
128'h00000000000000000000002000000000 : dataout<=7'b0100101;
128'h00000000000000000000004000000000 : dataout<=7'b0100110;
128'h00000000000000000000008000000000 : dataout<=7'b0100111;
128'h00000000000000000000010000000000 : dataout<=7'b0101000;
128'h00000000000000000000020000000000 : dataout<=7'b0101001;
128'h00000000000000000000040000000000 : dataout<=7'b0101010;
128'h00000000000000000000080000000000 : dataout<=7'b0101011;
128'h00000000000000000000100000000000 : dataout<=7'b0101000;
128'h00000000000000000000200000000000 : dataout<=7'b0101101;
128'h00000000000000000000400000000000 : dataout<=7'b0101110;
128'h00000000000000000000800000000000 : dataout<=7'b0101111;
128'h00000000000000000001000000000000 : dataout<=7'b0110000;
128'h00000000000000000002000000000000 : dataout<=7'b0110001;
128'h00000000000000000004000000000000 : dataout<=7'b0110010;
128'h00000000000000000008000000000000 : dataout<=7'b0110011;
128'h00000000000000000010000000000000 : dataout<=7'b0110100;
128'h00000000000000000020000000000000 : dataout<=7'b0110101;
128'h00000000000000000040000000000000 : dataout<=7'b0110110;
128'h00000000000000000080000000000000 : dataout<=7'b0110111;
128'h00000000000000000100000000000000 : dataout<=7'b0111000;
128'h00000000000000000200000000000000 : dataout<=7'b0111001;
128'h00000000000000000400000000000000 : dataout<=7'b0111010;
128'h00000000000000000800000000000000 : dataout<=7'b0111011;
128'h00000000000000001000000000000000 : dataout<=7'b0111000;
128'h00000000000000002000000000000000 : dataout<=7'b0111101;
128'h00000000000000004000000000000000 : dataout<=7'b0111110;
128'h00000000000000008000000000000000 : dataout<=7'b0111111;
128'h00000000000000010000000000000000 : dataout<=7'b1000000;
128'h00000000000000020000000000000000 : dataout<=7'b1000001;
128'h00000000000000040000000000000000 : dataout<=7'b1000010;
128'h00000000000000080000000000000000 : dataout<=7'b1000011;
128'h00000000000000100000000000000000 : dataout<=7'b1000100;
128'h00000000000000200000000000000000 : dataout<=7'b1000101;
128'h00000000000000400000000000000000 : dataout<=7'b1000110;
128'h00000000000000800000000000000000 : dataout<=7'b1000111;
128'h00000000000001000000000000000000 : dataout<=7'b1001000;
128'h00000000000002000000000000000000 : dataout<=7'b1001001;
128'h00000000000004000000000000000000 : dataout<=7'b1001010;
128'h00000000000008000000000000000000 : dataout<=7'b1001011;
128'h00000000000010000000000000000000 : dataout<=7'b1001000;
128'h00000000000020000000000000000000 : dataout<=7'b1001101;
128'h00000000000040000000000000000000 : dataout<=7'b1001110;
128'h00000000000080000000000000000000 : dataout<=7'b1001111;
128'h00000000000100000000000000000000 : dataout<=7'b1010000;
128'h00000000000200000000000000000000 : dataout<=7'b1010001;
128'h00000000000400000000000000000000 : dataout<=7'b1010010;
128'h00000000000800000000000000000000 : dataout<=7'b1010011;
128'h00000000001000000000000000000000 : dataout<=7'b1010100;
128'h00000000002000000000000000000000 : dataout<=7'b1010101;
128'h00000000004000000000000000000000 : dataout<=7'b1010110;
128'h00000000008000000000000000000000 : dataout<=7'b1010111;
128'h00000000010000000000000000000000 : dataout<=7'b1011000;
128'h00000000020000000000000000000000 : dataout<=7'b1011001;
128'h00000000040000000000000000000000 : dataout<=7'b1011010;
128'h00000000080000000000000000000000 : dataout<=7'b1011011;
128'h00000000100000000000000000000000 : dataout<=7'b1011000;
128'h00000000200000000000000000000000 : dataout<=7'b1011101;
128'h00000000400000000000000000000000 : dataout<=7'b1011110;
128'h00000000800000000000000000000000 : dataout<=7'b1011111;
128'h00000001000000000000000000000000 : dataout<=7'b1100000;
128'h00000002000000000000000000000000 : dataout<=7'b1100001;
128'h00000004000000000000000000000000 : dataout<=7'b1100010;
128'h00000008000000000000000000000000 : dataout<=7'b1100011;
128'h00000010000000000000000000000000 : dataout<=7'b1100100;
128'h00000020000000000000000000000000 : dataout<=7'b1100101;
128'h00000040000000000000000000000000 : dataout<=7'b1100110;
128'h00000080000000000000000000000000 : dataout<=7'b1100111;
128'h00000100000000000000000000000000 : dataout<=7'b1101000;
128'h00000200000000000000000000000000 : dataout<=7'b1101001;
128'h00000400000000000000000000000000 : dataout<=7'b1101010;
128'h00000800000000000000000000000000 : dataout<=7'b1101011;
128'h00001000000000000000000000000000 : dataout<=7'b1101000;
128'h00002000000000000000000000000000 : dataout<=7'b1101101;
128'h00004000000000000000000000000000 : dataout<=7'b1101110;
128'h00008000000000000000000000000000 : dataout<=7'b1101111;
128'h00010000000000000000000000000000 : dataout<=7'b1110000;
128'h00020000000000000000000000000000 : dataout<=7'b1110001;
128'h00040000000000000000000000000000 : dataout<=7'b1110010;
128'h00080000000000000000000000000000 : dataout<=7'b1110011;
128'h00100000000000000000000000000000 : dataout<=7'b1110100;
128'h00200000000000000000000000000000 : dataout<=7'b1110101;
128'h00400000000000000000000000000000 : dataout<=7'b1110110;
128'h00800000000000000000000000000000 : dataout<=7'b1110111;
128'h01000000000000000000000000000000 : dataout<=7'b1111000;
128'h02000000000000000000000000000000 : dataout<=7'b1111001;
128'h04000000000000000000000000000000 : dataout<=7'b1111010;
128'h08000000000000000000000000000000 : dataout<=7'b1111011;
128'h10000000000000000000000000000000 : dataout<=7'b1111000;
128'h20000000000000000000000000000000 : dataout<=7'b1111101;
128'h40000000000000000000000000000000 : dataout<=7'b1111110;
128'h80000000000000000000000000000000 : dataout<=7'b1111111;
default: dataout<=7'b0000000;
endcase
end
endmodule

View File

@ -0,0 +1,104 @@
module top(clock,reset,datain,dataout,datain1,dataout1);
input clock,reset;
input [127:0] datain;
output [127:0] dataout;
input [127:0] datain1;
output [127:0] dataout1;
wire [6:0] enc_out;
reg [127:0] data_encin;
reg [6:0] data_encout;
wire [6:0] enc_out1;
reg [127:0] data_encin1;
reg [6:0] data_encout1;
encoder128 U01(.datain(data_encin),.dataout(enc_out));
decoder128 U02(.datain(data_encout),.dataout(dataout));
encoder128 U011(.datain(data_encin1),.dataout(enc_out1));
decoder128 U021(.datain(data_encout1),.dataout(dataout1));
always @(posedge clock)
begin
if (reset)
data_encin <= 127'h00000;
else
data_encin <= datain;
end
always @(posedge clock)
begin
if (reset)
data_encout <= 7'h0;
else
data_encout<= enc_out;
end
always @(posedge clock)
begin
if (reset)
data_encin1 <= 127'h00000;
else
data_encin1 <= datain1;
end
always @(posedge clock)
begin
if (reset)
data_encout1 <= 7'h0;
else
data_encout1<= enc_out1;
end
endmodule

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,75 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE SD Card Controller IP Core ////
//// ////
//// bistable_domain_cross.v ////
//// ////
//// This file is part of the WISHBONE SD Card ////
//// Controller IP Core project ////
//// http://opencores.org/project,sd_card_controller ////
//// ////
//// Description ////
//// Clock synchronisation beetween two clock domains. ////
//// Assumption is that input signal duration has to be at least ////
//// one clk_b clock period. ////
//// ////
//// Author(s): ////
//// - Marek Czerski, ma.czerski@gmail.com ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2013 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
module bistable_domain_cross(
rst,
clk_a,
in,
clk_b,
out
);
parameter width = 1;
input rst;
input clk_a;
input [width-1:0] in;
input clk_b;
output [width-1:0] out;
// We use a two-stages shift-register to synchronize in to the clk_b clock domain
reg [width-1:0] sync_clk_b [1:0];
always @(posedge clk_b or posedge rst)
begin
if (rst == 1) begin
sync_clk_b[0] <= 0;
sync_clk_b[1] <= 0;
end else begin
sync_clk_b[0] <= in;
sync_clk_b[1] <= sync_clk_b[0];
end
end
assign out = sync_clk_b[1]; // new signal synchronized to (=ready to be used in) clk_b domain
endmodule

View File

@ -0,0 +1,64 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE SD Card Controller IP Core ////
//// ////
//// edge_detect.v ////
//// ////
//// This file is part of the WISHBONE SD Card ////
//// Controller IP Core project ////
//// http://opencores.org/project,sd_card_controller ////
//// ////
//// Description ////
//// Signal edge detection. If input signal transitions between ////
//// two states, output signal is generated for one clock cycle. ////
//// ////
//// Author(s): ////
//// - Marek Czerski, ma.czerski@gmail.com ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2013 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
module edge_detect (
input rst,
input clk,
input sig,
output rise,
output fall
);
reg [1:0] sig_reg;
always @(posedge clk or posedge rst)
if (rst == 1'b1)
sig_reg <= 2'b00;
else
sig_reg <= {sig_reg[0], sig};
assign rise = sig_reg[0] == 1'b1 && sig_reg[1] == 1'b0 ? 1'b1 : 1'b0;
assign fall = sig_reg[0] == 1'b0 && sig_reg[1] == 1'b1 ? 1'b1 : 1'b0;
endmodule

View File

@ -0,0 +1,501 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// Generic Dual-Port Synchronous RAM ////
//// ////
//// This file is part of memory library available from ////
//// http://www.opencores.org/cvsweb.shtml/generic_memories/ ////
//// ////
//// Description ////
//// This block is a wrapper with common dual-port ////
//// synchronous memory interface for different ////
//// types of ASIC and FPGA RAMs. Beside universal memory ////
//// interface it also provides behavioral model of generic ////
//// dual-port synchronous RAM. ////
//// It also contains a fully synthesizeable model for FPGAs. ////
//// It should be used in all OPENCORES designs that want to be ////
//// portable accross different target technologies and ////
//// independent of target memory. ////
//// ////
//// Supported ASIC RAMs are: ////
//// - Artisan Dual-Port Sync RAM ////
//// - Avant! Two-Port Sync RAM (*) ////
//// - Virage 2-port Sync RAM ////
//// ////
//// Supported FPGA RAMs are: ////
//// - Generic FPGA (VENDOR_FPGA) ////
//// Tested RAMs: Altera, Xilinx ////
//// Synthesis tools: LeonardoSpectrum, Synplicity ////
//// - Xilinx (VENDOR_XILINX) ////
//// - Altera (VENDOR_ALTERA) ////
//// ////
//// To Do: ////
//// - fix Avant! ////
//// - add additional RAMs (VS etc) ////
//// ////
//// Author(s): ////
//// - Richard Herveille, richard@asics.ws ////
//// - Damjan Lampret, lampret@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: not supported by cvs2svn $
// Revision 1.3 2001/11/09 00:34:18 samg
// minor changes: unified with all common rams
//
// Revision 1.2 2001/11/08 19:11:31 samg
// added valid checks to behvioral model
//
// Revision 1.1.1.1 2001/09/14 09:57:10 rherveille
// Major cleanup.
// Files are now compliant to Altera & Xilinx memories.
// Memories are now compatible, i.e. drop-in replacements.
// Added synthesizeable generic FPGA description.
// Created "generic_memories" cvs entry.
//
// Revision 1.1.1.2 2001/08/21 13:09:27 damjan
// *** empty log message ***
//
// Revision 1.1 2001/08/20 18:23:20 damjan
// Initial revision
//
// Revision 1.1 2001/08/09 13:39:33 lampret
// Major clean-up.
//
// Revision 1.2 2001/07/30 05:38:02 lampret
// Adding empty directories required by HDL coding guidelines
//
//
//`include "timescale.v"
`define VENDOR_FPGA
//`define VENDOR_XILINX
//`define VENDOR_ALTERA
module generic_dpram(
// Generic synchronous dual-port RAM interface
rclk, rrst, rce, oe, raddr, do,
wclk, wrst, wce, we, waddr, di
);
//
// Default address and data buses width
//
parameter aw = 5; // number of bits in address-bus
parameter dw = 16; // number of bits in data-bus
//
// Generic synchronous double-port RAM interface
//
// read port
input rclk; // read clock, rising edge trigger
input rrst; // read port reset, active high
input rce; // read port chip enable, active high
input oe; // output enable, active high
input [aw-1:0] raddr; // read address
output [dw-1:0] do; // data output
// write port
input wclk; // write clock, rising edge trigger
input wrst; // write port reset, active high
input wce; // write port chip enable, active high
input we; // write enable, active high
input [aw-1:0] waddr; // write address
input [dw-1:0] di; // data input
//
// Module body
//
`ifdef VENDOR_FPGA
//
// Instantiation synthesizeable FPGA memory
//
// This code has been tested using LeonardoSpectrum and Synplicity.
// The code correctly instantiates Altera EABs and Xilinx BlockRAMs.
//
reg [dw-1:0] mem [(1<<aw) -1:0]; //pragma attribute mem block_ram false
reg [aw-1:0] ra; // register read address
// read operation
always @(posedge rclk)
if (rce)
ra <= raddr;
assign do = mem[ra];
// write operation
always@(posedge wclk)
if (we && wce)
mem[waddr] <= di;
`else
`ifdef VENDOR_XILINX
//
// Instantiation of FPGA memory:
//
// Virtex/Spartan2 BlockRAMs
//
xilinx_ram_dp xilinx_ram(
// read port
.CLKA(rclk),
.RSTA(rrst),
.ENA(rce),
.ADDRA(raddr),
.DIA( {dw{1'b0}} ),
.WEA(1'b0),
.DOA(do),
// write port
.CLKB(wclk),
.RSTB(wrst),
.ENB(wce),
.ADDRB(waddr),
.DIB(di),
.WEB(we),
.DOB()
);
defparam
xilinx_ram.dwidth = dw,
xilinx_ram.awidth = aw;
`else
`ifdef VENDOR_ALTERA
//
// Instantiation of FPGA memory:
//
// Altera FLEX/APEX EABs
//
altera_ram_dp altera_ram(
// read port
.rdclock(rclk),
.rdclocken(rce),
.rdaddress(raddr),
.q(do),
// write port
.wrclock(wclk),
.wrclocken(wce),
.wren(we),
.wraddress(waddr),
.data(di)
);
defparam
altera_ram.dwidth = dw,
altera_ram.awidth = aw;
`else
`ifdef VENDOR_ARTISAN
//
// Instantiation of ASIC memory:
//
// Artisan Synchronous Double-Port RAM (ra2sh)
//
art_hsdp #(dw, 1<<aw, aw) artisan_sdp(
// read port
.qa(do),
.clka(rclk),
.cena(~rce),
.wena(1'b1),
.aa(raddr),
.da( {dw{1'b0}} ),
.oena(~oe),
// write port
.qb(),
.clkb(wclk),
.cenb(~wce),
.wenb(~we),
.ab(waddr),
.db(di),
.oenb(1'b1)
);
`else
`ifdef VENDOR_AVANT
//
// Instantiation of ASIC memory:
//
// Avant! Asynchronous Two-Port RAM
//
avant_atp avant_atp(
.web(~we),
.reb(),
.oeb(~oe),
.rcsb(),
.wcsb(),
.ra(raddr),
.wa(waddr),
.di(di),
.do(do)
);
`else
`ifdef VENDOR_VIRAGE
//
// Instantiation of ASIC memory:
//
// Virage Synchronous 2-port R/W RAM
//
virage_stp virage_stp(
// read port
.CLKA(rclk),
.MEA(rce_a),
.ADRA(raddr),
.DA( {dw{1'b0}} ),
.WEA(1'b0),
.OEA(oe),
.QA(do),
// write port
.CLKB(wclk),
.MEB(wce),
.ADRB(waddr),
.DB(di),
.WEB(we),
.OEB(1'b1),
.QB()
);
`else
//
// Generic dual-port synchronous RAM model
//
//
// Generic RAM's registers and wires
//
reg [dw-1:0] mem [(1<<aw)-1:0]; // RAM content
reg [dw-1:0] do_reg; // RAM data output register
//
// Data output drivers
//
assign do = (oe & rce) ? do_reg : {dw{1'bz}};
// read operation
always @(posedge rclk)
if (rce)
do_reg <= (we && (waddr==raddr)) ? {dw{1'b x}} : mem[raddr];
// write operation
always @(posedge wclk)
if (wce && we)
mem[waddr] <= di;
// Task prints range of memory
// *** Remember that tasks are non reentrant, don't call this task in parallel for multiple instantiations.
task print_ram;
input [aw-1:0] start;
input [aw-1:0] finish;
integer rnum;
begin
for (rnum=start;rnum<=finish;rnum=rnum+1)
$display("Addr %h = %h",rnum,mem[rnum]);
end
endtask
`endif // !VENDOR_VIRAGE
`endif // !VENDOR_AVANT
`endif // !VENDOR_ARTISAN
`endif // !VENDOR_ALTERA
`endif // !VENDOR_XILINX
`endif // !VENDOR_FPGA
endmodule
//
// Black-box modules
//
`ifdef VENDOR_ALTERA
module altera_ram_dp(
data,
wraddress,
rdaddress,
wren,
wrclock,
wrclocken,
rdclock,
rdclocken,
q) /* synthesis black_box */;
parameter awidth = 7;
parameter dwidth = 8;
input [dwidth -1:0] data;
input [awidth -1:0] wraddress;
input [awidth -1:0] rdaddress;
input wren;
input wrclock;
input wrclocken;
input rdclock;
input rdclocken;
output [dwidth -1:0] q;
// synopsis translate_off
// exemplar translate_off
syn_dpram_rowr #(
"UNUSED",
dwidth,
awidth,
1 << awidth
)
altera_dpram_model (
// read port
.RdClock(rdclock),
.RdClken(rdclocken),
.RdAddress(rdaddress),
.RdEn(1'b1),
.Q(q),
// write port
.WrClock(wrclock),
.WrClken(wrclocken),
.WrAddress(wraddress),
.WrEn(wren),
.Data(data)
);
// exemplar translate_on
// synopsis translate_on
endmodule
`endif // VENDOR_ALTERA
`ifdef VENDOR_XILINX
module xilinx_ram_dp (
ADDRA,
CLKA,
ADDRB,
CLKB,
DIA,
WEA,
DIB,
WEB,
ENA,
ENB,
RSTA,
RSTB,
DOA,
DOB) /* synthesis black_box */ ;
parameter awidth = 7;
parameter dwidth = 8;
// port_a
input CLKA;
input RSTA;
input ENA;
input [awidth-1:0] ADDRA;
input [dwidth-1:0] DIA;
input WEA;
output [dwidth-1:0] DOA;
// port_b
input CLKB;
input RSTB;
input ENB;
input [awidth-1:0] ADDRB;
input [dwidth-1:0] DIB;
input WEB;
output [dwidth-1:0] DOB;
// insert simulation model
// synopsys translate_off
// exemplar translate_off
C_MEM_DP_BLOCK_V1_0 #(
awidth,
awidth,
1,
1,
"0",
1 << awidth,
1 << awidth,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
"",
16,
0,
0,
1,
1,
1,
1,
dwidth,
dwidth)
xilinx_dpram_model (
.ADDRA(ADDRA),
.CLKA(CLKA),
.ADDRB(ADDRB),
.CLKB(CLKB),
.DIA(DIA),
.WEA(WEA),
.DIB(DIB),
.WEB(WEB),
.ENA(ENA),
.ENB(ENB),
.RSTA(RSTA),
.RSTB(RSTB),
.DOA(DOA),
.DOB(DOB));
// exemplar translate_on
// synopsys translate_on
endmodule
`endif // VENDOR_XILINX

View File

@ -0,0 +1,324 @@
/////////////////////////////////////////////////////////////////////
//// ////
//// Universal FIFO Dual Clock, gray encoded ////
//// ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// D/L from: http://www.opencores.org/cores/generic_fifos/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// 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: generic_fifo_dc_gray.v,v 1.2 2004-01-13 09:11:55 rudi Exp $
//
// $Date: 2004-01-13 09:11:55 $
// $Revision: 1.2 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.1 2003/10/14 09:34:41 rudi
// Dual clock FIFO Gray Code encoded version.
//
//
//
//
//
//`include "timescale.v"
/*
Description
===========
I/Os
----
rd_clk Read Port Clock
wr_clk Write Port Clock
rst low active, either sync. or async. master reset (see below how to select)
clr synchronous clear (just like reset but always synchronous), high active
re read enable, synchronous, high active
we read enable, synchronous, high active
din Data Input
dout Data Output
full Indicates the FIFO is full (driven at the rising edge of wr_clk)
empty Indicates the FIFO is empty (driven at the rising edge of rd_clk)
wr_level indicates the FIFO level:
2'b00 0-25% full
2'b01 25-50% full
2'b10 50-75% full
2'b11 %75-100% full
rd_level indicates the FIFO level:
2'b00 0-25% empty
2'b01 25-50% empty
2'b10 50-75% empty
2'b11 %75-100% empty
Status Timing
-------------
All status outputs are registered. They are asserted immediately
as the full/empty condition occurs, however, there is a 2 cycle
delay before they are de-asserted once the condition is not true
anymore.
Parameters
----------
The FIFO takes 2 parameters:
dw Data bus width
aw Address bus width (Determines the FIFO size by evaluating 2^aw)
Synthesis Results
-----------------
In a Spartan 2e a 8 bit wide, 8 entries deep FIFO, takes 97 LUTs and runs
at about 113 MHz (IO insertion disabled).
Misc
----
This design assumes you will do appropriate status checking externally.
IMPORTANT ! writing while the FIFO is full or reading while the FIFO is
empty will place the FIFO in an undefined state.
*/
module generic_fifo_dc_gray( rd_clk, wr_clk, rst, clr, din, we,
dout, re, full, empty, wr_level, rd_level );
parameter dw=16;
parameter aw=8;
input rd_clk, wr_clk, rst, clr;
input [dw-1:0] din;
input we;
output [dw-1:0] dout;
input re;
output full;
output empty;
output [1:0] wr_level;
output [1:0] rd_level;
////////////////////////////////////////////////////////////////////
//
// Local Wires
//
reg [aw:0] wp_bin, wp_gray;
reg [aw:0] rp_bin, rp_gray;
reg [aw:0] wp_s, rp_s;
reg full, empty;
wire [aw:0] wp_bin_next, wp_gray_next;
wire [aw:0] rp_bin_next, rp_gray_next;
wire [aw:0] wp_bin_x, rp_bin_x;
reg [aw-1:0] d1, d2;
reg rd_rst, wr_rst;
reg rd_rst_r, wr_rst_r;
reg rd_clr, wr_clr;
reg rd_clr_r, wr_clr_r;
////////////////////////////////////////////////////////////////////
//
// Reset Logic
//
always @(posedge rd_clk or negedge rst)
if(!rst) rd_rst <= 1'b0;
else
if(rd_rst_r) rd_rst <= 1'b1; // Release Reset
always @(posedge rd_clk or negedge rst)
if(!rst) rd_rst_r <= 1'b0;
else rd_rst_r <= 1'b1;
always @(posedge wr_clk or negedge rst)
if(!rst) wr_rst <= 1'b0;
else
if(wr_rst_r) wr_rst <= 1'b1; // Release Reset
always @(posedge wr_clk or negedge rst)
if(!rst) wr_rst_r <= 1'b0;
else wr_rst_r <= 1'b1;
always @(posedge rd_clk or posedge clr)
if(clr) rd_clr <= 1'b1;
else
if(!rd_clr_r) rd_clr <= 1'b0; // Release Clear
always @(posedge rd_clk or posedge clr)
if(clr) rd_clr_r <= 1'b1;
else rd_clr_r <= 1'b0;
always @(posedge wr_clk or posedge clr)
if(clr) wr_clr <= 1'b1;
else
if(!wr_clr_r) wr_clr <= 1'b0; // Release Clear
always @(posedge wr_clk or posedge clr)
if(clr) wr_clr_r <= 1'b1;
else wr_clr_r <= 1'b0;
////////////////////////////////////////////////////////////////////
//
// Memory Block
//
generic_dpram #(aw,dw) u0(
.rclk( rd_clk ),
.rrst( !rd_rst ),
.rce( 1'b1 ),
.oe( 1'b1 ),
.raddr( rp_bin[aw-1:0] ),
.do( dout ),
.wclk( wr_clk ),
.wrst( !wr_rst ),
.wce( 1'b1 ),
.we( we ),
.waddr( wp_bin[aw-1:0] ),
.di( din )
);
////////////////////////////////////////////////////////////////////
//
// Read/Write Pointers Logic
//
always @(posedge wr_clk)
if(!wr_rst) wp_bin <= {aw+1{1'b0}};
else
if(wr_clr) wp_bin <= {aw+1{1'b0}};
else
if(we) wp_bin <= wp_bin_next;
always @(posedge wr_clk)
if(!wr_rst) wp_gray <= {aw+1{1'b0}};
else
if(wr_clr) wp_gray <= {aw+1{1'b0}};
else
if(we) wp_gray <= wp_gray_next;
assign wp_bin_next = wp_bin + {{aw{1'b0}},1'b1};
assign wp_gray_next = wp_bin_next ^ {1'b0, wp_bin_next[aw:1]};
always @(posedge rd_clk)
if(!rd_rst) rp_bin <= {aw+1{1'b0}};
else
if(rd_clr) rp_bin <= {aw+1{1'b0}};
else
if(re) rp_bin <= rp_bin_next;
always @(posedge rd_clk)
if(!rd_rst) rp_gray <= {aw+1{1'b0}};
else
if(rd_clr) rp_gray <= {aw+1{1'b0}};
else
if(re) rp_gray <= rp_gray_next;
assign rp_bin_next = rp_bin + {{aw{1'b0}},1'b1};
assign rp_gray_next = rp_bin_next ^ {1'b0, rp_bin_next[aw:1]};
////////////////////////////////////////////////////////////////////
//
// Synchronization Logic
//
// write pointer
always @(posedge rd_clk) wp_s <= wp_gray;
// read pointer
always @(posedge wr_clk) rp_s <= rp_gray;
////////////////////////////////////////////////////////////////////
//
// Registered Full & Empty Flags
//
assign wp_bin_x = wp_s ^ {1'b0, wp_bin_x[aw:1]}; // convert gray to binary
assign rp_bin_x = rp_s ^ {1'b0, rp_bin_x[aw:1]}; // convert gray to binary
always @(posedge rd_clk)
empty <= (wp_s == rp_gray) | (re & (wp_s == rp_gray_next));
always @(posedge wr_clk)
full <= ((wp_bin[aw-1:0] == rp_bin_x[aw-1:0]) & (wp_bin[aw] != rp_bin_x[aw])) |
(we & (wp_bin_next[aw-1:0] == rp_bin_x[aw-1:0]) & (wp_bin_next[aw] != rp_bin_x[aw]));
////////////////////////////////////////////////////////////////////
//
// Registered Level Indicators
//
reg [1:0] wr_level;
reg [1:0] rd_level;
reg [aw-1:0] wp_bin_xr, rp_bin_xr;
reg full_rc;
reg full_wc;
always @(posedge wr_clk) full_wc <= full;
always @(posedge wr_clk) rp_bin_xr <= ~rp_bin_x[aw-1:0] + {{aw-1{1'b0}}, 1'b1};
always @(posedge wr_clk) d1 <= wp_bin[aw-1:0] + rp_bin_xr[aw-1:0];
always @(posedge wr_clk) wr_level <= {d1[aw-1] | full | full_wc, d1[aw-2] | full | full_wc};
always @(posedge rd_clk) wp_bin_xr <= ~wp_bin_x[aw-1:0];
always @(posedge rd_clk) d2 <= rp_bin[aw-1:0] + wp_bin_xr[aw-1:0];
always @(posedge rd_clk) full_rc <= full;
always @(posedge rd_clk) rd_level <= full_rc ? 2'h0 : {d2[aw-1] | empty, d2[aw-2] | empty};
////////////////////////////////////////////////////////////////////
//
// Sanity Check
//
// synopsys translate_off
//always @(posedge wr_clk)
// if(we && full)
// $display("%m WARNING: Writing while fifo is FULL (%t)",$time);
//always @(posedge rd_clk)
// if(re && empty)
// $display("%m WARNING: Reading while fifo is EMPTY (%t)",$time);
// synopsys translate_on
endmodule

View File

@ -0,0 +1,78 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE SD Card Controller IP Core ////
//// ////
//// monostable_domain_cross.v ////
//// ////
//// This file is part of the WISHBONE SD Card ////
//// Controller IP Core project ////
//// http://opencores.org/project,sd_card_controller ////
//// ////
//// Description ////
//// Clock synchronisation beetween two clock domains. ////
//// Assumption is that input signal duration is always ////
//// one clk_a clock period. If that is true output signal ////
//// duration is always one clk_b clock period. ////
//// ////
//// Author(s): ////
//// - Marek Czerski, ma.czerski@gmail.com ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2013 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
module monostable_domain_cross(
input rst,
input clk_a,
input in,
input clk_b,
output out
);
// this changes level when the in is seen in clk_a
reg toggle_clk_a;
always @(posedge clk_a or posedge rst)
begin
if (rst)
toggle_clk_a <= 0;
else
toggle_clk_a <= toggle_clk_a ^ in;
end
// which can then be sync-ed to clk_b
reg [2:0] sync_clk_b;
always @(posedge clk_b or posedge rst)
begin
if (rst)
sync_clk_b <= 0;
else
sync_clk_b <= {sync_clk_b[1:0], toggle_clk_a};
end
// and recreate the flag in clk_b
assign out = (sync_clk_b[2] ^ sync_clk_b[1]);
endmodule

View File

@ -0,0 +1,79 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE SD Card Controller IP Core ////
//// ////
//// sd_clock_divider.v ////
//// ////
//// This file is part of the WISHBONE SD Card ////
//// Controller IP Core project ////
//// http://opencores.org/project,sd_card_controller ////
//// ////
//// Description ////
//// Control of sd card clock rate ////
//// ////
//// Author(s): ////
//// - Marek Czerski, ma.czerski@gmail.com ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2013 Authors ////
//// ////
//// Based on original work by ////
//// Adam Edvardsson (adam.edvardsson@orsoc.se) ////
//// ////
//// Copyright (C) 2009 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
module sd_clock_divider (
input CLK,
input [7:0] DIVIDER,
input RST,
output SD_CLK
);
reg [7:0] ClockDiv;
reg SD_CLK_O;
//assign SD_CLK = DIVIDER[7] ? CLK : SD_CLK_O;
assign SD_CLK = SD_CLK_O;
always @(posedge CLK or posedge RST)
begin
if (RST) begin
ClockDiv <= 8'b0000_0000;
SD_CLK_O <= 0;
end
else if (ClockDiv == DIVIDER) begin
ClockDiv <= 0;
SD_CLK_O <= ~SD_CLK_O;
end else begin
ClockDiv <= ClockDiv + 8'h1;
SD_CLK_O <= SD_CLK_O;
end
end
endmodule

View File

@ -0,0 +1,245 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE SD Card Controller IP Core ////
//// ////
//// sd_cmd_master.v ////
//// ////
//// This file is part of the WISHBONE SD Card ////
//// Controller IP Core project ////
//// http://opencores.org/project,sd_card_controller ////
//// ////
//// Description ////
//// State machine resposible for controlling command transfers ////
//// on 1-bit sd card command interface ////
//// ////
//// Author(s): ////
//// - Marek Czerski, ma.czerski@gmail.com ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2013 Authors ////
//// ////
//// Based on original work by ////
//// Adam Edvardsson (adam.edvardsson@orsoc.se) ////
//// ////
//// Copyright (C) 2009 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 "sd_defines.v"
module sd_cmd_master(
input sd_clk,
input rst,
input start_i,
input int_status_rst_i,
output [1:0] setting_o,
output reg start_xfr_o,
output reg go_idle_o,
output reg [39:0] cmd_o,
input [119:0] response_i,
input crc_ok_i,
input index_ok_i,
input finish_i,
input busy_i, //direct signal from data sd data input (data[0])
//input card_detect,
input [31:0] argument_i,
input [`CMD_REG_SIZE-1:0] command_i,
input [15:0] timeout_i,
output [`INT_CMD_SIZE-1:0] int_status_o,
output reg [31:0] response_0_o,
output reg [31:0] response_1_o,
output reg [31:0] response_2_o,
output reg [31:0] response_3_o
);
//-----------Types--------------------------------------------------------
reg [15:0] timeout_reg;
reg crc_check;
reg index_check;
reg busy_check;
reg expect_response;
reg long_response;
reg [`INT_CMD_SIZE-1:0] int_status_reg;
//reg card_present;
//reg [3:0]debounce;
reg [15:0] watchdog;
parameter SIZE = 2;
reg [SIZE-1:0] state;
reg [SIZE-1:0] next_state;
parameter IDLE = 2'b00;
parameter EXECUTE = 2'b01;
parameter BUSY_CHECK = 2'b10;
assign setting_o[1:0] = {long_response, expect_response};
assign int_status_o = state == IDLE ? int_status_reg : 5'h0;
//---------------Input ports---------------
// always @ (posedge sd_clk or posedge rst )
// begin
// if (rst) begin
// debounce<=0;
// card_present<=0;
// end
// else begin
// if (!card_detect) begin//Card present
// if (debounce!=4'b1111)
// debounce<=debounce+1'b1;
// end
// else
// debounce<=0;
//
// if (debounce==4'b1111)
// card_present<=1'b1;
// else
// card_present<=1'b0;
// end
// end
always @(state or start_i or finish_i or go_idle_o or busy_check or busy_i)
begin: FSM_COMBO
case(state)
IDLE: begin
if (start_i)
next_state <= EXECUTE;
else
next_state <= IDLE;
end
EXECUTE: begin
if ((finish_i && !busy_check) || go_idle_o)
next_state <= IDLE;
else if (finish_i && busy_check)
next_state <= BUSY_CHECK;
else
next_state <= EXECUTE;
end
BUSY_CHECK: begin
if (!busy_i)
next_state <= IDLE;
else
next_state <= BUSY_CHECK;
end
default: next_state <= IDLE;
endcase
end
always @(posedge sd_clk or posedge rst)
begin: FSM_SEQ
if (rst) begin
state <= IDLE;
end
else begin
state <= next_state;
end
end
always @(posedge sd_clk or posedge rst)
begin
if (rst) begin
crc_check <= 0;
response_0_o <= 0;
response_1_o <= 0;
response_2_o <= 0;
response_3_o <= 0;
int_status_reg <= 0;
expect_response <= 0;
long_response <= 0;
cmd_o <= 0;
start_xfr_o <= 0;
index_check <= 0;
busy_check <= 0;
watchdog <= 0;
timeout_reg <= 0;
go_idle_o <= 0;
end
else begin
case(state)
IDLE: begin
go_idle_o <= 0;
index_check <= command_i[`CMD_IDX_CHECK];
crc_check <= command_i[`CMD_CRC_CHECK];
busy_check <= command_i[`CMD_BUSY_CHECK];
if (command_i[`CMD_RESPONSE_CHECK] == 2'b10 || command_i[`CMD_RESPONSE_CHECK] == 2'b11) begin
expect_response <= 1;
long_response <= 1;
end
else if (command_i[`CMD_RESPONSE_CHECK] == 2'b01) begin
expect_response <= 1;
long_response <= 0;
end
else begin
expect_response <= 0;
long_response <= 0;
end
cmd_o[39:38] <= 2'b01;
cmd_o[37:32] <= command_i[`CMD_INDEX]; //CMD_INDEX
cmd_o[31:0] <= argument_i; //CMD_Argument
timeout_reg <= timeout_i;
watchdog <= 0;
if (start_i) begin
start_xfr_o <= 1;
int_status_reg <= 0;
end
end
EXECUTE: begin
start_xfr_o <= 0;
watchdog <= watchdog + 16'd1;
if (watchdog > timeout_reg) begin
int_status_reg[`INT_CMD_CTE] <= 1;
int_status_reg[`INT_CMD_EI] <= 1;
go_idle_o <= 1;
end
//Incoming New Status
else begin //if ( req_in_int == 1) begin
if (finish_i) begin //Data avaible
if (crc_check & !crc_ok_i) begin
int_status_reg[`INT_CMD_CCRCE] <= 1;
int_status_reg[`INT_CMD_EI] <= 1;
end
if (index_check & !index_ok_i) begin
int_status_reg[`INT_CMD_CIE] <= 1;
int_status_reg[`INT_CMD_EI] <= 1;
end
int_status_reg[`INT_CMD_CC] <= 1;
if (expect_response != 0) begin
response_0_o <= response_i[119:88];
response_1_o <= response_i[87:56];
response_2_o <= response_i[55:24];
response_3_o <= {response_i[23:0], 8'h00};
end
// end
end ////Data avaible
end //Status change
end //EXECUTE state
BUSY_CHECK: begin
start_xfr_o <= 0;
go_idle_o <= 0;
end
endcase
if (int_status_rst_i)
int_status_reg <= 0;
end
end
endmodule

View File

@ -0,0 +1,336 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE SD Card Controller IP Core ////
//// ////
//// sd_cmd_serial_host.v ////
//// ////
//// This file is part of the WISHBONE SD Card ////
//// Controller IP Core project ////
//// http://opencores.org/project,sd_card_controller ////
//// ////
//// Description ////
//// Module resposible for sending and receiving commands ////
//// through 1-bit sd card command interface ////
//// ////
//// Author(s): ////
//// - Marek Czerski, ma.czerski@gmail.com ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2013 Authors ////
//// ////
//// Based on original work by ////
//// Adam Edvardsson (adam.edvardsson@orsoc.se) ////
//// ////
//// Copyright (C) 2009 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
module sd_cmd_serial_host (
sd_clk,
rst,
setting_i,
cmd_i,
start_i,
response_o,
crc_ok_o,
index_ok_o,
finish_o,
cmd_dat_i,
cmd_out_o,
cmd_oe_o
);
//---------------Input ports---------------
input sd_clk;
input rst;
input [1:0] setting_i;
input [39:0] cmd_i;
input start_i;
input cmd_dat_i;
//---------------Output ports---------------
output reg [119:0] response_o;
output reg finish_o;
output reg crc_ok_o;
output reg index_ok_o;
output reg cmd_oe_o;
output reg cmd_out_o;
//-------------Internal Constant-------------
parameter INIT_DELAY = 4;
parameter BITS_TO_SEND = 48;
parameter CMD_SIZE = 40;
parameter RESP_SIZE = 128;
//---------------Internal variable-----------
reg cmd_dat_reg;
integer resp_len;
reg with_response;
reg [CMD_SIZE-1:0] cmd_buff;
reg [RESP_SIZE-1:0] resp_buff;
integer resp_idx;
//CRC
reg crc_rst;
reg [6:0]crc_in;
wire [6:0] crc_val;
reg crc_enable;
reg crc_bit;
reg crc_ok;
//-Internal Counterns
integer counter;
//-State Machine
parameter STATE_SIZE = 10;
parameter
INIT = 7'h00,
IDLE = 7'h01,
SETUP_CRC = 7'h02,
WRITE = 7'h04,
READ_WAIT = 7'h08,
READ = 7'h10,
FINISH_WR = 7'h20,
FINISH_WO = 7'h40;
reg [STATE_SIZE-1:0] state;
reg [STATE_SIZE-1:0] next_state;
//Misc
`define cmd_idx (CMD_SIZE-1-counter)
//sd cmd input pad register
always @(posedge sd_clk)
cmd_dat_reg <= cmd_dat_i;
//------------------------------------------
sd_crc_7 CRC_7(
crc_bit,
crc_enable,
sd_clk,
crc_rst,
crc_val);
//------------------------------------------
always @(state or counter or start_i or with_response or cmd_dat_reg or resp_len)
begin: FSM_COMBO
case(state)
INIT: begin
if (counter >= INIT_DELAY) begin
next_state <= IDLE;
end
else begin
next_state <= INIT;
end
end
IDLE: begin
if (start_i) begin
next_state <= SETUP_CRC;
end
else begin
next_state <= IDLE;
end
end
SETUP_CRC:
next_state <= WRITE;
WRITE:
if (counter >= BITS_TO_SEND && with_response) begin
next_state <= READ_WAIT;
end
else if (counter >= BITS_TO_SEND) begin
next_state <= FINISH_WO;
end
else begin
next_state <= WRITE;
end
READ_WAIT:
if (!cmd_dat_reg) begin
next_state <= READ;
end
else begin
next_state <= READ_WAIT;
end
FINISH_WO:
next_state <= IDLE;
READ:
if (counter >= resp_len+8) begin
next_state <= FINISH_WR;
end
else begin
next_state <= READ;
end
FINISH_WR:
next_state <= IDLE;
default:
next_state <= INIT;
endcase
end
always @(posedge sd_clk or posedge rst)
begin: COMMAND_DECODER
if (rst) begin
resp_len <= 0;
with_response <= 0;
cmd_buff <= 0;
end
else begin
if (start_i == 1) begin
resp_len <= setting_i[1] ? 127 : 39;
with_response <= setting_i[0];
cmd_buff <= cmd_i;
end
end
end
//----------------Seq logic------------
always @(posedge sd_clk or posedge rst)
begin: FSM_SEQ
if (rst) begin
state <= INIT;
end
else begin
state <= next_state;
end
end
//-------------OUTPUT_LOGIC-------
always @(posedge sd_clk or posedge rst)
begin: FSM_OUT
if (rst) begin
crc_enable <= 0;
resp_idx <= 0;
cmd_oe_o <= 1;
cmd_out_o <= 1;
resp_buff <= 0;
finish_o <= 0;
crc_rst <= 1;
crc_bit <= 0;
crc_in <= 0;
response_o <= 0;
index_ok_o <= 0;
crc_ok_o <= 0;
crc_ok <= 0;
counter <= 0;
end
else begin
case(state)
INIT: begin
counter <= counter+1;
cmd_oe_o <= 1;
cmd_out_o <= 1;
end
IDLE: begin
cmd_oe_o <= 0; //Put CMD to Z
counter <= 0;
crc_rst <= 1;
crc_enable <= 0;
response_o <= 0;
resp_idx <= 0;
crc_ok_o <= 0;
index_ok_o <= 0;
finish_o <= 0;
end
SETUP_CRC: begin
crc_rst <= 0;
crc_enable <= 1;
crc_bit <= cmd_buff[`cmd_idx];
end
WRITE: begin
if (counter < BITS_TO_SEND-8) begin // 1->40 CMD, (41 >= CNT && CNT <=47) CRC, 48 stop_bit
cmd_oe_o <= 1;
cmd_out_o <= cmd_buff[`cmd_idx];
if (counter < BITS_TO_SEND-9) begin //1 step ahead
crc_bit <= cmd_buff[`cmd_idx-1];
end else begin
crc_enable <= 0;
end
end
else if (counter < BITS_TO_SEND-1) begin
cmd_oe_o <= 1;
crc_enable <= 0;
cmd_out_o <= crc_val[BITS_TO_SEND-counter-2];
end
else if (counter == BITS_TO_SEND-1) begin
cmd_oe_o <= 1;
cmd_out_o <= 1'b1;
end
else begin
cmd_oe_o <= 0;
cmd_out_o <= 1'b1;
end
counter <= counter+1;
end
READ_WAIT: begin
crc_enable <= 0;
crc_rst <= 1;
counter <= 1;
cmd_oe_o <= 0;
resp_buff[RESP_SIZE-1] <= cmd_dat_reg;
end
FINISH_WO: begin
finish_o <= 1;
crc_enable <= 0;
crc_rst <= 1;
counter <= 0;
cmd_oe_o <= 0;
end
READ: begin
crc_rst <= 0;
crc_enable <= (resp_len != RESP_SIZE-1 || counter > 7);
cmd_oe_o <= 0;
if (counter <= resp_len) begin
if (counter < 8) //1+1+6 (S,T,Index)
resp_buff[RESP_SIZE-1-counter] <= cmd_dat_reg;
else begin
resp_idx <= resp_idx + 1;
resp_buff[RESP_SIZE-9-resp_idx] <= cmd_dat_reg;
end
crc_bit <= cmd_dat_reg;
end
else if (counter-resp_len <= 7) begin
crc_in[(resp_len+7)-(counter)] <= cmd_dat_reg;
crc_enable <= 0;
end
else begin
crc_enable <= 0;
if (crc_in == crc_val) crc_ok <= 1;
else crc_ok <= 0;
end
counter <= counter + 1;
end
FINISH_WR: begin
if (cmd_buff[37:32] == resp_buff[125:120])
index_ok_o <= 1;
else
index_ok_o <= 0;
crc_ok_o <= crc_ok;
finish_o <= 1;
crc_enable <= 0;
crc_rst <= 1;
counter <= 0;
cmd_oe_o <= 0;
response_o <= resp_buff[119:0];
end
endcase
end
end
endmodule

View File

@ -0,0 +1,195 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE SD Card Controller IP Core ////
//// ////
//// sd_controller_wb.v ////
//// ////
//// This file is part of the WISHBONE SD Card ////
//// Controller IP Core project ////
//// http://opencores.org/project,sd_card_controller ////
//// ////
//// Description ////
//// Wishbone interface responsible for comunication with core ////
//// ////
//// Author(s): ////
//// - Marek Czerski, ma.czerski@gmail.com ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2013 Authors ////
//// ////
//// Based on original work by ////
//// Adam Edvardsson (adam.edvardsson@orsoc.se) ////
//// ////
//// Copyright (C) 2009 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 "sd_defines.v"
module sd_controller_wb(
// WISHBONE slave
wb_clk_i, wb_rst_i, wb_dat_i, wb_dat_o,
wb_adr_i, wb_sel_i, wb_we_i, wb_cyc_i, wb_stb_i, wb_ack_o,
cmd_start,
data_int_rst,
cmd_int_rst,
argument_reg,
command_reg,
response_0_reg,
response_1_reg,
response_2_reg,
response_3_reg,
software_reset_reg,
timeout_reg,
block_size_reg,
controll_setting_reg,
cmd_int_status_reg,
cmd_int_enable_reg,
clock_divider_reg,
block_count_reg,
dma_addr_reg,
data_int_status_reg,
data_int_enable_reg
);
// WISHBONE common
input wb_clk_i; // WISHBONE clock
input wb_rst_i; // WISHBONE reset
input [31:0] wb_dat_i; // WISHBONE data input
output reg [31:0] wb_dat_o; // WISHBONE data output
// WISHBONE error output
// WISHBONE slave
input [7:0] wb_adr_i; // WISHBONE address input
input [3:0] wb_sel_i; // WISHBONE byte select input
input wb_we_i; // WISHBONE write enable input
input wb_cyc_i; // WISHBONE cycle input
input wb_stb_i; // WISHBONE strobe input
output reg wb_ack_o; // WISHBONE acknowledge output
output reg cmd_start;
//Buss accessible registers
output reg [31:0] argument_reg;
output reg [`CMD_REG_SIZE-1:0] command_reg;
input wire [31:0] response_0_reg;
input wire [31:0] response_1_reg;
input wire [31:0] response_2_reg;
input wire [31:0] response_3_reg;
output reg [0:0] software_reset_reg;
output reg [15:0] timeout_reg;
output reg [`BLKSIZE_W-1:0] block_size_reg;
output reg [15:0] controll_setting_reg;
input wire [`INT_CMD_SIZE-1:0] cmd_int_status_reg;
output reg [`INT_CMD_SIZE-1:0] cmd_int_enable_reg;
output reg [7:0] clock_divider_reg;
input wire [`INT_DATA_SIZE-1:0] data_int_status_reg;
output reg [`INT_DATA_SIZE-1:0] data_int_enable_reg;
//Register Controll
output reg data_int_rst;
output reg cmd_int_rst;
output reg [`BLKCNT_W-1:0]block_count_reg;
output reg [31:0] dma_addr_reg;
parameter voltage_controll_reg = `SUPPLY_VOLTAGE_mV;
parameter capabilies_reg = 16'b0000_0000_0000_0000;
always @(posedge wb_clk_i or posedge wb_rst_i)
begin
if (wb_rst_i)begin
argument_reg <= 0;
command_reg <= 0;
software_reset_reg <= 0;
timeout_reg <= 0;
block_size_reg <= `RESET_BLOCK_SIZE;
controll_setting_reg <= 0;
cmd_int_enable_reg <= 0;
clock_divider_reg <= `RESET_CLK_DIV;
wb_ack_o <= 0;
cmd_start <= 0;
data_int_rst <= 0;
data_int_enable_reg <= 0;
cmd_int_rst <= 0;
block_count_reg <= 0;
dma_addr_reg <= 0;
end
else
begin
cmd_start <= 1'b0;
data_int_rst <= 0;
cmd_int_rst <= 0;
if ((wb_stb_i & wb_cyc_i) || wb_ack_o)begin
if (wb_we_i) begin
case (wb_adr_i)
`argument: begin
argument_reg <= wb_dat_i;
cmd_start <= 1'b1;
end
`command: command_reg <= wb_dat_i[`CMD_REG_SIZE-1:0];
`reset: software_reset_reg <= wb_dat_i[0];
`timeout: timeout_reg <= wb_dat_i[15:0];
`blksize: block_size_reg <= wb_dat_i[`BLKSIZE_W-1:0];
`controller: controll_setting_reg <= wb_dat_i[15:0];
`cmd_iser: cmd_int_enable_reg <= wb_dat_i[4:0];
`cmd_isr: cmd_int_rst <= 1;
`clock_d: clock_divider_reg <= wb_dat_i[7:0];
`data_isr: data_int_rst <= 1;
`data_iser: data_int_enable_reg <= wb_dat_i[`INT_DATA_SIZE-1:0];
`dst_src_addr: dma_addr_reg <= wb_dat_i;
`blkcnt: block_count_reg <= wb_dat_i[`BLKCNT_W-1:0];
endcase
end
wb_ack_o <= wb_cyc_i & wb_stb_i & ~wb_ack_o;
end
end
end
always @(posedge wb_clk_i or posedge wb_rst_i)begin
if (wb_rst_i == 1)
wb_dat_o <= 0;
else
if (wb_stb_i & wb_cyc_i) begin //CS
case (wb_adr_i)
`argument: wb_dat_o <= argument_reg;
`command: wb_dat_o <= command_reg;
`resp0: wb_dat_o <= response_0_reg;
`resp1: wb_dat_o <= response_1_reg;
`resp2: wb_dat_o <= response_2_reg;
`resp3: wb_dat_o <= response_3_reg;
`controller: wb_dat_o <= controll_setting_reg;
`blksize: wb_dat_o <= block_size_reg;
`voltage: wb_dat_o <= voltage_controll_reg;
`reset: wb_dat_o <= software_reset_reg;
`timeout: wb_dat_o <= timeout_reg;
`cmd_isr: wb_dat_o <= cmd_int_status_reg;
`cmd_iser: wb_dat_o <= cmd_int_enable_reg;
`clock_d: wb_dat_o <= clock_divider_reg;
`capa: wb_dat_o <= capabilies_reg;
`data_isr: wb_dat_o <= data_int_status_reg;
`blkcnt: wb_dat_o <= block_count_reg;
`data_iser: wb_dat_o <= data_int_enable_reg;
`dst_src_addr: wb_dat_o <= dma_addr_reg;
endcase
end
end
endmodule

View File

@ -0,0 +1,43 @@
// ==========================================================================
// CRC Generation Unit - Linear Feedback Shift Register implementation
// (c) Kay Gorontzi, GHSi.de, distributed under the terms of LGPL
// ==========================================================================
module sd_crc_16(BITVAL, ENABLE, BITSTRB, CLEAR, CRC);
input BITVAL; // Next input bit
input ENABLE; // Enable calculation
input BITSTRB; // Current bit valid (Clock)
input CLEAR; // Init CRC value
output [15:0] CRC; // Current output CRC value
reg [15:0] CRC; // We need output registers
wire inv;
assign inv = BITVAL ^ CRC[15]; // XOR required?
always @(posedge BITSTRB or posedge CLEAR) begin
if (CLEAR) begin
CRC <= 0; // Init before calculation
end
else begin
if (ENABLE == 1) begin
CRC[15] <= CRC[14];
CRC[14] <= CRC[13];
CRC[13] <= CRC[12];
CRC[12] <= CRC[11] ^ inv;
CRC[11] <= CRC[10];
CRC[10] <= CRC[9];
CRC[9] <= CRC[8];
CRC[8] <= CRC[7];
CRC[7] <= CRC[6];
CRC[6] <= CRC[5];
CRC[5] <= CRC[4] ^ inv;
CRC[4] <= CRC[3];
CRC[3] <= CRC[2];
CRC[2] <= CRC[1];
CRC[1] <= CRC[0];
CRC[0] <= inv;
end
end
end
endmodule

View File

@ -0,0 +1,34 @@
// ==========================================================================
// CRC Generation Unit - Linear Feedback Shift Register implementation
// (c) Kay Gorontzi, GHSi.de, distributed under the terms of LGPL
// ==========================================================================
module sd_crc_7(BITVAL, ENABLE, BITSTRB, CLEAR, CRC);
input BITVAL; // Next input bit
input ENABLE; // Enable calculation
input BITSTRB; // Current bit valid (Clock)
input CLEAR; // Init CRC value
output [6:0] CRC; // Current output CRC value
reg [6:0] CRC; // We need output registers
wire inv;
assign inv = BITVAL ^ CRC[6]; // XOR required?
always @(posedge BITSTRB or posedge CLEAR) begin
if (CLEAR) begin
CRC <= 0; // Init before calculation
end
else begin
if (ENABLE == 1) begin
CRC[6] <= CRC[5];
CRC[5] <= CRC[4];
CRC[4] <= CRC[3];
CRC[3] <= CRC[2] ^ inv;
CRC[2] <= CRC[1];
CRC[1] <= CRC[0];
CRC[0] <= inv;
end
end
end
endmodule

Some files were not shown because too many files have changed in this diff Show More