ModelSim处理器设计


第一部分
第二部分
第三部分
第四部分
第五部分

这是上一篇文章的完整版本,其中添加了测试平台。

我们在Verilog中设计Little Man Computer

关于LMC 的文章在Habré上。

这台计算机的在线模拟器在这里

我们将编写一个包含四个(ADDR_WIDTH = 2)四位(DATA_WIDTH = 4)字的RAM模块。 当时钟信号clk到达时,数据从adr的data_in加载到RAM中。

module R0 #(parameter ADDR_WIDTH = 2, DATA_WIDTH = 4) ( input clk, //  input [ADDR_WIDTH-1:0] adr, // input [DATA_WIDTH-1:0] data_in, //   output [DATA_WIDTH-1:0] RAM_out //   ); reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; //  mem always @(posedge clk) //    clk mem [adr] <= data_in; //     data_in assign RAM_out = mem[adr]; // RAM_out    endmodule 

在测试平台中,在00处加载0001,在01处加载0010,在10处加载0100,在11处加载1000:
创建一个测试平台
创建一个新项目,创建文件R0.v和tR0.v(这些文件将自动添加到项目中)。
编译两个文件。
运行编译文件tR0.v的模拟

 module tR0; reg clk; reg [1:0] adr; reg [3:0] data_in; wire [3:0] RAM_out; R0 test_R0 (clk, adr, data_in,RAM_out); initial begin clk = 0; adr[0] = 0; adr[1] = 0; data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; #5 data_in[0] = 1; #5 clk = 1; #5 adr[0] = 1; data_in[0] = 0; data_in[1] = 1; clk = 0; #5 clk = 1; #5 adr[0] = 0; adr[1] = 1; data_in[1] = 0; data_in[2] = 1; clk = 0; #5 clk = 1; #5 adr[0] = 1; adr[1] = 1; data_in[2] = 0; data_in[3] = 1; clk = 0; #5 clk = 1; #5 adr[0] = 0; adr[1] = 0; data_in[3] = 0; clk = 0; #5 adr[0] = 1; adr[1] = 0; #5 adr[0] = 0; adr[1] = 1; #5 adr[0] = 1; adr[1] = 1; #5 adr[0] = 0; adr[1] = 0; #5 adr[0] = 1; adr[1] = 0; #5 adr[0] = 0; adr[1] = 1; #5 adr[0] = 1; adr[1] = 1; #5 adr[0] = 0; adr[1] = 0; #5 adr[0] = 1; adr[1] = 0; #5 adr[0] = 0; adr[1] = 1; #5 adr[0] = 1; adr[1] = 1; end endmodule 



我们将计数器连接到RAM的地址输入。 必须将时钟发生器连接到计数器输入。

