有什么建议来监视结果吗?用于使用数据存储器实现的存储和加载指令

时间:2019-01-12 08:43:39

标签: architecture verilog display instruction-set

我很难在我的处理器中实现加载和存储指令。我现在已经成功实现了ALU RegisterFile,我想添加一个数据存储器并升级控制单元。我尚未执行记忆指令。因此,指令在InstructionReg中被硬编码为32位。 我想检查天气负荷,并妥善保存存储说明。所以我监视了data_write data_read和toReg的时钟变化。但是我没有结果。您能帮我解决代码中的任何错误吗?或者您可以建议我任何方法来执行此操作。希望代码清晰,如果有任何不清楚的地方,请评论我可以解释

  

我的结果

     

执行loadImmediate clk = 0 DataIn = 17 ReadData = x toReg = 17   clk = 1 DataIn = 17 ReadData = x toReg = 17执行存储clk = 0   DataIn = x ReadData = x toReg = x clk = 1 DataIn = x ReadData = x   toReg = x正在执行加载clk = 0 DataIn = x ReadData = x toReg = x   clk = 1 DataIn = x ReadData = x toReg = x clk = 0 DataIn = x   ReadData = x toReg = x clk = 1 DataIn = x ReadData = x toReg = x   clk = 0 DataIn = x ReadData = x toReg = x clk = 1 DataIn = x   ReadData = x toReg = x clk = 0 DataIn = x ReadData = x toReg = x   clk = 1 DataIn = x ReadData = x toReg = x clk = 0 DataIn = x   ReadData = x toReg = x clk = 1 DataIn = x ReadData = x toReg = x   clk = 0 DataIn = x ReadData = x toReg = x clk = 1 DataIn = x   ReadData = x toReg = x clk = 0 DataIn = x ReadData = x toReg = x   clk = 1 DataIn = x ReadData = x toReg = x clk = 0 DataIn = x   ReadData = x toReg = x clk = 1 DataIn = x ReadData = x toReg = x   clk = 0 DataIn = x ReadData = x toReg = x clk = 1 DataIn = x   ReadData = x toReg = x clk = 0 DataIn = x ReadData = x toReg = x   clk = 1 DataIn = x ReadData = x toReg = x clk = 0 DataIn = x   ReadData = x toReg = x clk = 1 DataIn = x ReadData = x toReg = x   clk = 0 DataIn = x ReadData = x toReg = x clk = 1 DataIn = x   ReadData = x toReg = x

<pre><code>
module testbed;

    //this is test bench

    reg clk, reset,rst;
    wire [31:0] instruction;
    wire [2:0] out_addr1, out_addr2, in_addr, select;
    wire [3:0] ReadAddr;
    wire data2_compli_control, immediate_control,busy_wait,memRead,memWrite,regWrite;
    wire [7:0] dataIN, dataSRC1, dataSRC2, dataSRC2_COMPLI, data2, data1, immediate_value,toReg,address,read_data,write_data;

    PC myPC(clk, reset,busy_wait, ReadAddr);
    regInstructions myRegInstr(clk, ReadAddr, instruction);
    CU myCU(busy_wait,instruction, out_addr1, out_addr2, in_addr, select, data2_compli_control, immediate_control, immediate_value, memRead,memWrite,regWrite,address);



    regFile8x8a mREG(clk,busy_wait, in_addr, toReg, out_addr1, dataSRC1, out_addr2, dataSRC2);
    CMPL myCMPL(dataSRC2, dataSRC2_COMPLI);
    MUX mMUX_C(dataSRC2, dataSRC2_COMPLI, data2_compli_control, data2);
    MUX mMUX_I(dataSRC1, immediate_value, immediate_control, data1);
    MUX mMUX_regWrite(write_data, read_data, regWrite, toReg);
    alu mALU(write_data, data1, data2, select);
    data_mem mdata_mem(clk,rst,memRead,memWrite,address,write_data,read_data,busy_wait);
    initial
    begin

        //$dumpfile("wavedata.vcd");
        //$dumpvars(0,testbed);

        clk = 1'b0;
        reset = 1'b0;
        rst = 1'b0;
        rst = 1'b1;
        //$monitor("DataIn = %d", write_data);

    end

    always #50 clk = ~clk;

    initial
    begin
    $monitor("clk = %d write_data= %d read_data= %d toReg=%d",clk,write_data,read_data,toReg);
        #5000 $finish;

    end

