mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			77 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			77 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| pattern ql_dsp_macc
 | |
| // Rough sketch: (mux is optional)
 | |
| //
 | |
| //               /-----------------------\
 | |
| //               |                       |
 | |
| //              \ /                      |
 | |
| //   mul ----> add -----> mux -----> ff -+---->
 | |
| //         |              /\
 | |
| //         |              |
 | |
| //          --------------
 | |
| 
 | |
| state <IdString> add_ba
 | |
| state <IdString> mux_ab
 | |
| 
 | |
| // Is the output taken from before or after the FF?
 | |
| state <bool> output_registered
 | |
| 
 | |
| // Is there a mux in the pattern?
 | |
| state <bool> mux_in_pattern
 | |
| 
 | |
| code mux_in_pattern
 | |
|     mux_in_pattern = false;
 | |
|     branch;
 | |
|     mux_in_pattern = true;
 | |
| endcode
 | |
| 
 | |
| // The multiplier is at the center of our pattern
 | |
| match mul
 | |
|     select mul->type.in($mul)
 | |
|     // It has either two or three consumers depending on whether there's a mux
 | |
|     // in the pattern or not
 | |
|     select nusers(port(mul, \Y)) <= 3
 | |
|     filter nusers(port(mul, \Y)) == (mux_in_pattern ? 3 : 2)
 | |
| endmatch
 | |
| 
 | |
| code output_registered
 | |
|     output_registered = false;
 | |
|     branch;
 | |
|     output_registered = true;
 | |
| endcode
 | |
| 
 | |
| match add
 | |
|     select add->type.in($add, $sub)
 | |
|     choice <IdString> AB {\A, \B}
 | |
|     define <IdString> BA (AB == \A ? \B : \A)
 | |
|     // One input to the adder is fed by the multiplier
 | |
|     index <SigSpec> port(add, AB) === port(mul, \Y)
 | |
|     // Save the other input port, it needs to be fed by the flip-flop
 | |
|     set add_ba BA
 | |
|     // Adder has either two or three consumers; it will have three consumers
 | |
|     // IFF there's no mux in the pattern and the multiplier-accumulator result
 | |
|     // is taken unregistered
 | |
|     filter nusers(port(add, \Y)) == (!mux_in_pattern && !output_registered ? 3 : 2)
 | |
| endmatch
 | |
| 
 | |
| match mux
 | |
|     if mux_in_pattern
 | |
|     select mux->type.in($mux)
 | |
|     choice <IdString> AB {\A, \B}
 | |
|     define <IdString> BA (AB == \A ? \B : \A)
 | |
|     index <SigSpec> port(mux, AB) === port(mul, \Y)
 | |
|     index <SigSpec> port(mux, BA) === port(add, \Y)
 | |
|     filter nusers(port(mux, \Y)) == (output_registered ? 2 : 3)
 | |
|     set mux_ab AB
 | |
| endmatch
 | |
| 
 | |
| match ff
 | |
|     select ff->type.in($dff, $adff, $dffe, $adffe)
 | |
|     select param(ff, \CLK_POLARITY).as_bool()
 | |
|     index <SigSpec> port(ff, \D) === mux_in_pattern ? port(mux, \Y) : port(add, \Y);
 | |
|     index <SigSpec> port(ff, \Q) === port(add, add_ba)
 | |
|     filter nusers(port(ff, \Q)) == (output_registered ? 3 : 2)
 | |
| endmatch
 | |
| 
 | |
| code
 | |
|     accept;
 | |
| endcode
 |