o enunciado assusta, mas nao eh realmente nada complexo... na real, o proprio enunciado dah uma pista forte sobre a solucao: o cara indica que o valor entra serialmente com o LSB primeiro e que o resultado sai serialmente. isso eh uma dica forte de que talvez o circuito opere bit a bit.
bom, outra pista eh que o resultado eh 3*N:
R = 3*N = N+N*2 = N + N<<1
juntando isso com o fato de que o numero estah entrando serialmente pelo LSB primeiro, vc tem uma combinacao magica: a soma se faz pelo LSB primeiro. mais ainda, a entrada serial implica em um shift-register. e melhor ainda, o resultado pode ser enviado imediatamente via shift-register tambem. bom, disso para o codigo realmente, precisa de alguma imaginacao para se materializar:
- Código: Selecionar todos
module mul3ser(input clk,input res,input in, output out);
reg outff;
reg carryff;
wire carry;
assign { carry, out } = outff+in+carryff; // 2
always@(posedge clk)
begin
outff <= res ? 0 : in; // 1
carryff <= res ? 0 : carry; // 3
end
endmodule
bom, coloquei numeros comentados para referencias... o principal eh ali no posedge em 1: outff eh um flip-flop que armazena o valor de in a cada clock. em essencia, se vc visualizar in e outff, vai ver que outff eh como se fosse in shiftado de 1, quer dizer, eh a parte N<<1. daih tem um assign em 2 que soma ouff (o nosso N<<1) com N, para perfazer 3*N. inicialmente eh fiz apenas a soma simples R = N<<1 + N e quase funcionou... para alguns numeros falhava e me ocorreu que a soma gera um carry! felizmente o carry se propaga corretamente fazendo a soma pelo LSB, pelo que eu fiz a soma CR = N<<1 + N + C, de modo que o carry eh salvo em carryff em 3 e se propaga para o proximo clock. e isso eh todo o codigo! :3 hahaha
claro, o cara pede apenas em funcao de flip-flops e porta NAND... os flip-flops estah lah (reg), inclusive o suporte a reset faz parte dos flip-flops, mas as portas NAND nao. mas o circuito eh realmente simples e vc precisaria escrever apenas as somas na forma de portas NAND.
o testbench do negocio ficou um pouco maior:
- Código: Selecionar todos
module mul3ser_test;
reg clk = 0;
reg [3:0] res = -1;
always #10 clk = !clk;
reg [31:0] inff;
reg [31:0] outff;
reg [31:0] result;
reg [4:0] ptr;
wire out;
always@(posedge clk)
begin
if(res)
begin
result <= 0;
outff <= 0;
ptr <= 0;
inff <= 0;
res <= res-1;
end
else
begin
if(ptr==31)
begin
result <= outff;
inff <= inff+1;
if(outff!=inff*3)
begin
$display("oh crap! failed in=%d*3 != out=%d",inff,outff);
$stop;
end
else
if(inff==65536)
begin
$display("testbench ok between 0 and 65536! o/");
$stop;
end
end
outff[ptr] <= out;
ptr <= ptr+1;
end
end
mul3ser mul3ser(clk,|res,inff[ptr],out);
endmodule
como supostamente os bits de entrada sao arbitrarios, fiz um mecanismo fixo com 32 bits, mas testo apenas ateh 65536. qualquer quantidade daria conta, mas 32 bits me pareceu um valor bom. eu shifto esses 32 bits pelo LSB primeiro e vou coletando os resultados. quando chego no ultimo bit, comparo com o esperado e incremento para o proximo valor de teste. cuidado para nao escorregar no meu reset ali: eu costumo fazer reset dessa forma, um contador inicializado como -1 (todos os bits 1, de fato) e decremento ele clock a clock ateh atingir zero, liberando a operacao. podia ser ateh mais curto, mas eu gosto de identificar bem quando o circuito estah em reset ou nao. para o contador de reset propagar como reset, eu faco um |res, de modo que eh 1 se res!=0 e 0 se res==0. o resto acho que esta compreensivel.
o testbench para se falhar em algum ponto e indica o ponto, do contrario vai ateh o fim e termina feliz. obviamente eu jah debuguei o codigo: a falha inicial foi que esqueci o carry. corrigido isso, foi ateh o fim.
- Código: Selecionar todos
This is a Lite version of ISE Simulator(ISim).
Simulator is doing circuit initialization process.
Finished circuit initialization process.
restart
run all
Simulator is doing circuit initialization process.
Finished circuit initialization process.
testbench ok between 0 and 65536! o/
Stopped at time : 41.943970 ms : File "Z:/Users/marcelo/Documents/Verilog/cache/asm51.v" Line 82
Stopped at line=82 file name=Z:/Users/marcelo/Documents/Verilog/cache/asm51.v
%
normalmente eu nao curto muito ajudar o povo com lista de exercicios, mas o enunciado me chamou a atencao e acabei caindo na tentacao de testar para ver se era assim simples mesmo! :v
chrdcv escreveu:Pessoal,
Não conseguí resolver o exercício abaixo e recorro a lista para esclarecimentos (esse exercício o Prof. tirou da "cartola" de um livro da década de 80 ou 90):
2.17). Design a sequential circuit that multiplies an unsigned binary number N of arbitrary length by 3. N is entered serially via input line X with its leas significant bit first. The result represent 3N emerges serially from the circuit's output line Z. Construct a state table for your circuit and give a complete logic circuit that uses D flip-flops and NAND gates only.
O problema é que não consigo sequer imaginar a FSM (máquina de estados) do circuito. O que encontrei no google mais próximo do que eu preciso foi um circuito chamado de semi-systolic multiplier, entretanto, o mesmo é mais uma espécie de circuito combinacional do que sequencial.
Agradeço a todos pela ajuda!