O eso pensaba yo.
Me da esta tarde por hacer unas pruebas y he visto que es tan trivial como la multiplicación binaria. Para comprobarlo del todo, he escrito un módulo en Verilog que divide dos números de 32 bits sin signo (división entera), devolviendo el cociente entero y el resto.
Parto de un algoritmo completamente "naive" y no pretende ser rápido ni nada de eso. Tarda N+1 ciclos de reloj en proporcionar un resultado final, donde N es el número de bits que tengan los operandos. Tampoco detecto división por 0 (si divides entre 0, lo único que pasa es que obtienes un resultado erróneo)
Lo he escrito como siempre, usando EDA Playground como herramienta para hacer mis "bocetos" en Verilog. Está el módulo y un pequeño testbench para probar valores que pongas en el código.
https://www.edaplayground.com/x/5YDu
Código: Seleccionar todo
module division (
input wire clk,
input wire [31:0] dividendo,
input wire [31:0] divisor,
output reg [31:0] cociente,
output reg [31:0] resto,
input wire start,
output wire busy
);
reg [33:0] contador = 34'h200000000; // one hot.
assign busy = ~contador[33]; // cuando llega al ultimo estado, busy = 0 y terminamos
wire no_desplaza_resto = contador[32]; // penultimo estado. Se actualiza el cociente, pero no el resto
reg [31:0] rdivisor;
reg [31:0] proximo_resto;
reg [63:0] proximo_restocociente;
always @(posedge clk) begin
if (busy == 1'b0 && start == 1'b1) begin
cociente <= dividendo; // el dividendo se va desplazando a la izquierda, y el cociente entra por la derecha
rdivisor <= divisor; // guardamos el divisor
resto <= 32'h00000000; // el resto es el dividendo parcial que en cada ciclo es comparado con el divisor
contador <= 34'h000000001; // contador one-hot. Se desplaza a la izquierda
end
else if (busy == 1'b1) begin
contador <= {contador[32:0], contador[33]}; // contamos un estado
{resto, cociente} <= proximo_restocociente; // asignamos el cociente y resto
end
end
always @* begin
proximo_resto = resto - divisor; // proximo dividendo parcial. Solo se usa si el actual es >= divisor
if (resto < rdivisor) begin // si el dividendo parcial actual es menor que el divisor
if (no_desplaza_resto == 1'b0) // y hay que desplazar el resto
proximo_restocociente = {resto[30:0], cociente, 1'b0}; // simplemente desplazamos cociente y resto a la izquierda
else // y por la derecha entra un 0
proximo_restocociente = {resto, cociente[30:0], 1'b0}; // si no hay que desplazar el resto, entonces splo se
end // desplaza el cociente
else begin // si el dividendo parcial actual es mayor que el divisor
if (no_desplaza_resto == 1'b0) // y hay que desplazar el resto
proximo_restocociente = {proximo_resto[30:0], cociente, 1'b1}; // entonces se hace todo el desplazamiento, pero
else // usando proximo_resto en lugar de resto
proximo_restocociente = {proximo_resto, cociente[30:0], 1'b1}; // si no se desplaza el resto, pues solo se hace
end // en el cociente
end
endmodule