endmodule

module PC (

    input clk,    // Clock
    input reset,
    input busy_wait,
    output [3:0] Read_addr

);

reg [3:0] Read_addr = 4'b0000;

always @(posedge clk)
begin
    if(~reset)
        begin

            Read_addr <= Read_addr + 1'b1;  
        end

    else if (busy_wait) begin
        Read_addr <= Read_addr ;
    end
    else begin
        Read_addr <= 4'b0000;
    end

end

endmodule

module regInstructions (
    input clk,    
    input [3:0] Read_Addr, 
    output [31:0] instruction

);

reg [31:0] instruction;

                   //  00000000                         op_code
                   //          00000000                 destination
                   //                  00000000         source 2
                   //                          00000000 source 1
reg [31:0] step1 = 32'b00001000000001000000000000010001;        // loadi 4, X, 17
reg [31:0] step2 = 32'b00000101000000000000000000000100;        // store 0, X, 4
reg [31:0] step3 = 32'b00000100000001010000000000000000;        // load 5, X, 0
reg [31:0] step4 = 32'b00000001000001100000010100000100;        // add   5, 5, 4
//..............///
 /*reg [31:0] step5 = 32'b00000010000000010000010000000101;     // and   1, 4, 5
 reg [31:0] step6 = 32'b00000011000000100000000100000110;       // or    2, 1, 6 
 reg [31:0] step7 = 32'b00000000000001110000000000000010;       // mov   7, x, 2
 reg [31:0] step8 = 32'b00001001000001000000011100000011;       // sub   4, 7, 3*/

always @(negedge clk) 
begin
    case (Read_Addr)
        4'd0:instruction = step1;
        4'd1:instruction = step2;
        4'd2:instruction = step3;
        4'd3:instruction = step4;
        /*//...............////
         4'd4:instruction = step5;
         4'd5:instruction = step6;
         4'd6:instruction = step7;
         4'd7:instruction = step8;*/
        default : /* default */;
    endcase
end

endmodule

module CU (

    input busy_wait, //new
    input [31:0] instruction,
    output [2:0] OUT1addr,
    output [2:0] OUT2addr,
    output [2:0] INaddr,    
    output [2:0] select,
    output data2_compli_control,
    output immediate_control,
    output [7:0] immediate_value,
    output memRead, //new
    output memWrite, //new
    output regWrite, //new
    output [7:0] address

);

reg select, OUT1addr, OUT2addr, INaddr, data2_compli_control, immediate_control, immediate_value,memWrite,memRead,regWrite,address;

always @(instruction) 
begin
    memRead = 1'b0;
    memWrite = 1'b0;
    select = instruction[26:24];
    INaddr = instruction[18:16];
    OUT1addr = instruction[2:0];
    OUT2addr = instruction[10:8];
    immediate_control = 1'b0;
    immediate_value = instruction[7:0];
    data2_compli_control = 1'b0;
        case (instruction[27:24])               //new
        4'b0100:
            // load from memory 
            begin
                memWrite = 1'b0;
                memRead = 1'b1;
                address = instruction[7:0];
                $display("executing load"); 
            end

        4'b0101:
            begin
                memRead = 1'b0;
                memWrite = 1'b1;
                address = instruction[23:16];
                $display("executing store");
            end                     
            // store to memory
        4'b1000:
            // load
            begin
                immediate_control = 1'b1;
                $display("executing loadImmediate");        
            end 

        4'b1001:                        
            // sub
            // use the 2's comp
            data2_compli_control = 1'b1;
            //$display("oper = SUB");
        default : 
        begin
            memWrite = 1'b0;
            memRead = 1'b0; 
        end



    endcase

end

endmodule

module regFile8x8a (
    input clk,  
    input busy_wait,        //new
    input [2:0] INaddr, 
    input [7:0] IN,
    input [2:0] OUT1addr,
    output [7:0] OUT1,
    input [2:0] OUT2addr,
    output [7:0] OUT2
);

reg [7:0] reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7;

