Sadly, my knowledge of circuits is quite limited, so I will try to answer the question algorithmically. If You go through your bits from most to least significant, You could reconstruct Your number as follows:
number = 0
foreach bit in [a[n-1], a[n-2], ..., a[n]] do
number = 2*number + bit
end foreach
return number
This can be done by a simple shift followed by an increment per iteration. But, of course, the number might be huge and we are only interested in the remainder. So instead we can can use modular arithmetic to only build the remainder:
remainder = 0
foreach bit in [a[n-1], a[n-2], ..., a[n]] do
remainder = (2*number + bit) mod k
end foreach
return remainder
Since 2*remainder + bit <= 2*(k-1) + 1
we can replace the modulo operator by a comparison, conditonally followed by a subtraction:
remainder = 0
foreach bit in [a[n-1], a[n-2], ..., a[n]] do
remainder = 2*number + bit
if remainder >= k then
remainder = remainder - k
end if
end foreach
return remainder
And there You have it. For each bit in $a$ you would need:
- 1 Shift
- 1 Increment (e.g. via chain of "flip-flops")
- 1 Comparison
- 1 Conditional Subtraction (e.g. via Ripple-Carry-Adder using two's complement of $k$)
That should take around $\mathcal{O}\left(\left\lceil\log_2\left(2k-1\right)\right\rceil\right)$ logic gates per bit in $a$.
In practice there are of course much more efficient solutions than that. For division algorithms, I can recommend the book Modern Computer Arithmetic. Everything You learn there should be applicable to circuits as well, but You will have to think much more parallel in circuit design, I presume.
For reference, here is a Scala implementation of the algorithm:
def mod( n: BigInt, k: Int ): Int =
require(n >= 0)
require(k > 1)
var rem = 0L
var i = n.bitLength
while i > 0 do
i -= 1
rem *= 2
if n.testBit(i) then rem += 1
if rem >= k then rem -= k
end while
assert(rem >= 0)
assert(rem < k)
return rem.toInt
end mod