(提醒:此作业仅供参考学习,有缺点或问题可提出。)
大二上学期数字电路实验:更相减损术求最大公约数的Verilog实现。
问题背景:
《九章算术》中记载求两正整数最大公约数的更相减损术:“可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。”请设计一个Verilog程序实现更相减损术。
题目要求:
Finish the verilog code above using Digital Processor structure
Simulation with your own testbench
Synthesis
Diagram of structure and STD should be included
问题分析:
使用一个顶层模块和若干模块来实现计算、储存和显示等功能。
程序整体采用Von neumann structure,分为了计算部分(Datapath、Controlunit)、储存部分(RAM)、显示部分(Displayer)四个module。计算部分Controlunit采用Finiteness States Machine的运行方式,Datapath则用于实现更相减损术的具体操作。
计算部分总体概括图:
Datapath部分:
Controlunit部分:
储存部分使用IP自动生成一个8×2的RAM模块来实现。
显示部分采用7段数码管实现。
Module部分代码:
顶层模块:
`timescale 1ns / 1ps
module GCD_Top(
input clk,
input clr,
input go,
input xsig,
input ysig,
input wea,
input addra,
input [7:0] dina,
output [7:0] douta,
output [7:0] gcd,
output [6:0] a_to_g,
output [3:0] an);
wire xmsel,ymsel,eqflg,ltflg,xld,yld,gld;
reg [7:0] xin;
reg [7:0] yin;
always @ (posedge clk)
begin
if(xsig == 1)
xin <= douta;
else if(ysig == 1)
yin <= douta;
end
GCD_Datatpath U1(
.clk(clk),
.clr(clr),
.xmsel(xmsel),
.ymsel(ymsel),
.xin(xin),
.yin(yin),
.gcd(gcd),
.eqflg(eqflg),
.ltflg(ltflg),
.xld(xld),
.yld(yld),
.gld(gld));
GCD_Controlunit U2(
.clk(clk),
.clr(clr),
.go(go),
.eqflg(eqflg),
.ltflg(ltflg),
.xmsel(xmsel),
.ymsel(ymsel),
.xld(xld),
.yld(yld),
.gld(gld));
GCD_RAM U3(
.clka(clk),
.wea(wea),
.addra(addra),
.dina(dina),
.douta(douta));
GCD_Displayer U4(
.clk(clk),
.clr(clr),
.x(gcd),
.a_to_g(a_to_g),
.an(an));
endmodule
Datapath模块:
`timescale 1ns / 1ps
module GCD_Datatpath(
input clk,
input clr,
input xmsel,
input ymsel,
input xld,
input yld,
input gld,
input [7:0] xin,
input [7:0] yin,
output [7:0] gcd,
output reg eqflg,
output reg ltflg);
wire [7:0] xmy, ymx;
reg [7:0] x, y, xl, yl, gcd_out;
assign xmy = x - y;
assign ymx = y - x;
always @(*) begin //eqf lag
if (x == y)
eqflg <= 1'b1;
else
eqflg <= 1'b0;
end
always @(*) begin //ltflag
if (x < y)
ltflg <= 1'b1;
else if(x > y)
ltflg <= 1'b0;
end
always @(*) begin //mux_x;
if (xmsel == 1)
xl <= xin;
else if(ltflg == 0)
xl <= xmy;
end
always @(*) begin //muxy;
if (ymsel == 1)
yl <= yin;
else if(ltflg == 1)
yl <= ymx;
end
always@ (posedge clk) begin //reg_x
if (clr == 1)
x <= 0;
else if (xld == 1)
x <= xl;
end
always@ (posedge clk) begin //reg_y
if (clr == 1)
y <= 0;
else if (yld == 1)
y <= yl;
end
always@ (posedge clk) begin //reggcd
if (clr == 1)
gcd_out <= 0;
else if (gld == 1)
gcd_out <= x;
end
assign gcd = gcd_out;
endmodule
Controlunit模块:
`timescale 1ns / 1ps
module GCD_Controlunit(
input clk,
input clr,
input go,
input eqflg,
input ltflg,
output reg xmsel,
output reg ymsel,
output reg xld,
output reg yld,
output reg gld);
reg [2:0] current_state,next_state;
parameter start = 3'b000;
parameter input1 = 3'b001;
parameter test1 = 3'b010;
parameter test2 = 3'b011;
parameter update1 = 3'b100;
parameter update2 = 3'b110;
parameter done = 3'b111;//state register
always @(posedge clk) begin
if (clr == 1)
current_state <= start;
else
current_state <= next_state;
end
//next sate logic
always @(*) begin
case(current_state)
start:
if(go == 1)
next_state = input1;
else
next_state = start;
input1:
next_state = test1;
test1:
if(eqflg == 1)
next_state = done;
else
next_state = test2;
test2:
if(ltflg == 1)
next_state = update1;
else
next_state = update2;
update1:
next_state = test1;
update2:
next_state = test1;
done:
next_state = start;
default:
next_state = start;
endcase
end
//output logic
always @(*)begin
if (clr == 1)
{xmsel,ymsel,xld,yld,gld} = 5'b00000;
else
case(current_state)
start:
{xmsel,ymsel,xld,yld,gld} = 5'b00000;
input1:
{xmsel,ymsel,xld,yld,gld} = 5'b11110;
update1:
{xmsel,ymsel,xld,yld,gld} = 5'b00010;
update2:
{xmsel,ymsel,xld,yld,gld} = 5'b00100;
done:
{xmsel,ymsel,xld,yld,gld} = 5'b00001;
default:
{xmsel,ymsel,xld,yld,gld} = 5'b00000;
endcase
end
endmodule
RAM模块:(偷懒用IP生成的,照搬代码运行会出错,具体操作自行查阅)
`timescale 1ns / 1ps
module GCD_RAM(
input wire clka,
input wire wea,
input wire addra,
input wire [7:0] dina,
output wire [7:0] douta);
blk_mem_gen_0 your_instance_name (
.clka(clka),
.wea(wea),
.addra(addra),
.dina(dina),
.douta(douta)
);
endmodule
显示模块:
`timescale 1ns / 1ps
module GCD_Displayer(
input clk,
input clr,
input [15: 0] x,
output reg [6: 0] a_to_g,
output reg [3: 0] an
);
wire [1: 0] s;
reg [3: 0] digit;
reg [19: 0] clkdiv;
assign s = clkdiv[19:18];
always @(posedge clk)
case(s)
0: digit = x[3: 0];
1: digit = x[7: 4];
2: digit = x[11: 8];
3: digit = x[15: 12];
default: digit = x[3: 0];
endcase
always @(posedge clk) begin
case(digit)
0: a_to_g = 7'b1111_110; // 1
1: a_to_g = 7'b0110_000; // 1
2: a_to_g = 7'b1101_101; // 2
3: a_to_g = 7'b1111_001; // 3
4: a_to_g = 7'b0110_011; // 4
5: a_to_g = 7'b1011_011; // 5
6: a_to_g = 7'b1011_111; // 6
7: a_to_g = 7'b1110_000; // 7
8: a_to_g = 7'b1111_111; // 8
9: a_to_g = 7'b1111_011; // 9
10: a_to_g = 7'b1110_111; // A
11: a_to_g = 7'b0011_111; // b
12: a_to_g = 7'b0001_101; // c
13: a_to_g = 7'b0111_101; // d
14: a_to_g = 7'b1001_111; // E
15: a_to_g = 7'b1000_111; // F
default: a_to_g = 7'b1111_110;
endcase
end
always @(posedge clk) begin
an = 4'b0000;
an[s] = 1'b1;
end
always @(posedge clk) begin
if (clr) begin
clkdiv <= 0;
end
else begin
clkdiv <= clkdiv + 1;
end
end
endmodule
Testbench:
`timescale 1ns / 1ps
module TB_GCD();
reg clk,clr,go,wea,addra;
reg [7:0] dina;
wire [7:0] gcd;
wire [7:0] douta;
reg xsig,ysig;
GCD_Top uut(
.clk(clk),
.clr(clr),
.go(go),
.gcd(gcd),
.xsig(xsig),
.ysig(ysig),
.wea(wea),
.addra(addra),
.dina(dina),
.douta(douta)
);
always begin
#10 clk = ~clk;
end
initial begin
clk = 1'b1;
clr = 1'b1;
go = 1'b0;
xsig = 1'b0;
ysig = 1'b0;
dina = 8'b00000000;
wea = 1'b0;
addra = 1'b0;
#30 clr = 1'b0;
#30 wea = 1'b1;
dina = 8'b00001111;
#30 wea = 1'b0;
#30 xsig = 1'b1;
#30 xsig = 1'b0;
#30 wea = 1'b1;
dina = 8'b01011101;
addra = 1'b1;
#30 wea = 1'b0;
#30 ysig = 1'b1;
#30 ysig = 1'b0;
#30 go = 1'b1;
end
endmodule
管脚分配(I/O Ports)文件:
开发板型号:Xilinx Artix7 EGO1(如封面图)
set_property IOSTANDARD LVCMOS33 [get_ports {dina[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dina[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dina[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dina[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dina[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dina[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dina[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dina[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {douta[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {douta[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {douta[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {douta[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {douta[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {douta[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {douta[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {douta[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports addra]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports wea]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {an[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {an[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {an[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {an[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gcd[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gcd[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gcd[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gcd[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gcd[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gcd[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gcd[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gcd[0]}]
set_property PACKAGE_PIN P17 [get_ports clk]
set_property PACKAGE_PIN R15 [get_ports clr]
set_property PACKAGE_PIN U3 [get_ports go]
set_property PACKAGE_PIN V2 [get_ports wea]
set_property PACKAGE_PIN V5 [get_ports xsig]
set_property PACKAGE_PIN V4 [get_ports ysig]
set_property PACKAGE_PIN P5 [get_ports {dina[7]}]
set_property PACKAGE_PIN P4 [get_ports {dina[6]}]
set_property PACKAGE_PIN P3 [get_ports {dina[5]}]
set_property PACKAGE_PIN P2 [get_ports {dina[4]}]
set_property PACKAGE_PIN R2 [get_ports {dina[3]}]
set_property PACKAGE_PIN M4 [get_ports {dina[2]}]
set_property PACKAGE_PIN N4 [get_ports {dina[1]}]
set_property PACKAGE_PIN R1 [get_ports {dina[0]}]
set_property PACKAGE_PIN F6 [get_ports {douta[7]}]
set_property PACKAGE_PIN G4 [get_ports {douta[6]}]
set_property PACKAGE_PIN G3 [get_ports {douta[5]}]
set_property PACKAGE_PIN J4 [get_ports {douta[4]}]
set_property PACKAGE_PIN H4 [get_ports {douta[3]}]
set_property PACKAGE_PIN J3 [get_ports {douta[2]}]
set_property PACKAGE_PIN J2 [get_ports {douta[1]}]
set_property PACKAGE_PIN K2 [get_ports {douta[0]}]
set_property PACKAGE_PIN K1 [get_ports {gcd[7]}]
set_property PACKAGE_PIN H6 [get_ports {gcd[6]}]
set_property PACKAGE_PIN H5 [get_ports {gcd[5]}]
set_property PACKAGE_PIN J5 [get_ports {gcd[4]}]
set_property PACKAGE_PIN K6 [get_ports {gcd[3]}]
set_property PACKAGE_PIN L1 [get_ports {gcd[2]}]
set_property PACKAGE_PIN M1 [get_ports {gcd[1]}]
set_property PACKAGE_PIN K3 [get_ports {gcd[0]}]
set_property PACKAGE_PIN T5 [get_ports addra]
set_property PACKAGE_PIN D4 [get_ports {a_to_g[6]}]
set_property PACKAGE_PIN E3 [get_ports {a_to_g[5]}]
set_property PACKAGE_PIN D3 [get_ports {a_to_g[4]}]
set_property PACKAGE_PIN F4 [get_ports {a_to_g[3]}]
set_property PACKAGE_PIN F3 [get_ports {a_to_g[2]}]
set_property PACKAGE_PIN E2 [get_ports {a_to_g[1]}]
set_property PACKAGE_PIN D2 [get_ports {a_to_g[0]}]
set_property PACKAGE_PIN G1 [get_ports {an[3]}]
set_property PACKAGE_PIN F1 [get_ports {an[2]}]
set_property PACKAGE_PIN E1 [get_ports {an[1]}]
set_property PACKAGE_PIN G6 [get_ports {an[0]}]
运行结果示例:
Synthesis RTL
Testbench:
仿真通过。
Bord Verification:
板级验证通过。
Thanks for your reading.