assign OUT1 = OUT1addr == 0 ? reg0 :
              OUT1addr == 1 ? reg1 :
              OUT1addr == 2 ? reg2 :
              OUT1addr == 3 ? reg3 :
              OUT1addr == 4 ? reg4 :
              OUT1addr == 5 ? reg5 :
              OUT1addr == 6 ? reg6 :
              OUT1addr == 7 ? reg7 :
              0;

assign OUT2 = OUT2addr == 0 ? reg0 :
              OUT2addr == 1 ? reg1 :
              OUT2addr == 2 ? reg2 :
              OUT2addr == 3 ? reg3 :
              OUT2addr == 4 ? reg4 :
              OUT2addr == 5 ? reg5 :
              OUT2addr == 6 ? reg6 :
              OUT2addr == 7 ? reg7 :
              0;

always @(negedge clk) //new
begin
    if (!busy_wait) begin
        case (INaddr)
        3'b000:reg0 = IN;
        3'b001:reg1 = IN;
        3'b010:reg2 = IN;
        3'b011:reg3 = IN;
        3'b100:reg4 = IN;
        3'b101:reg5 = IN;
        3'b110:reg6 = IN;
        3'b111:reg7 = IN;
    endcase 
    end

end

endmodule

module CMPL (
    input [7:0] Data,    
    output [7:0] out    
);

reg out;

always @(Data)
begin
    out = ~Data + 8'b00000001;
end

endmodule

module MUX (
    input [7:0] Data1,    
    input [7:0] Data2, 
    input control,
    output [7:0] out    
);

reg out;

always @(Data1, Data2, control)
begin
    case (control)
        1'b1:out = Data2;
        default :out = Data1;
    endcase

end

endmodule

module alu(out, DATA1, DATA2, Select);

input [7:0] DATA1, DATA2;
input [2:0] Select;
output [7:0] out;
reg out;

always @(DATA1, DATA2, Select)
    begin
    //$display("opcode = %b" ,Select);
    case(Select)
    3'b000:out = DATA1;
    3'b100:out = DATA1; //new
    3'b101:out = DATA1; //new
    3'b001:out = DATA1+DATA2;
    3'b010:out = DATA1 & DATA2;
    3'b011:out = DATA1 | DATA2;
    default:$display("Err in OpCode");
    endcase
    //$display("op = %b => %b %b = %b",Select, DATA1, DATA2, out);
end
endmodule

module data_mem(
    clk,
    rst,
    read,
    write,
    address,
    write_data,
    read_data,
    busy_wait
);
input           clk;
input           rst;
input           read;
input           write;
input[7:0]      address;
input[7:0]      write_data;
output[7:0]     read_data;
output          busy_wait;

reg[7:0]     read_data;
reg busy_wait,clkMem=1'b0;
integer  i;

// Declare memory 256x8 bits 
reg [7:0] memory_array [255:0];
//reg [7:0] memory_ram_q [255:0];



always @(posedge rst)
begin
    if (rst)
    begin
        for (i=0;i<256; i=i+1)
            memory_array[i] <= 0;
    end
end

always #1 clkMem = ~clkMem;

always @(posedge clkMem)
begin
    if (write && !read && !busy_wait)
    begin
        busy_wait <= 1;
        // artificially delay 100 cycles
        repeat(10)
        begin
        @(posedge clk);
        end
        $display("writing to memory");
        memory_array[address] = write_data;
        busy_wait <= 0;
    end
    if (!write && read && !busy_wait)
    begin
        busy_wait <= 1;
        // artificially delay 100 cycles
        repeat(10)
        begin
        @(posedge clk);
        end
        $display("reading from memory");
        read_data = memory_array[address];
        busy_wait <= 0;
    end
end

endmodule

</code></pre>

1 个答案:

答案 0 :(得分:2)

您这样做的方式是错误的。

为了调试HDL,您应该熟悉波形显示。它不仅可以随时显示信号和每个信号的值。但是您还可以看到时间关系,什么时间发生了什么变化,什么是一两个周期。
您可以搜索值,设置标记,放大和缩小,扩展和折叠总线,在二进制,十六进制,十进制之间更改数字格式。有些还可以将值转换为模拟格式。

如果电路复杂一些,则可能必须跟踪几百个信号。仅使用文本是不可能的。

如果您的模拟器没有波形显示,请放弃并找到其他波形。