总结:
1. 定义各个模块:
存储器部分:指令存储器和数据存储器,利用Xilinx生成,均采用板载时钟作为时钟输入。
寄存器:包括PC和寄存器堆,均采用按键时钟作为时钟输入。注意PC寄存器的写入控制(按键按下时写入)以及+4操作。
运算器:ALU模块(需要根据控制信号进行加法输入)和加法器,
控制器:control模块和ALUControl模块(就是一个组合电路)。
选择器:包括各种多路选择器以及对应的控制信号。
显示器:负责显示数字,要点在于将32位二进制转化成8个十六进制并利用分时复用显示出来,分时的信号是将板载时钟频率降低得到。
2. 在top模块中综合(生成各个模块的实例),相当于产生了真正的组件。
3. 利用线性变量(wire类型)作为输入输出,相当于把各个组件用线连接起来。
问题:
1. 时钟信号
clk:对应的是按键。
按键clk:用于控制PC寄存器、寄存器堆、
disp_clk,即板载时钟t9。
用于控制数码管的显示、指令存储器、数据存储器。
2. PC不需要初始化,因为rst(reset)信号。
3.unexpected token
语法问题,括号,全角、半角问题。
4. 单周期中,PC以及地址的运算用的是单独的ALU
5. project clean up:解决找不到数据存储器模块的问题
6.
http://stackoverflow.com/questions/7589443/xilinx-error-place-1018-message
NET "clk" CLOCK_DEDICATED_ROUTE = FALSE;
7.
在xilinx12.4版本中,使用block memory generator代替10.1中的Single Port Block Memory
instr_block_instr_block.coe为什么有十一条指令?
MEMORY_INITIALIZATION_RADIX=2;
MEMORY_INITIALIZATION_VECTOR=
100011 00000 00001 00000 00000 000000,
10001100000000100000000000000100,
10001100000001000000000000000001,
000000 00001 00010 00011 00000 100000,
00000000011000100001000000100000,
00000000011000010001100000100000,
00010000011001000000000000000001,
00001000000000000000000000000100,
10101100000000100000000000000010,
000000 00001 00100 00110 00000 101010,//slt #4 #
000000 00100 00001 00110 00000 101010,//slt
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 14:27:50 04/16/2013
// Design Name:
// Module Name: top
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`timescale 1 ps / 1 ps
//顶层模块
module top(
clk, rst,
disp_sel, disp_clk,
o_a, o_b, o_c, o_d, o_e, o_f, o_g, o_dp,
o_sel,
o_instr);
input clk, rst, disp_clk;//disp_clk对应板载时钟,用来控制寄存器的写入。
input [6:0] disp_sel;
output o_a, o_b, o_c, o_d, o_e, o_f, o_g, o_dp;
output [3:0] o_sel;
output [5:0] o_instr;
wire clk_clk;//去抖动之后的按键输出
wire [8:0] pc_out, pc_in, pc_plus_4;
wire [4:0] reg3_out,
tmp_sel;
wire [31:0] wdata_out,
instr_out,
reg1_dat, reg2_dat,
signext_out,
mux_to_alu,
alu_out,
mem_dat_out,
branch_addr_out,
branch_mux_out,
gpr_disp_out;
wire [1:0] aluop;
wire [2:0] alu_ctrl;
wire regwrite, alusrc, memwrite, memtoreg, memread, branch, jump, regdst, alu_zero, and_out;
reg [15:0] clk_cnt, tmp_cnt;
reg [1:0] disp_clk_cnt;
always @ (posedge clk_clk or posedge rst) begin
if (rst == 1)
clk_cnt = 16'h0000;
else begin
clk_cnt = clk_cnt + 1;
end
end
always @ (posedge disp_clk or posedge rst) begin
if (rst == 1) begin
disp_clk_cnt = 2'b00;
tmp_cnt = 0;
end
else begin
tmp_cnt = tmp_cnt + 1;
if (tmp_cnt == 16'h0000)
disp_clk_cnt = disp_clk_cnt + 1;
end
end
assign o_instr = instr_out[31:26];
assign tmp_sel[4:0] = disp_sel[4:0];
//防抖动模块
anti_jitter x_anti_jitter(disp_clk, clk, clk_clk);
//debug display module
debug_out x_debug_out(
disp_clk_cnt,
clk_cnt,
gpr_disp_out,
pc_out,
disp_sel,o_a, o_b, o_c, o_d, o_e, o_f, o_g, o_dp, o_sel);
//PC register
single_pc x_single_pc(clk_clk, rst, pc_in, pc_out);
//PC plus 4
single_pc_plus4 x_single_pc_plus4(pc_out, pc_plus_4);
//intruction memory, read only. read address from PC's output
c_instr_mem x_c_instr_mem(pc_out, disp_clk, instr_out);
//mux5, select from [20:16] or [15:11], to register file's write port
single_mux5 x_single_mux5(instr_out[20:16],instr_out[15:11],
regdst, reg3_out);
//register files, read from 3 ports, write to 1 port
single_gpr x_single_gpr(
clk_clk, rst,
instr_out[25:21], instr_out[20:16],
tmp_sel,
reg3_out, wdata_out,
regwrite,
reg1_dat, reg2_dat,
gpr_disp_out);
//ALU ctrl
single_alu_ctrl x_single_alu_ctrl(aluop, instr_out[5:0],alu_ctrl);
//16 to 32 extension
single_signext x_single_signext(instr_out[15:0], signext_out);
//mux32,to ALU B-port input(mux to alu)
single_mux32 x_single_mux32(reg2_dat, signext_out, alusrc, mux_to_alu);
//ALU
single_alu x_single_alu(reg1_dat, mux_to_alu, alu_ctrl, alu_zero, alu_out);
//data memory, r/w
c_dat_mem x_c_dat_mem(
alu_out[8:0],
disp_clk,
reg2_dat,
mem_dat_out,
memwrite);
//mux32, select from ALU or Memory 's output, to Register files' write port
single_mux32 x_single_mux32_2(alu_out, mem_dat_out, memtoreg, wdata_out);
//and gate, zero and branch signal for BEQ
and x_and(and_out, alu_zero, branch);
//ADD, add PC+4 and immediate number for BEQ's address transition
single_add x_single_add(signext_out, {{23'b000_0000_0000_0000_0000_0000},pc_plus_4},branch_addr_out);//why not shifit left 2 bits?
//mux32,ctrl is the output of and gate, determine whether use the BEQ transition address,(branch mux out)
single_mux32 x_single_mux_32_3({23'b000_0000_0000_0000_0000_0000,pc_plus_4}, branch_addr_out, and_out, branch_mux_out);
//mux9, jump selection, to pc_in
single_mux9 x_single_mux9(branch_mux_out[8:0], instr_out[8:0], jump, pc_in);
//CPU controllor
single_ctrl x_single_ctrl(rst, instr_out[31:26], regdst, alusrc,memtoreg, regwrite, memread, memwrite, branch, jump, aluop);
endmodule
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
/////
//按键去抖动模块,和我写的有差别
module anti_jitter(clk, button, button_out);
input wire clk;
input wire button;
output reg button_out;
reg [31:0] counter;
always @(posedge clk) begin
if(counter>0) begin
if(counter<100000)
counter<=counter+1;
else begin
counter<=32'b0;
button_out<=button;
end
end
else
if(button>0)
counter<=counter+1;
end
endmodule
//N 路多路复用器模块
module single_mux5(A, B, Ctrl, S);//2to1MUX
parameter N = 5;//N=5
input wire [N-1:0] A, B;
input Ctrl;
output wire [N-1:0] S;
assign S = (Ctrl == 1'b0) ? (A) : (B);
endmodule
module single_mux9(A, B, Ctrl, S);//2to1MUX
parameter N = 9;//N=9
input wire [N-1:0] A, B;
input Ctrl;
output wire [N-1:0] S;
assign S = (Ctrl == 1'b0) ? (A) : (B);
endmodule
module single_mux32(A, B, Ctrl, S);//2to1MUX
parameter N = 32;//N=32
input wire [N-1:0] A, B;
input Ctrl;
output wire [N-1:0] S;
assign S = (Ctrl == 1'b0) ? (A) : (B);
endmodule
//PC+4 模块
module single_pc_plus4(i_pc, o_pc);//PC+4
parameter N = 9;//N
input wire [N-1:0] i_pc;
output wire [N-1:0] o_pc;
assign o_pc[N-1:0] = i_pc[N-1:0] + 1;
endmodule
//PC 模块
module single_pc(clk, rst, i_pc, o_pc);//PC
parameter N = 9;//N
input wire clk, rst;
input wire [N-1:0] i_pc;
output wire [N-1:0] o_pc;
reg [N-1:0] t_pc;
assign o_pc = rst ? {N{1'b1}} : t_pc;
always@(posedge clk) begin
t_pc <= i_pc;
end
endmodule
//符号扩展模块
module single_signext(i_16, o_32);//sign extent
input wire [15:0] i_16;
output reg [31:0] o_32;
always@(i_16) begin
o_32 <= {{16{i_16[15]}}, i_16[15:0]};
end
endmodule
//加法器模块
module single_add(i_op1, i_op2, o_out);//single adder
parameter N = 32;//N
input wire [N-1:0] i_op1;
input wire [N-1:0] i_op2;
output wire [N-1:0] o_out;
assign o_out = i_op1 + i_op2;
endmodule
//指令控制模块
module single_ctrl(rst, OP, RegDst, ALUsrc, MemtoReg, RegWrite,MemRead,
MemWrite, Branch, Jump, ALUop);//single ctrl
input wire rst;
input wire [5:0] OP;
output wire RegDst, RegWrite, ALUsrc, MemtoReg, MemRead, MemWrite,
Branch, Jump;
output wire [1:0] ALUop;
wire R, LW, SW, BEQ;
assign R = ~OP[5]&~OP[4]&~OP[3]&~OP[2]&~OP[1]&~OP[0];//000000=0
assign LW = OP[5]&~OP[4]&~OP[3]&~OP[2]&OP[1]&OP[0];//100011=35
assign SW = OP[5]&~OP[4]&OP[3]&~OP[2]&OP[1]&OP[0];//101011=43
assign BEQ = ~OP[5]&~OP[4]&~OP[3]&OP[2]&~OP[1]&~OP[0];//000100=4
assign RegDst = ~rst & R;
assign MemtoReg = ~rst & LW;
assign RegWrite = ~rst & (R | LW);//? not or?
assign ALUsrc = ~rst & (LW | SW);//? not or?
assign ALUop = ~rst & {R, BEQ};
assign MemRead = ~rst & LW;
assign MemWrite = ~rst & SW;
assign Branch = ~rst & BEQ;
assign Jump = (~OP[5]&~OP[4]&~OP[3]&~OP[2]&OP[1]&~OP[0]);//000010=2
endmodule
//ALUop 控制模块
module single_alu_ctrl(aluop, func, alu_ctrl);//single ALU ctrl
input [1:0] aluop;
input [5:0] func;
output reg [2:0] alu_ctrl;
always @(aluop or func) begin
case(aluop)
2'b00: begin
alu_ctrl = 3'b010;//ADD
end
2'b01: begin
alu_ctrl = 3'b110;//SUB
end
2'b10: begin
case(func)
6'b100000: alu_ctrl = 3'b010;//ADD
6'b100010: alu_ctrl = 3'b110;//SUB
6'b101010: alu_ctrl = 3'b111;//SLT
6'b100100: alu_ctrl = 3'b000;//AND
6'b100101: alu_ctrl = 3'b001;//OR
default: alu_ctrl = 3'b000;//ADD
endcase
end
default: begin
alu_ctrl = 3'b000;//ADD
end
endcase
end
endmodule
//ALU 计算模块
module single_alu(i_r, i_s, i_aluc, o_zf, o_alu);//single ALU
input [31:0] i_r;
input [31:0] i_s;
input [2:0] i_aluc;
output reg o_zf;
output reg [31:0] o_alu;
always @(i_aluc or i_r or i_s) begin
case (i_aluc)
3'b000: begin//AND
o_zf = 0;
o_alu = i_r & i_s;
end
3'b001: begin//OR
o_zf = 0;
o_alu = i_r | i_s;
end
3'b010: begin//ADD
o_zf = 0;
o_alu = i_r + i_s;
end
3'b110: begin//SUB
o_alu = i_r - i_s;
o_zf = (o_alu == 0);
end
3'b111: begin//SLT
o_zf = 0;
if (i_r < i_s)
o_alu = 1;
else
o_alu = 0;
end
default: begin//reset
o_alu = 0;
o_zf = 0;
end
endcase
end
endmodule
//寄存器读写模块
module single_gpr(//general purpose registers
clk, rst,//clock and reset
i_adr1, i_adr2,//read register 1 2
i_adr3,//read register 3, for test
i_wreg, i_wdata,//register to be written and the data
i_wen,//RegWrite Enable
o_op1,o_op2,//read data output 1 2
o_op3//read data output 3, for test
);
input wire clk, rst, i_wen;
input wire [4:0] i_adr1, i_adr2, i_adr3, i_wreg;
input wire [31:0] i_wdata;
output wire [31:0] o_op1, o_op2, o_op3;
reg [31:0] mem[31:0];//32 local registers
assign o_op1 = mem[i_adr1];
assign o_op2 = mem[i_adr2];
assign o_op3 = mem[i_adr3];
always @(posedge clk or posedge rst) begin//both on positive pulse written
if (rst == 1) begin
mem[0] <= 32'h0000_0000;
end
else if (i_wen) begin
mem[i_wreg] <= (i_wreg == 5'b00000) ? 32'h0000_0000 :
i_wdata;//zero can't be written
end
end
endmodule
//测试模块
module debug_out(//debug led display
clk,//decides which digit to display
i_clk_cnt,//clock number to display
i_reg_dat,//register to display
i_pc,//PC to display
i_disp_sel,//display selection
o_a, o_b, o_c, o_d, o_e, o_f, o_g, o_dp,//8 digit display
o_sel);
input [1:0] clk;
input [15:0] i_clk_cnt;
input [31:0] i_reg_dat;
input [8:0] i_pc;
input [6:0] i_disp_sel;
output o_a, o_b, o_c, o_d, o_e, o_f, o_g, o_dp;
output [3:0] o_sel;
single_leds x_single_leds(clk,
(i_disp_sel[6:5]==2'b10)?{{5'b00000},i_pc}:
((i_disp_sel[6:5]==2'b11)?i_clk_cnt:
((i_disp_sel[6:5]==2'b00)?i_reg_dat[15:0]:i_reg_dat[31:16])),
o_a,o_b,o_c,o_d,o_e,o_f,o_g,o_dp,o_sel);
endmodule
//display 模块
module single_leds(clk_cnt, i_number, o_a, o_b, o_c, o_d, o_e, o_f, o_g, o_dp, o_sel);
input [1:0] clk_cnt;
input [15:0] i_number;
output o_a, o_b, o_c, o_d, o_e, o_f, o_g, o_dp;
output [3:0] o_sel;
reg o_a, o_b, o_c, o_d, o_e, o_f, o_g;
reg [3:0] o_sel;
reg [3:0] t_num;
assign o_dp = 1;
always @ (clk_cnt or i_number or t_num) begin
case (clk_cnt)
2'b00:begin
o_sel <= 4'b0111;
t_num <= i_number[15:12];
end
2'b01:begin
o_sel <= 4'b1011;
t_num <= i_number[11:8];
end
2'b10:begin
o_sel <= 4'b1101;
t_num <= i_number[7:4];
end
2'b11:begin
o_sel <= 4'b1110;
t_num <= i_number[3:0];
end
default:;
endcase
case (t_num)
4'b0000:begin
o_a <= 0;
o_b <= 0;
o_c <= 0;
o_d <= 0;
o_e <= 0;
o_f <= 0;
o_g <= 1;
end
4'b0001:begin
o_a <= 1;
o_b <= 0;
o_c <= 0;
o_d <= 1;
o_e <= 1;
o_f <= 1;
o_g <= 1;
end
4'b0010:begin
o_a <= 0;
o_b <= 0;
o_c <= 1;
o_d <= 0;
o_e <= 0;
o_f <= 1;
o_g <= 0;
end
4'b0011:begin
o_a <= 0;
o_b <= 0;
o_c <= 0;
o_d <= 0;
o_e <= 1;
o_f <= 1;
o_g <= 0;
end
4'b0100:begin
o_a <= 1;
o_b <= 0;
o_c <= 0;
o_d <= 1;
o_e <= 1;
o_f <= 0;
o_g <= 0;
end
4'b0101:begin
o_a <= 0;
o_b <= 1;
o_c <= 0;
o_d <= 0;
o_e <= 1;
o_f <= 0;
o_g <= 0;
end
4'b0110:begin
o_a <= 0;
o_b <= 1;
o_c <= 0;
o_d <= 0;
o_e <= 0;
o_f <= 0;
o_g <= 0;
end
4'b0111:begin
o_a <= 0;
o_b <= 0;
o_c <= 0;
o_d <= 1;
o_e <= 1;
o_f <= 1;
o_g <= 1;
end
4'b1000:begin
o_a <= 0;
o_b <= 0;
o_c <= 0;
o_d <= 0;
o_e <= 0;
o_f <= 0;
o_g <= 0;
end
4'b1001:begin
o_a <= 0;
o_b <= 0;
o_c <= 0;
o_d <= 0;
o_e <= 1;
o_f <= 0;
o_g <= 0;
end
4'b1010:begin
o_a <= 0;
o_b <= 0;
o_c <= 0;
o_d <= 1;
o_e <= 0;
o_f <= 0;
o_g <= 0;
end
4'b1011:begin
o_a <= 1;
o_b <= 1;
o_c <= 0;
o_d <= 0;
o_e <= 0;
o_f <= 0;
o_g <= 0;
end
4'b1100:begin
o_a <= 0;
o_b <= 1;
o_c <= 1;
o_d <= 0;
o_e <= 0;
o_f <= 0;
o_g <= 1;
end
4'b1101:begin
o_a <= 1;
o_b <= 0;
o_c <= 0;
o_d <= 0;
o_e <= 0;
o_f <= 1;
o_g <= 0;
end
4'b1110:begin
o_a <= 0;
o_b <= 1;
o_c <= 1;
o_d <= 0;
o_e <= 0;
o_f <= 0;
o_g <= 0;
end
4'b1111:begin
o_a <= 0;
o_b <= 1;
o_c <= 1;
o_d <= 1;
o_e <= 0;
o_f <= 0;
o_g <= 0;
end
default:;
endcase
end
endmodule
ucf文件
NET"clk" LOC="L13";
NET"rst" LOC="L14";
NET"disp_clk" LOC="T9";
NET"disp_sel[0]" LOC="F12";
NET"disp_sel[1]" LOC="G12";
NET"disp_sel[2]" LOC="H14";
NET"disp_sel[3]" LOC="H13";
NET"disp_sel[4]" LOC="J14";
NET"disp_sel[5]" LOC="J13";
NET"o_a" LOC="E14";
NET"o_b" LOC="G13";
NET"o_c" LOC="N15";
NET"o_d" LOC="P15";
NET"o_e" LOC="R16";
NET"o_f" LOC="F13";
NET"o_g" LOC="N16";
NET"o_dp" LOC="P16";
NET"o_instr[0]" LOC="K12";
NET"o_instr[1]" LOC="P14";
NET"o_instr[2]" LOC="L12";
NET"o_instr[3]" LOC="N14";
NET"o_instr[4]" LOC="P13";
NET"o_instr[5]" LOC="N12";
NET"o_sel[0]" LOC="D14";
NET"o_sel[1]" LOC="G14";
NET"o_sel[2]" LOC="F14";
NET"o_sel[3]" LOC="E13";
NET "clk" CLOCK_DEDICATED_ROUTE = FALSE;#占用了ckl信号
计算机组成实验-第7章_单时钟数据通路设计
最新推荐文章于 2022-11-12 16:08:16 发布