出现意外波形,正在设计CPU

时间:2020-05-19 09:50:27

标签: verilog xilinx

enter image description here

我正在尝试设计CPU和SRAM之间的读写周期。 初始内存值为mem(0)= 000f,mem(1)= 000e。 我想按5个周期设计 周期1:分配地址= 0 周期2:从SRAM读取值,mem(0)-> IR 周期3:分配地址= 1 周期4:将值写入SRAM,IR-> mem(1) 周期5:从SRAM读取值mem(1)-> DR

        module sram(addr,clk,din,dout,we); //sram.v

        parameter addr_width = 12, word_depth = 4096, word_width = 16;

        input clk,we;
        input [addr_width-1:0] addr; 
        input [word_width-1:0] din; 
        output [word_width-1:0] dout; 

        reg [word_width-1:0]mem[0:word_depth-1]; 
        reg [word_width-1:0]dout;

        always @ (posedge clk) begin
            if(!we)
                mem[addr] <= din[word_width-1:0]; 
            end
        always @ (posedge clk) begin
            if(we)
                dout[word_width-1:0] <= mem[addr];
            end

        endmodule


        module cpu(clk,reset,select); //cpu.v

        input clk,reset;
        input [2:0]select;

        reg[15:0] ir,dr,ac;
        reg[11:0] ar,pc;

        reg [11:0]addr;
        reg[15:0] din;
        reg we;
        wire[15:0] dout;

        sram sram(addr,clk,din,dout,we);

        always @ (posedge clk or negedge reset) begin
            if(!reset) begin
                ar <= 12'b0;  ir <= 16'b0;  pc <= 12'b0;  dr <= 16'b0;  ac <= 16'b0;
            end

            if(select==3'b001)  //cycle1, address assign
                 addr <= 12'b0; 
            if(select==3'b010) //cycle2, read
                 we <= 1;ir[15:0] <= dout[15:0]; 
            if(select==3'b011) //cycle1, address assign
                 addr <= 12'b1;    
            if(select==3'b100) //cycle4, write
                 we <= 0; din[15:0] <= ir[15:0]; 
            if(select==3'b101) //cycle5, read
                 we <= 1; dr[15:0] <= dout[15:0];
            end

        endmodule

        module tb_cpu(); //tb_cpu.v
        parameter addr_width = 12, word_depth = 4096, word_width = 16;

        reg clk,reset;
        reg [2:0] select;
        integer sram_pointer;
        integer reg_pointer;

        cpu cpu(clk,reset,select);

        always #5 clk = ~clk;

        initial begin
            clk = 0; reset = 1;

            $readmemb("sram.dat", tb_cpu.cpu.sram.mem);

            sram_pointer = $fopen("sram_aftercycle.dat");
            reg_pointer = $fopen("reg.dat");
            #1 reset = 0;
            #1 reset = 1;
            #3 select = 3'b001; //cycle 1
            #20 select = 3'b010; //cycle 2
            #20 select = 3'b011; //cycle 3
            #20 select = 3'b100; //cycle 4
            #20 select = 3'b101; //cycle 5

            #10
            $fdisplay(reg_pointer, "AR = %b", tb_cpu.cpu.ar);
            $fdisplay(reg_pointer, "IR = %b", tb_cpu.cpu.ir);
            $fdisplay(reg_pointer, "PC = %b", tb_cpu.cpu.pc);
            $fdisplay(reg_pointer, "DR = %b", tb_cpu.cpu.dr);
            $fdisplay(reg_pointer, "AC = %b", tb_cpu.cpu.ac);

            $fdisplay(sram_pointer, "mem[0000 0000 0000] = %b",tb_cpu.cpu.sram.mem[0]);
            $fdisplay(sram_pointer, "mem[0000 0000 0001] = %b",tb_cpu.cpu.sram.mem[1]);
            $fdisplay(sram_pointer, "mem[0000 0000 0010] = %b",tb_cpu.cpu.sram.mem[2]);
            $fdisplay(sram_pointer, "mem[0000 0000 0011] = %b",tb_cpu.cpu.sram.mem[3]);

             $fclose(sram_pointer);
             $fclose(reg_pointer);

             #5 $finish;
         end

        endmodule

这是我的模拟。选择值可以表示循环数。如我所料,当第2周期开始时,mem(0)值000f分配给dout,因此dout变为000f,IR应该在下一个上升沿获得该值,但是DR值却意外地与IR同时改变。问题出在哪里?

1 个答案:

答案 0 :(得分:2)

在always块的底部,您有一个if / begin / end

if(select==3'b101) //cycle5, read
   we <= 1; dr[15:0] <= dout[15:0];

这意味着将始终发生对dr的分配;该条件仅覆盖we <= 1