总结: 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 发布