计算机组成实验-第7章_单时钟数据通路设计

总结:
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信号



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值