这是一个使用ALTUFM_OSC内部生成器的程序示例。 标准发生器的频率为5.5 MHz(MAX II EPM240 CPLD最小开发板)。

 module inner_Clock ( output reg LED); ALTUFM_OSC osc( .oscena(1'b1), .osc(clk)); reg signal; reg [24:0] osc_counter; reg [24:0] const_data = 25'b10110111000110110000000; initial begin signal = 1'b0; osc_counter = 25'b0; end //  6 000 000    osc_counter always @(posedge clk) begin osc_counter <= osc_counter+ 1'b1; if(osc_counter == const_data) begin signal <= ~signal; osc_counter <= 25'b0; end LED = signal; // LED  ~1   . end endmodule 

您还可以使用外部发生器,例如555 CMOS计时器(由3.3V供电)。 我们将555定时器连接到计数器,将计数器连接到RAM的地址输入。

T.O. 当时钟信号到达计数器时,我们将转到内存中的下一个单元。 我们将把RAM_button按钮连接到RAM时钟输入-单击此按钮将加载RAM中的数据。

 module R1 (timer555, RAM_button, data_in, RAM_out, counter); parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; input timer555; input RAM_button; //input [ADDR_WIDTH-1:0] adr; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM_out; output reg [1:0] counter; // Counter always @(posedge timer555) counter <= counter + 1; // RAM wire [ADDR_WIDTH-1:0] adr; assign adr = counter; reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; always @(posedge RAM_button) mem [adr] <= data_in; assign RAM_out = mem[adr]; endmodule 

这就是RTL Viewer中的电路



在ModelSim模拟器中,此方案将不起作用,因为模拟器不知道计数器[1:0]寄存器的初始值。
可以通过直接将程序下载到FPGA来检查电路的操作。

接下来,将下载功能添加到计数器。 通过单击Counter_load按钮从data_in [1:0]下载

 module R2 (counter, timer555, Counter_load, RAM_button, data_in, RAM_out); parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; output [1:0] counter; input timer555, Counter_load; // input [N-1:0] adr; input RAM_button; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM_out; // Counter reg [1:0] counter; always @ (posedge timer555 or posedge Counter_load) if (Counter_load) counter <= data_in[1:0]; else counter <= counter + 2'b01; // RAM wire [ADDR_WIDTH-1:0] adr; assign adr = counter; reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; always @(posedge RAM_button) mem [adr] <= data_in; assign RAM_out = mem[adr]; endmodule 

Pin Planner中的按钮和LED的连接如下所示:



在00、0010、01、00100、10、1000、11下载0001

 module tR2; parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; reg timer555, Counter_load, RAM_button; wire [1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM_out; R2 test_R2(counter, timer555, Counter_load, RAM_button, data_in, RAM_out); initial // Clock generator begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; Counter_load = 0; RAM_button = 0; #5 data_in[0]=0; data_in[1]=0; Counter_load=1; RAM_button=0; #5 data_in[0]=1; data_in[1]=0; Counter_load=0; RAM_button=1; #5 data_in[0]=0; data_in[1]=0; Counter_load=0; RAM_button=0; #5 data_in[0]=1; data_in[1]=0; Counter_load=1; RAM_button=0; #5 data_in[0]=0; data_in[1]=1; Counter_load=0; RAM_button=1; #5 data_in[0]=0; data_in[1]=0; Counter_load=0; RAM_button=0; #5 data_in[0]=0; data_in[1]=1; Counter_load=1; RAM_button=0; #5 data_in[2]=1; data_in[0]=0; data_in[1]=0; Counter_load=0; RAM_button=1; #5 data_in[2]=0; data_in[0]=0; data_in[1]=0; Counter_load=0; RAM_button=0; #5 data_in[0]=1; data_in[1]=1; Counter_load=1; RAM_button=0; #5 data_in[3]=1; data_in[0]=0; data_in[1]=0; Counter_load=0; RAM_button=1; #5 data_in[3]=0; data_in[0]=0; data_in[1]=0; Counter_load=0; RAM_button=0; end endmodule 



在一个单独的模块中,创建一个4bit'ny寄存器(电池)。

当您单击reg_button按钮时,数据被加载到寄存器中:

 module register4 ( input [3:0] reg_data, input reg_button, output reg [3:0] q ); always @(posedge reg_button) q <= reg_data; endmodule 

将累加器,MUX2多路复用器和求和器加到通用电路中。
加法器将存储器中的电池Acc编号添加到该编号中。
给多路复用器的信号输入编号为data_in和sum。
通过按下Acc_button按钮将MUX2中的号码加载到Acc电池中。
当按下RAM_button按钮时,来自Ass的编号将被加载到RAM中。





 module R3 (MUX_switch, Acc_button, Acc, counter, timer555, Counter_load, RAM_button, data_in, RAM_out); parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; input MUX_switch; input Acc_button; output [3:0] Acc; input timer555, Counter_load; output [1:0] counter; // input [N-1:0] adr; input RAM_button; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM_out; // Counter reg [1:0] counter; always @ (posedge timer555 or posedge Counter_load) if (Counter_load) counter <= data_in[1:0]; else counter <= counter + 2'b01; // RAM wire [ADDR_WIDTH-1:0] adr; assign adr = counter; reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; always @(posedge RAM_button) mem [adr] <= Acc; assign RAM_out = mem[adr]; // sum wire [3:0] sum; assign sum = Acc + RAM_out; // MUX2 reg [3:0] MUX2; always @* MUX2 = MUX_switch ? sum : data_in; //     Acc_button /* reg Acc_dff; always @(posedge Acc_button or negedge timer555) if (!timer555) Acc_dff <= 1'b0; else Acc_dff <= timer555; */ //Acc register4 Acc_reg( .reg_data(MUX2), //.reg_button(Acc_dff), .reg_button(Acc_button), .q(Acc) ); endmodule 

对于程序性颤振抑制,可以使用注释中给出的简单方案。
/ * reg Acc_dff;
总是@(posege Acc_button或negedge timer555)
如果(!timer555)
Acc_dff <= 1'b0;
别的
Acc_dff <= timer555; * /

您还可以在本文的评论中阅读有关抑制按钮颤动的信息。

接下来,我们将添加数字,例如2和3。

1.将数字加载到RAM
2.将屁股归零
3.切换MUX2
4.将第一个数字从RAM下载到Ass
5.将RAM中的第二个数字添加到Ass中的数字
6.将金额下载到RAM

 module tR3; parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; reg MUX_switch; reg Acc_button; wire [3:0] Acc; reg timer555, Counter_load, RAM_button; wire [1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM_out; R3 test_R3(MUX_switch, Acc_button, Acc, counter, timer555, Counter_load, RAM_button, data_in, RAM_out); initial begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; Counter_load = 0; Acc_button = 0; RAM_button = 0; MUX_switch = 0; #5 Counter_load = 1; #5 data_in[0]=0; data_in[1]=1; Counter_load = 0; #5 Acc_button = 1; #5 RAM_button = 1; #5 data_in[0]=0; data_in[1] = 0; Acc_button = 0; RAM_button = 0; #5 data_in[0]=1; data_in[1]=1; #15 Acc_button = 1; #5 RAM_button = 1; #5 Acc_button = 0; #5 data_in[0]=0; data_in[1] = 0; RAM_button = 0; #10 Acc_button = 1; #10 Acc_button = 0; #60 MUX_switch = 1; #10 Acc_button = 1; #10 Acc_button = 0; #30 Acc_button = 1; #10 Acc_button = 0; #30 RAM_button = 1; #10 RAM_button = 0; end endmodule 



在主模块中添加一个元素,该元素将从电池中的数量减去内存中记录的数量。

 wire [3:0] subtract; assign subract = Acc - RAM_out ; 


我们用四输入代替两输入多路复用器
 always @* MUX4 = MUX_switch[1] ? (MUX_switch[0] ? RAM_out : subtract) : (MUX_switch[0] ? sum : data_in); 

我们将输出设备连接到电池(4bit'ny寄存器),还将两个标志连接到电池:

1.标志“ 0”是一个日志。 元素4或不。 如果Ass的内容为零,则引发该标志。

2.标志“零或正数”是一个日志。 元素不在四位数电池的高电平上。 如果Ass的内容大于或等于零,则引发该标志。

 // "" output Z_flag; assign Z_flag = ~(|Acc); //    // "   " output PZ_flag; assign PZ_flag = ~Acc[3]; 



新增三支队伍

1.将电池内容加载到data_out输出设备中
2.如果标志“零”被引发,则将地址加载到计数器中(如果Acc = 0,则为JMP)
3.如果出现标志“零或正数”,则将地址加载到计数器中(如果Acc> = 0,则为JMP)

 module R4 (JMP,Z_JMP,PZ_JMP,Z_flag,PZ_flag,Output_button,data_out,MUX_switch,Acc_button,Acc,counter,timer555,RAM_button,data_in,RAM_out); parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; input JMP, Z_JMP, PZ_JMP; output Z_flag, PZ_flag; input Output_button; output [3:0] data_out; input [1:0] MUX_switch; input Acc_button; output [3:0] Acc; input timer555; output [1:0] counter; input RAM_button; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM_out; // flags wire Z,PZ; assign Z = Z_flag & Z_JMP; assign PZ = PZ_flag & PZ_JMP; // Counter reg [1:0] counter; always @ (posedge timer555 or posedge JMP or posedge Z or posedge PZ) if (JMP|Z|PZ) counter <= data_in[1:0]; else counter <= counter + 2'b01; // RAM wire [ADDR_WIDTH-1:0] adr; assign adr = counter; reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; always @(posedge RAM_button) mem [adr] <= Acc; assign RAM_out = mem[adr]; // sum wire [3:0] sum; assign sum = Acc + RAM_out; //subtract wire [3:0] subtract; assign subtract = Acc - RAM_out; // MUX4 reg [3:0] MUX4; always @* MUX4 = MUX_switch[1] ? (MUX_switch[0] ? RAM_out : subtract) : (MUX_switch[0] ? sum : data_in); //Acc register4 Acc_reg( .reg_data(MUX4), .reg_button(Acc_button), .q(Acc) ); //data_out register4 Output_reg( .reg_data(Acc), .reg_button(Output_button), .q(data_out) ); assign Z_flag = ~(|Acc); assign PZ_flag = ~Acc[3]; endmodule 



1.将数字加载到RAM
2.将屁股归零
3.切换MUX2
4.从Ass中减去第一个数字(写在RAM中)
5.从Ass中减去第二个数字(写在RAM中)
6.将金额下载到RAM和data_out

 module tR4; parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; reg JMP, Z_JMP, PZ_JMP; wire Z_flag, PZ_flag; reg Output_button; wire [3:0] data_out; reg [1:0] MUX_switch; reg Acc_button; wire [3:0] Acc; reg timer555, RAM_button; wire [1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM_out; R4 test_R4 (JMP,Z_JMP,PZ_JMP,Z_flag,PZ_flag,Output_button,data_out,MUX_switch,Acc_button,Acc, counter,timer555,RAM_button,data_in,RAM_out); initial begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; JMP = 0; Z_JMP = 0; PZ_JMP = 0; Acc_button = 0; RAM_button = 0; Output_button = 0; MUX_switch[0] = 0; MUX_switch[1] = 0; #5 JMP = 1; #5 data_in[0]=0; data_in[1]=1; JMP = 0; #5 Acc_button = 1; #5 RAM_button = 1; #5 data_in[0]=0; data_in[1] = 0; Acc_button = 0; RAM_button = 0; #5 data_in[0]=1; data_in[1]=1; #15 Acc_button = 1; #5 RAM_button = 1; #5 Acc_button = 0; #5 data_in[0]=0; data_in[1] = 0; RAM_button = 0; #10 Acc_button = 1; #10 Acc_button = 0; #60 MUX_switch[1] = 1; #10 Acc_button = 1; #10 Acc_button = 0; #30 Acc_button = 1; #10 Acc_button = 0; #30 RAM_button = 1; Output_button = 1; #10 RAM_button = 0; Output_button = 0; end endmodule 



检查当Ass中有正数时,不会发生Z_JMP转换:

 module tR4_jmp; parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; reg JMP, Z_JMP, PZ_JMP; wire Z_flag, PZ_flag; reg Output_button; wire [3:0] data_out; reg [1:0] MUX_switch; reg Acc_button; wire [3:0] Acc; reg timer555, RAM_button; wire [1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM_out; R4 test_R4 (JMP,Z_JMP,PZ_JMP,Z_flag,PZ_flag,Output_button,data_out,MUX_switch,Acc_button,Acc, counter,timer555,RAM_button,data_in,RAM_out); initial begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; JMP = 0; Z_JMP = 0; PZ_JMP = 0; Acc_button = 0; RAM_button = 0; Output_button = 0; MUX_switch[0] = 0; MUX_switch[1] = 0; #5 JMP = 1; #5 data_in[0]=0; data_in[1]=1; JMP = 0; #5 Acc_button = 1; #5 data_in[0]=1; data_in[1]=1; Acc_button = 1; #5 data_in[0]=1; data_in[1]=1; Acc_button = 0; #5 Z_JMP = 1; #5 PZ_JMP = 1; Z_JMP = 0; #5 PZ_JMP = 0; end endmodule 



将无条件跳转命令放入RAM



查看设计

 //wire Counter_load; always @ (posedge timer555) if (Counter_load) counter <= RAM_out[3:0]; else counter <= counter + 2'b01; 

ModelSim将不起作用,因此我们将使用附加的reset_count命令,该命令将初始化计数器,并将其重置,即

 module resCount (reset_count, counter, timer555, RAM_button, data_in, RAM_out); parameter ADDR_WIDTH = 4; parameter DATA_WIDTH = 8; input reset_count; output [ADDR_WIDTH-1:0] counter; input timer555; input RAM_button; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM_out; wire Counter_load; assign Counter_load = RAM_out[7]; reg [ADDR_WIDTH-1:0] counter; always @ (posedge timer555 or posedge reset_count) if (reset_count) counter <= 4'b0000; else if (Counter_load) counter <= RAM_out[3:0]; else counter <= counter + 4'b0001; wire [ADDR_WIDTH-1:0] adr; assign adr = counter; reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; always @(posedge RAM_button) mem [adr] <= data_in; assign RAM_out = mem[adr]; endmodule 

测试台

 module tresCount; parameter ADDR_WIDTH = 4; parameter DATA_WIDTH = 8; reg reset_count; reg timer555, RAM_button; wire [ADDR_WIDTH-1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM_out; resCount test_resCount(reset_count, counter, timer555, RAM_button, data_in, RAM_out); initial // Clock generator begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; data_in[4] = 0; data_in[5] = 0; data_in[6] = 0; data_in[7] = 0; RAM_button = 0; reset_count =1; #5 reset_count =0; #1500 data_in[7] =1; #5 RAM_button = 1; #5 data_in[7] =0; RAM_button = 0; end endmodule 



添加到电路MUX2和Ass。 我们将使用RAM_out命令[6]记录在Ass中。

 assign Acc_button = RAM_out[6]; 

我们将一个日志连接到时钟输入Ass。 元素AND

 //  regiser4  (posedge reg_button)  (negedge reg_button) .reg_button(Acc_button & timer555), 

连接日志的含义。 时钟输入是现在在timer555的前面,您可以切换多路复用器,并在下降时记录电池。 T.O. 我们将两支球队一拍即合。

我们将使用RAM_out命令[5]切换MUX2。

 assign MUX_switch = RAM_out[5]; 



 module register4 ( input [3:0] reg_data, input reg_button, output reg [3:0] q ); always @(negedge reg_button) //  "posedge"  "negedge" q <= reg_data; endmodule module R50 (reset_count, counter, timer555, RAM_button, data_in, RAM_out, mux_switch_out, mux_out,Acc_out); parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 8; input reset_count; output [ADDR_WIDTH-1:0] counter; input timer555; input RAM_button; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM_out; output [3:0] Acc_out; output mux_switch_out; output [3:0] mux_out; wire Counter_load; assign Counter_load = RAM_out[7]; //Counter reg [ADDR_WIDTH-1:0] counter; always @ (posedge timer555 or posedge reset_count) if (reset_count) counter <= 2'b00; else if (Counter_load) counter <= RAM_out[1:0]; else counter <= counter + 2'b01; wire [ADDR_WIDTH-1:0] adr; assign adr = counter; //RAM reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; always @(posedge RAM_button) mem [adr] <= data_in; assign RAM_out = mem[adr]; // MUX2 wire MUX_switch; assign MUX_switch = RAM_out[5]; reg [3:0] MUX2; always @* MUX2 = MUX_switch ? RAM_out : data_in[3:0]; //  4   data_in assign mux_out = MUX2; assign mux_switch_out = MUX_switch; wire Acc_button; assign Acc_button = RAM_out[6]; //Acc register4 Acc_reg( .reg_data(mux_out), .reg_button(Acc_button & timer555), .q(Acc_out) ); endmodule 

在测试平台中,将数字0101写入单元格00,并将数字1010写入单元格01; 将这些数字装入电池

 module tR50; parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 8; reg reset_count; reg timer555, RAM_button; wire [ADDR_WIDTH-1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM_out; wire mux_switch_out; wire [3:0] mux_out; wire [3:0] Acc_out; R50 test_R50(reset_count, counter, timer555, RAM_button, data_in, RAM_out, mux_switch_out, mux_out,Acc_out); initial // Clock generator begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 1; data_in[1] = 0; data_in[2] = 1; data_in[3] = 0; data_in[4] = 0; data_in[5] = 1; data_in[6] = 1; data_in[7] = 0; RAM_button = 0; reset_count =1; #5 RAM_button = 1; reset_count = 0; #5 data_in[0]=0; data_in[2]=0; data_in[5]=0; data_in[6]=0; RAM_button=0; #15 data_in[1]=1; data_in[3]=1; data_in[5]=1;data_in[6]=1; #5 RAM_button=1; #5 data_in[1]=0; data_in[3]=0; data_in[5]=0; data_in[6]=0; RAM_button=0; end endmodule 



我们将第二个RAM放置在通用电路中,并使用RAM1_out命令[4]写入RAM。

 assign RAM2_button = RAM1_out[4]; 



 module register4 ( input [3:0] reg_data, input reg_button, output reg [3:0] q ); always @(negedge reg_button) q <= reg_data; endmodule module R51 (reset_count, counter, timer555, RAM1_button, data_in, RAM1_out, RAM2_out, mux_switch_out, mux_out,Acc_out); parameter ADDR_WIDTH = 3; parameter DATA_WIDTH = 8; input reset_count; output [ADDR_WIDTH-1:0] counter; input timer555; input RAM1_button; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM1_out; output [3:0] RAM2_out; output [3:0] Acc_out; output mux_switch_out; output [3:0] mux_out; wire Counter_load; assign Counter_load = RAM1_out[7]; //Counter reg [ADDR_WIDTH-1:0] counter; always @ (posedge timer555 or posedge reset_count) if (reset_count) counter <= 2'b00; else if (Counter_load) counter <= RAM1_out[1:0]; else counter <= counter + 2'b01; wire [ADDR_WIDTH-1:0] adr1; assign adr1 = counter; //RAM1 reg [DATA_WIDTH-1:0] mem1 [2**ADDR_WIDTH-1:0]; always @(posedge RAM1_button ) mem1 [adr1] <= data_in; assign RAM1_out = mem1[adr1]; wire [ADDR_WIDTH-1:0] adr2; assign adr2 = RAM1_out[3:0]; wire RAM2_button; assign RAM2_button = RAM1_out[4]; //RAM2 reg [3:0] mem2 [2**ADDR_WIDTH-1:0]; always @(posedge RAM2_button) mem2 [adr2] <= Acc_out; assign RAM2_out = mem2[adr2]; // MUX2 wire MUX_switch; assign MUX_switch = RAM1_out[5]; reg [3:0] MUX2; always @* MUX2 = MUX_switch ? RAM2_out : data_in[3:0]; assign mux_out = MUX2; assign mux_switch_out = MUX_switch; wire Acc_button; assign Acc_button = RAM1_out[6]; //Acc register4 Acc_reg( .reg_data(mux_out), .reg_button(Acc_button & timer555), .q(Acc_out) ); endmodule 

在测试平台中,将编号0100和1000从Ass加载到零0000和RAM mem2的第一个0001单元(然后将这些编号从RAM mem2加载到Ass)

 module tR51; parameter ADDR_WIDTH = 3; parameter DATA_WIDTH = 8; reg reset_count; reg timer555, RAM1_button; wire [ADDR_WIDTH-1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM1_out; wire [3:0] RAM2_out; wire mux_switch_out; wire [3:0] mux_out; wire [3:0] Acc_out; R51 test_R51(reset_count, counter, timer555, RAM1_button, data_in, RAM1_out, RAM2_out, mux_switch_out, mux_out,Acc_out); initial // Clock generator begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; data_in[4] = 0; data_in[5] = 0; data_in[6] = 1; data_in[7] = 0; RAM1_button = 0; reset_count =1; #5 RAM1_button = 1; reset_count = 0; #5 RAM1_button = 0; data_in[6] = 0; #10 data_in[4] = 1; #5 RAM1_button = 1; #5 data_in[4] = 0; RAM1_button = 0; #30 data_in[6] = 1; #5 RAM1_button = 1; #5 data_in[6] = 0; RAM1_button = 0; #30 data_in[4] = 1; data_in[0] = 1; #5 RAM1_button = 1; #5 data_in[4] = 0; data_in[0] = 0; RAM1_button = 0; #30 data_in[6] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[6] = 0; #30 data_in[5] = 1; data_in[6] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[5] = 0; data_in[6] = 0; #30 data_in[5] = 1; data_in[6] = 1; data_in[0] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[0] = 0; data_in[5] = 0; data_in[6] = 0; #70 data_in[2] = 1; #80 data_in[2] = 0; data_in[3] = 1; #40 data_in[3] = 0; end endmodule 



我将添加该方案c日志。 电池时钟输入端的And元素将始终无法正常工作(取决于主板)。 替换日志。 元素并且在Acc_dff触发器上,我们将在timer555时钟信号的负沿(在下降沿)加载到触发器中,在正沿将其加载到电池上

 // Acc_dff reg Acc_dff; always @(negedge timer555) Acc_dff <= Acc_button; 

因此,添加其余命令,创建R52模块(LMC)



 module register4 ( input [3:0] reg_data, input reg_button, output reg [3:0] q ); always @(posedge reg_button) // negedge -> posedge q <= reg_data; endmodule module R52 (Z_flag, PZ_flag, reset_count, counter, timer555, RAM1_button, data_in, RAM1_out, RAM2_out, mux_switch_out, mux_out, Acc_out, data_out, Acc_dff); parameter ADDR_WIDTH = 4; parameter DATA_WIDTH = 12; input reset_count; input timer555; input RAM1_button; input [DATA_WIDTH-1:0] data_in; output [ADDR_WIDTH-1:0] counter; output [1:0] mux_switch_out; output [3:0] mux_out; output [3:0] Acc_out; output [3:0] data_out; output [DATA_WIDTH-1:0] RAM1_out; output [3:0] RAM2_out; output Z_flag, PZ_flag; output Acc_dff; wire JMP_button, Z_JMP_button,PZ_JMP_button; assign JMP_button = RAM1_out[6]; assign Z_JMP_button = RAM1_out[5]; assign PZ_JMP_button = RAM1_out[4]; wire Z_JMP,PZ_JMP; assign Z_JMP = Z_flag & Z_JMP_button; assign PZ_JMP = PZ_flag & PZ_JMP_button; //Counter reg [ADDR_WIDTH-1:0] counter; always @ (posedge timer555 or posedge reset_count) if (reset_count) counter <= 4'b0000; else if (JMP_button|Z_JMP|PZ_JMP) counter <= RAM1_out[3:0]; else counter <= counter + 4'b0001; wire [ADDR_WIDTH-1:0] adr1; assign adr1 = counter; //RAM1 reg [DATA_WIDTH-1:0] mem1 [2**ADDR_WIDTH-1:0]; always @(posedge RAM1_button ) mem1 [adr1] <= data_in; assign RAM1_out = mem1[adr1]; //RAM2_adr wire [ADDR_WIDTH-1:0] adr2; assign adr2 = RAM1_out[2:0]; //RAM2_button wire RAM2_button; assign RAM2_button = RAM1_out[11]; //RAM2 reg [3:0] mem2 [2**ADDR_WIDTH-1:0]; always @(posedge RAM2_button) mem2 [adr2] <= Acc_out; assign RAM2_out = mem2[adr2]; // sum wire [3:0] sum; assign sum = Acc_out + RAM2_out; //subtract wire [3:0] subtract; assign subtract = Acc_out - RAM2_out; // MUX4 wire [1:0] mux_switch; assign mux_switch[0] = RAM1_out[7]; assign mux_switch[1] = RAM1_out[8]; reg [3:0] MUX4; always @* MUX4 = mux_switch[1] ? (mux_switch[0] ? RAM2_out : subtract) : (mux_switch[0] ? sum : data_in[3:0]); assign mux_out = MUX4; assign mux_switch_out[0] = mux_switch[0]; assign mux_switch_out[1] = mux_switch[1]; //Acc_button wire Acc_button; assign Acc_button = RAM1_out[10]; // Acc_dff reg Acc_dff; always @(negedge timer555) Acc_dff <= Acc_button; //Acc register4 Acc_reg( .reg_data(mux_out), //.reg_button(Acc_button & timer555), .reg_button(Acc_dff), .q(Acc_out) ); //data_out wire Output_button; assign Output_button = RAM1_out[9]; register4 Output_reg( .reg_data(Acc_out), .reg_button(Output_button), .q(data_out) ); // flags assign Z_flag = ~(|Acc_out); assign PZ_flag = ~Acc_out[3]; endmodule 

在测试平台中,我们将检查找到最大数量的算法如何工作。

在RAM中加载命令的特殊之处在于,加载所有命令后,我们必须返回(340ns)到单元8并加载另一个命令

 module tR52; parameter ADDR_WIDTH = 4; parameter DATA_WIDTH = 12; reg reset_count; reg timer555; reg RAM1_button; reg [DATA_WIDTH-1:0] data_in; wire [ADDR_WIDTH-1:0] counter; wire [1:0]mux_switch_out; wire [3:0] mux_out; wire [3:0] Acc_out; wire [3:0] data_out; wire [DATA_WIDTH-1:0] RAM1_out; wire [3:0] RAM2_out; wire Z_flag, PZ_flag; wire Acc_dff; R52 test_R52(Z_flag, PZ_flag, reset_count, counter, timer555, RAM1_button, data_in, RAM1_out, RAM2_out, mux_switch_out, mux_out,Acc_out, data_out, Acc_dff); initial // Clock generator begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; data_in[4] = 0; data_in[5] = 0; data_in[6] = 0; data_in[7] = 0; data_in[8] = 0; data_in[9] = 0; data_in[10] = 1; data_in[11] = 0; RAM1_button = 0; reset_count =1; //  1-    #5 RAM1_button = 1; reset_count = 0; #5 RAM1_button = 0; data_in[10] = 0; data_in[0] = 0; //  1-    0 #10 data_in[11] = 1; #5 RAM1_button = 1; #5 data_in[11] = 0; RAM1_button = 0; //  2-    #30 data_in[10] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[10] = 0; //  2-    0 #30 data_in[11] = 1;data_in[0] = 1; #5 RAM1_button = 1; #5 data_in[11] = 0;data_in[0] = 0; RAM1_button = 0; // 1-    #30 data_in[8]=1; data_in[10] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[8]=0; data_in[10] = 0; //  Acc>=0,    8 #30 data_in[4]=1; data_in[3]=1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[4]=0; data_in[3]=0; //  1-  #30 data_in[7] = 1; data_in[8] = 1; data_in[10] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[7] = 0; data_in[8] = 0; data_in[10] = 0; //     9 #30 data_in[6] = 1; data_in[3]=1; data_in[0]=1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[6] = 0; data_in[3]=0; data_in[0]=0; //   data_out #30 data_in[9] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[9] = 0; //     8 #30 data_in[6] = 1; data_in[3]=1; data_in[0]=0; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[6] = 0; data_in[3]=0; data_in[0]=0; // 2-  #30 data_in[7] = 1; data_in[8] = 1; data_in[10] = 1; data_in[0] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[7] = 0; data_in[8] = 0; data_in[10] = 0; data_in[0] = 0; #75 RAM1_button = 1; #5 RAM1_button = 0; #230 data_in[2]=1; data_in[0]=0; //  #80 data_in[2]=0; data_in[0]=1; //   end endmodule 

使用程序代码链接到github。

可以从www.model.com下载适用于Windows的免费学生版ModelSim
接下来,您必须(通过填写表格)下载student_license.dat文件,并将其放置在ModelSim程序的主目录中。

在此处链接到Linux(Ubuntu)的ModelSim文件
安装说明在这里

Source: https://habr.com/ru/post/zh-CN412379/


All Articles