{-# OPTIONS --safe --cubical #-}
module Spartan6.Primitive.DSP48A1 where
open import Spartan6.Prelude
open import Spartan6.Evidence
ug389-v1-2 : PinnedSource
ug389-v1-2 =
pinSource UG389 (revision "v1.2" (just "2014-05-29"))
ug615-v14-7 : PinnedSource
ug615-v14-7 =
pinSource UG615 (revision "v14.7" (just "2013-10-02"))
dsp48a1MultiplyLocator : SourceLocator
dsp48a1MultiplyLocator =
locate ug389-v1-2 "Two's Complement Multiplier and M Output Port"
"printed pages 19-21; Figure 1-10 and Tables 1-4 through 1-7; pipeline attributes on pages 12-13"
dsp48a1PrimitiveLocator : SourceLocator
dsp48a1PrimitiveLocator =
locate ug615-v14-7 "DSP48A1"
"printed pages 92-95: introduction, ports, OPMODE, and attributes"
dsp48a1MultiplyTrace : RuleTraceability
dsp48a1MultiplyTrace =
traceRule "primitive.DSP48A1.unsigned17-combinational-M"
officialDocumentation
(just dsp48a1MultiplyLocator)
partiallySupported
guaranteed
"Only zero-MSB unsigned operands and the unregistered direct 36-bit M output are executable; the full DSP48A1 is not modelled. UG615 v14.7 pages 92-95 provide the primitive-level cross-check."
record OPMODE : Type₀ where
constructor opmodeBits
field
opmode7 : Bit
opmode6 : Bit
opmode5 : Bit
opmode4 : Bit
opmode3 : Bit
opmode2 : Bit
opmode1 : Bit
opmode0 : Bit
open OPMODE public
multiplyOnlyOPMODE : OPMODE
multiplyOnlyOPMODE =
opmodeBits low low low low low low low high
data PipelineSelection : Type₀ where
bypassed : PipelineSelection
registered : PipelineSelection
record MultiplyOnlyAttributes : Type₀ where
constructor multiplyAttributes
field
a0reg : PipelineSelection
a1reg : PipelineSelection
b0reg : PipelineSelection
b1reg : PipelineSelection
mreg : PipelineSelection
opmodereg : PipelineSelection
open MultiplyOnlyAttributes public
combinationalMultiplyAttributes : MultiplyOnlyAttributes
combinationalMultiplyAttributes =
multiplyAttributes bypassed bypassed bypassed bypassed bypassed bypassed
UnsignedOperand : Type₀
UnsignedOperand = Word 17
DSPInput : Type₀
DSPInput = Word 18
MOutput : Type₀
MOutput = Word 36
appendWord : ∀ {m n} → Word m → Word n → Word (m + n)
appendWord [] suffix = suffix
appendWord (bit ∷ bits) suffix = bit ∷ appendWord bits suffix
toDSPInput : UnsignedOperand → DSPInput
toDSPInput magnitude = appendWord magnitude (low ∷ [])
widenDSPInput : DSPInput → MOutput
widenDSPInput input = appendWord input (replicate low)
sumBit : Bit → Bit → Bit → Bit
sumBit left right carry = (left ⊕ right) ⊕ carry
carryBit : Bit → Bit → Bit → Bit
carryBit left right carry =
(left and right) or (carry and (left ⊕ right))
addWithCarry : ∀ {width}
→ Bit → Word width → Word width → Word width × Bit
addWithCarry carry [] [] = [] , carry
addWithCarry carry (left ∷ lefts) (right ∷ rights)
with addWithCarry (carryBit left right carry) lefts rights
... | result , carry-out =
(sumBit left right carry ∷ result) , carry-out
addModulo : ∀ {width} → Word width → Word width → Word width
addModulo left right = fst (addWithCarry low left right)
dropLast : ∀ {width} → Word (suc width) → Word width
dropLast {zero} (bit ∷ []) = []
dropLast {suc width} (bit ∷ bits) = bit ∷ dropLast bits
shiftLeftModulo : ∀ {width} → Word width → Word width
shiftLeftModulo {zero} [] = []
shiftLeftModulo {suc width} word = low ∷ dropLast word
gateWord : ∀ {width} → Bit → Word width → Word width
gateWord select = map (λ bit → select and bit)
multiplyAccumulate : ∀ {steps width}
→ Word steps → Word width → Word width → Word width
multiplyAccumulate [] multiplier accumulator = accumulator
multiplyAccumulate (bit ∷ bits) multiplicand accumulator =
multiplyAccumulate bits
(shiftLeftModulo multiplicand)
(addModulo accumulator (gateWord bit multiplicand))
multiplyModulo : ∀ {width} → Word width → Word width → Word width
multiplyModulo left right =
multiplyAccumulate right left (replicate low)
multiplyM : UnsignedOperand → UnsignedOperand → MOutput
multiplyM left right =
multiplyAccumulate
(toDSPInput right)
(widenDSPInput (toDSPInput left))
(replicate low)
zero17 one17 two17 three17 : UnsignedOperand
zero17 = replicate low
one17 = high ∷ replicate low
two17 = low ∷ high ∷ replicate low
three17 = high ∷ high ∷ replicate low
zero4 one4 two4 three4 six4 : Word 4
zero4 = low ∷ low ∷ low ∷ low ∷ []
one4 = high ∷ low ∷ low ∷ low ∷ []
two4 = low ∷ high ∷ low ∷ low ∷ []
three4 = high ∷ high ∷ low ∷ low ∷ []
six4 = low ∷ high ∷ high ∷ low ∷ []
unsigned-port-is-zero-extended :
toDSPInput three17
≡ high ∷ high ∷ low ∷ low ∷ low ∷ low ∷ low ∷ low ∷ low
∷ low ∷ low ∷ low ∷ low ∷ low ∷ low ∷ low ∷ low ∷ low ∷ []
unsigned-port-is-zero-extended = refl
one-plus-one-mod-4 : addModulo one4 one4 ≡ two4
one-plus-one-mod-4 = refl
one-shifted-left-mod-4 : shiftLeftModulo one4 ≡ two4
one-shifted-left-mod-4 = refl
two-times-three-mod-4 : multiplyModulo two4 three4 ≡ six4
two-times-three-mod-4 = refl
fifteen-times-two-wraps-mod-4 :
multiplyModulo
(high ∷ high ∷ high ∷ high ∷ [])
two4
≡ low ∷ high ∷ high ∷ high ∷ []
fifteen-times-two-wraps-mod-4 = refl
multiply-mode-bypasses-pre-adder : opmode4 multiplyOnlyOPMODE ≡ low
multiply-mode-bypasses-pre-adder = refl
multiply-mode-selects-zero-Z :
(opmode3 multiplyOnlyOPMODE ≡ low)
× (opmode2 multiplyOnlyOPMODE ≡ low)
multiply-mode-selects-zero-Z = refl , refl
multiply-mode-selects-multiplier-X :
(opmode1 multiplyOnlyOPMODE ≡ low)
× (opmode0 multiplyOnlyOPMODE ≡ high)
multiply-mode-selects-multiplier-X = refl , refl