微控制器的Verilog代码(第3部分 - Verilog代码)


在此项目中,提出了用于微控制器的Verilog代码。这 微控制器 架构和指令集显示在 part 1part 2

微控制器的Verilog代码
在阅读代码之前,请先访问第1部分和第2部分。

首先是Alu单位的Verilog代码:

// yl315.net: FPGA project, Verilog project, VHDL project
// Verilog project: Verilog code for Microcontroller
// Verilog code for ALU
module ALU(  input [7:0] Operand1,Operand2,
  input E, 
  input [3:0] Mode,
  input [3:0] CFlags,
  output  [7:0] Out,
  output  [3:0] Flags 
// the Z (zero), C (carry), S (sign),O (overflow) bits, from MSB to LSB, connected to status register 
   );
  wire Z,S,O;
  reg CarryOut;
  reg [7:0] Out_ALU;
  always @(*)
  开始
  case(Mode) 
  4'b0000: {CarryOut,Out_ALU} = Operand1 + Operand2;
  4'b0001: 开始 Out_ALU = Operand1 -  Operand2;
  CarryOut = !Out_ALU[7];
  结尾
  4'b0010: Out_ALU = Operand1;
  4'b0011: Out_ALU = Operand2;
  4'b0100: Out_ALU = Operand1 & Operand2;
  4'b0101: Out_ALU = Operand1 | Operand2;
  4'b0110: Out_ALU = Operand1 ^ Operand2;
  4'b0111: 开始
  Out_ALU = Operand2 - Operand1;
  CarryOut = !Out_ALU[7];
  结尾
  4'b1000: {CarryOut,Out_ALU} = Operand2 + 8'h1;
  4'b1001: 开始
  Out_ALU = Operand2 - 8'h1;
  CarryOut = !Out_ALU[7];
  结尾 
  4'b1010: Out_ALU = (Operand2 << Operand1[2:0])| ( Operand2 >> Operand1[2:0]);
  4'b1011: Out_ALU = (Operand2 >> Operand1[2:0])| ( Operand2 << Operand1[2:0]);
  4'b1100: Out_ALU = Operand2 << Operand1[2:0];
  4'b1101: Out_ALU = Operand2 >> Operand1[2:0];
  4'b1110: Out_ALU = Operand2 >>> Operand1[2:0];
  4'b1111: 开始
 Out_ALU = 8'h0 - Operand2;
 CarryOut = !Out_ALU[7];
 结尾
 default: Out_ALU = Operand2;
 结尾case
 结尾
 assign O = Out_ALU[7] ^ Out_ALU[6];
 assign Z = (Out_ALU == 0)? 1'b1 : 1'b0;
 assign S = Out_ALU[7];
 assign Flags = {Z,CarryOut,S,O};
 assign Out = Out_ALU;
// yl315.net: FPGA project, Verilog project, VHDL project
终点

接下来是数据内存的Verilog代码:

// yl315.net: FPGA project, Verilog project, VHDL project
// Verilog project: Verilog code for Microcontroller
// Verilog code for data memory
 module DMem( input clk,
     input E, // Enable port 
     input WE, // Write enable port
     input [3:0] Addr, // Address port 
     input [7:0] DI, // Data input port
     output [7:0] DO // Data output port
    );
reg [7:0] data_mem [255:0];
// yl315.net: FPGA project, Verilog project, VHDL project
always @(posedge clk) 
开始
 if(E==1 && WE ==1) 
  data_mem[Addr] <= DI;
结尾 
 assign DO = (E ==1 )? data_mem[Addr]:0;
终点
Adder和Mux1的Verilog代码:
// Verilog project: Verilog code for microcontroller
// Submodule: Verilog code for Adder and MUXs
module adder( input [7:0] In,
      output [7:0] Out
    );

assign Out = In + 1;

终点
module MUX1( input [7:0] In1,In2,
     input Sel,
     output [7:0] Out
    );

assign Out = (Sel==1)? In1: In2;
终点

继续在Verilog代码上进行程序内存:

// Verilog project: Verilog code for microcontroller
// Submodule: Verilog code for Adder and MUXs// yl315.net: FPGA project, Verilog project, VHDL project 
// Verilog project: Verilog code for microcontroller
module PMem( input clk,
   input E, // Enable port
  input [7:0] Addr, // Address port
  output [11:0] I, // Instruction port
  // 3 special ports are used to load program to the memory
  input LE, // Load enable port 
  input[7:0] LA, // Load address port
  input [11:0] LI//Load instruction port
   );
 reg [11:0] Prog_Mem[255:0] ;
// yl315.net: FPGA project, Verilog project, VHDL project 
always @(posedge clk)
 开始
 if(LE == 1) 开始
 Prog_Mem[LA] <= LI;
 结尾
 结尾
 assign I =  (E == 1) ?  Prog_Mem[Addr]: 0 ;
终点
module adder( input [7:0] In,
      output [7:0] Out
    );

assign Out = In + 1;

终点
module MUX1( input [7:0] In1,In2,
     input Sel,
     output [7:0] Out
    );

assign Out = (Sel==1)? In1: In2;
终点

接下来,控制单元的Verilog代码:

// yl315.net: FPGA project, Verilog project, VHDL project
// Verilog project: Verilog code for microcontroller
// Control unit in Verilog
module Control_Logic( input[1:0] stage,
  input [11:0] IR,
  input [3:0] SR,
 output  reg PC_E,Acc_E,SR_E,IR_E,DR_E,PMem_E,DMem_E,DMem_WE,ALU_E,MUX1_Sel,MUX2_Sel,PMem_LE,
  output reg [3:0] ALU_Mode
    );
 parameter LOAD = 2'b00,FETCH = 2'b01, DECODE = 2'b10, EXECUTE = 2'b11;
 always @(*)
 开始
 PMem_LE = 0;
 PC_E = 0;
 Acc_E = 0;
 SR_E = 0;
 IR_E = 0;
 DR_E = 0;
 PMem_E = 0; 
 DMem_E = 0;
 DMem_WE = 0;
 ALU_E  =0; 
 ALU_Mode = 4'd0;
 MUX1_Sel = 0;
 MUX2_Sel = 0;
 if(stage== LOAD )
 开始
 PMem_LE = 1;
 PMem_E = 1; 
 结尾
 别的 if(stage== FETCH ) 开始
 IR_E = 1; 
 PMem_E = 1;  
 结尾
 别的 if(stage== DECODE ) 开始
 if( IR[11:9] == 3'b001) 
 开始
 DR_E = 1;
 DMem_E = 1;
 结尾
 别的
 开始
 DR_E = 0;
 DMem_E = 0;
 结尾
 结尾
 别的 if(stage== EXECUTE ) 
 开始
 if(IR[11]==1) 开始 // ALU I-type
 PC_E = 1; 
 Acc_E = 1; 
 SR_E = 1;
 ALU_E = 1;
 ALU_Mode = IR[10:8];
 MUX1_Sel = 1;
 MUX2_Sel = 0; 
 结尾
 别的 if(IR[10]==1) // JZ, JC,JS, JO
 开始
 PC_E = 1; 
 MUX1_Sel = SR[IR[9:8]]; 
 结尾
 别的 if(IR[9]==1) 
 开始
 PC_E = 1; 
 Acc_E = IR[8]; 
 SR_E = 1;
 DMem_E = !IR[8];
 DMem_WE = !IR[8];
 ALU_E = 1;
 ALU_Mode = IR[7:4];
 MUX1_Sel = 1;
 MUX2_Sel = 1;
 结尾
 别的 if(IR[8]==0)
 开始
 PC_E = 1; 
 MUX1_Sel = 1; 
 结尾
 别的
 开始
 PC_E = 1; 
 MUX1_Sel = 0; 
 结尾
 结尾
 结尾
终点

最后,微控制器的Verilog代码:

// The microcontroller (similar to Microchip PIC12, simplified extensively, not compatible in 
// instruction set) in this project is a 3 cycle nonpipeline
// 8 bit Harvard structure microcontroller, illustrated as the following block diagram
// yl315.net: FPGA project, Verilog project, VHDL project
// Verilog project: Verilog code for microcontroller
module MicroController(input clk,rst
    );
  parameter LOAD = 2'b00,FETCH = 2'b01, DECODE = 2'b10, EXECUTE = 2'b11;
  reg [1:0] current_state,next_state;
  reg [11:0] program_mem[9:0];
  reg load_done;
  reg[7:0] load_addr;
  wire[11:0] load_instr;
  reg[7:0] PC,  DR, Acc;
  reg [11:0] IR;
  reg [3:0]  SR;
  wire PC_E,Acc_E,SR_E,DR_E,IR_E;
 reg PC_clr,Acc_clr,SR_clr,DR_clr,IR_clr;
 wire [7:0] PC_updated,DR_updated;
 wire[11:0] IR_updated;
 wire[3:0] SR_updated;
 wire PMem_E,DMem_E,DMem_WE,ALU_E,PMem_LE,MUX1_Sel,MUX2_Sel;
 wire [3:0] ALU_Mode;
 wire [7:0] Adder_Out;
 wire [7:0] ALU_Out,ALU_Oper2;
 // LOAD instruction memory
 initial
 开始
 $readmemb("program_mem.dat........", program_mem,0,9);
 结尾
 // ALU
 ALU ALU_unit( .Operand1(Acc),
      .Operand2(ALU_Oper2),
   .E(ALU_E),
   .Mode(ALU_Mode),
   .CFlags(SR),
      .Out(ALU_Out),
      .Flags(SR_updated) // the Z (zero), C (carry), S (sign),O (overflow) bits, from MSB to LSB, connected to status register
  );
 // MUX2
 MUX1 MUX2_unit( .In2(IR[7:0]),.In1(DR),
  .Sel(MUX2_Sel),
  .Out(ALU_Oper2)
    ); 
 // Data Memory
 DMem DMem_unit( .clk(clk),
  .E(DMem_E), // Enable port 
  .WE(DMem_WE), // Write enable port
  .Addr(IR[3:0]), // Address port 
  .DI(ALU_Out), // Data input port
  .DO(DR_updated) // Data output port
    );
 // Program memory
 PMem PMem_unit( .clk(clk),
  .E(PMem_E), // Enable port
  .Addr(PC), // Address port
  .I(IR_updated), // Instruction port
  // 3 special ports are used to load program to the memory
  .LE(PMem_LE), // Load enable port 
  .LA(load_addr), // Load address port
  .LI(load_instr)//Load instruction port
   );
 // PC ADder
 adder PC_Adder_unit( .In(PC),
   .Out(Adder_Out)
    );
// yl315.net: FPGA project, Verilog project, VHDL project 
// MUX1
 MUX1 MUX1_unit( .In2(IR[7:0]),.In1(Adder_Out),
  .Sel(MUX1_Sel),
  .Out(PC_updated)
    );
 // Control logic
 Control_Logic Control_Logic_Unit( .stage(current_state),
  .IR(IR),
  .SR(SR),
  .PC_E(PC_E),
  .Acc_E(Acc_E),
  .SR_E(SR_E),
  .IR_E(IR_E),
  .DR_E(DR_E),
  .PMem_E(PMem_E),
  .DMem_E(DMem_E),
  .DMem_WE(DMem_WE),
  .ALU_E(ALU_E),
  .MUX1_Sel(MUX1_Sel),
  .MUX2_Sel(MUX2_Sel),
  .PMem_LE(PMem_LE),
  .ALU_Mode(ALU_Mode)
    );
// yl315.net: FPGA project, Verilog project, VHDL project
 // LOAD
 always @(posedge clk)
 开始
 if(rst==1) 开始
 load_addr <= 0;
 load_done <= 1'b0;
 结尾 
 别的 if(PMem_LE==1)
 开始 
 load_addr <= load_addr + 8'd1;
 if(load_addr == 8'd9)
 开始
 load_addr <= 8'd0;
 load_done <= 1'b1;
 结尾
 别的
 开始
 load_done <= 1'b0;
 结尾
 结尾 
 结尾
// yl315.net: FPGA project, Verilog project, VHDL project
 assign load_instr = program_mem[load_addr];
 // next state
 always @(posedge clk)
 开始
 if(rst==1)
 current_state <= LOAD;
 别的
 current_state <= next_state;
 结尾
 always @(*)
 开始
 PC_clr = 0;
 Acc_clr = 0;
 SR_clr = 0;
 DR_clr = 0; 
 IR_clr = 0;
 case(current_state)
 LOAD: 开始
 if(load_done==1) 开始
 next_state = FETCH;
 PC_clr = 1;
 Acc_clr = 1;
 SR_clr = 1;
 DR_clr = 1; 
 IR_clr = 1;
 结尾
 别的
 next_state = LOAD;
 结尾
 FETCH: 开始
 next_state = DECODE;
 结尾
 DECODE: 开始
 next_state = EXECUTE;
 结尾
 EXECUTE: 开始
 next_state = FETCH;
 结尾 
 结尾case
 结尾
// yl315.net: FPGA project, Verilog project, VHDL project
 // 3 programmer visible register
 always @(posedge clk)
 开始
 if(rst==1) 
 开始
 PC <= 8'd0;
 Acc <= 8'd0;
 SR <= 4'd0;
 结尾
 别的 
 开始
 if(PC_E==1'd1) 
 PC <= PC_updated;
 别的 if (PC_clr==1)
 PC <= 8'd0;
 if(Acc_E==1'd1) 
 Acc <= ALU_Out;
 别的 if (Acc_clr==1)
 Acc <= 8'd0;
 if(SR_E==1'd1) 
 SR <= SR_updated; 
 别的 if (SR_clr==1)
 SR <= 4'd0; 
 结尾
 结尾
// yl315.net: FPGA project, Verilog project, VHDL project
 // 2 programmer invisible register
 always @(posedge clk)
 开始
 if(DR_E==1'd1) 
 DR <= DR_updated;
 别的 if (DR_clr==1)
 DR  <= 8'd0;
 if(IR_E==1'd1) 
 IR <= IR_updated;
 别的 if(IR_clr==1)
 IR <= 12'd0;
 结尾 
终点

Verilog TestBench代码验证微控制器: 

module MCU_tb;
// yl315.net: FPGA project, Verilog project, VHDL project 
// Verilog project: Verilog code for microcontroller
// Inputs
reg clk;
reg rst;
// Instantiate the Unit Under Test (UUT)
MicroController uut (
.clk(clk), 
.rst(rst)
);
initial 开始
// Initialize Inputs
rst = 1;
// Wait 100 ns for global reset to finish
#100;
rst = 0;
结尾
initial 开始 
clk = 0;
forever #10 clk = ~clk;
结尾 
终点 
测试程序1:
0000_0000_0000
1011_0000_0001
0010_0010_0000
1011_0000_0000
0011_0011_0000
0001_0000_0101
0000_0000_0000
0000_0000_0000
0000_0000_0000
0000_0000_0000
测试程序2:
0000_0000_0000
1011_0000_0001
0010_0010_0000
0011_0000_0000
0010_0000_0000
0011_0001_0000
0010_0001_0000
0011_0111_0000
0010_0111_0000
0001_0000_1001
测试程序3:
0000_0000_0000
1011_0000_0101
0010_0010_0000
0010_0010_0001
0010_0010_0010
1011_0000_0011
0010_0100_0000
0010_0101_0001
0010_0110_0010
0001_0000_1001
测试程序4:
0000_0000_0000
1011_0000_0101
1010_0000_0000
1000_0000_0111
1001_0000_0110
1111_0000_0111
1100_0000_0011
1101_0000_0101
1110_0000_0011
0001_0000_1001
使用四个测试程序运行模拟并检查微控制器是否正常工作。
微控制器的Verilog代码
推荐的 Verilog projects:
2. FIFO记忆的Verilog代码
3. 16位单循环MIPS处理器的Verilog代码
4. Verilog HDL中的可编程数字延迟计时器
5. 数字电路中基本逻辑组件的Verilog代码
6. 32位无符号分频器的Verilog代码
7. 用于固定点矩阵乘法的Verilog代码
8. 在Verilog HDL中的板牌识别
9. 携带外观前方乘法器的Verilog代码
10。 微控制器的Verilog代码
11. 4x4乘法器的Verilog代码
12. 停车系统的Verilog代码
13。 使用Verilog HDL对FPGA的图像处理
14。 如何使用Verilog HDL将文本文件加载到FPGA中
15。 交通灯控制器的Verilog代码
16。 FPGA闹钟的Verilog代码
17。 比较器设计的Verilog代码
18。 VERILOG代码D触发器
19。 完整加法器的Verilog代码
20。 与测试台的计数器的Verilog代码
21。 16位RISC处理器的Verilog代码
22。 FPGA上的按钮的Verilog代码
23。 如何为双向/ inout端口编写Verilog TestBench
28。 解码器的Verilog代码
29。 多路复用器的Verilog代码
FPGA Verilog VHDL课程

28评论:

  1. 很好但丢失了以下模块:
    -MUX1
    ad

    回复删除
  2. 你还能请详细说明指令集吗?我成功地合成了Altera Cyclone IV的代码,但没有'现在跑步,我'm试图了解第一个测试程序的目的,看起来像一个柜台或类似的东西

    回复删除
  3. Instruction set: http://www.yl315.net/2016/11/verilog-hdl-implementation-of-micro.html
    Architecture Design: http://www.yl315.net/2016/11/verilog-microcontroller-code.html

    回复删除
  4. 主席先生,我想添加一个MMIO 8位porta,在每个微型控制器中所做的那样,将一个MMIO 8位porta添加到这个微控制器(在DRAM的Aadress 0x08)中,从而可以使用其地址读取或写入UC端口。所以,请提出可能的修改代码。

    回复删除
  5. You can refer to this: http://www.yl315.net/2016/12/a-complete-8-bit-microcontroller-in-vhdl.html
    在此微控制器中,根据需要添加内存和IO。

    回复删除
  6. 先生,请你分享"program_mem.dat"U HV以$ READMEMB提到。

    回复删除
    答案
    1. 测试程序在那里。测试程序1 - >4.将其复制到program_mem.dat中。

      删除
  7. 我无法妥善模拟它。你能帮我测试计划吗?此外,仿真仅显示2个元素 - 时钟和复位。请帮忙。

    回复删除
    答案
    1. $ readmemb("program_mem.dat", program_mem,0,9);
      您需要将不同的测试程序加载到"program_mem.dat"文件和运行模拟。是的,只提供时钟和重置,但您需要查看模拟波形和数据存储器以查看MCU的操作。

      删除
    2. 我正在使用Xilinx ISE 14.7,我创建了TXT文件复制了内容"test program 1"进入它并将其重命名为"program_mem.dat"然后试图模拟。从哪里可以看到结果吗?

      删除
    3. 添加必要的信号以仿真波形以查看结果。您需要了解存储在指令存储器中的程序,以便您可以了解模拟波形上的结果

      删除
  8. 你能上传吗?"program_mem.dat"文件?当模拟上面的Progran_mem.dat文件时,我有错误.CAN您可以告诉我如何使用该DAT文件进行模拟。
    谢谢

    回复删除
    答案
    1. 您需要创建此文件并将提供的测试程序复制到文件中"program_mem.dat"你创造了哪个。然后,运行仿真并查看仿真波形的结果。

      删除
  9. 我创建了一个文本文件,重命名了它"program_mem.dat"。然后将其中一个测试程序复制到它,然后保存在保存我的Verilog文件的文件夹中的文本文件。仍然显示无法找到该文件的错误。请帮忙

    回复删除
    答案
    1. 将文件保存到您运行代码的同一文件夹中。该文件应该命名"program_mem.dat" not "program_mem.dat.txt".

      删除
    2. 谢谢。它现在正常工作。只有一个问题,这是一个12位微控制器右或8位微控制器?

      删除
    3. 你好,你能帮我吗?我也面临着同样的概率。它是显示文件无法找到的。

      删除
  10. 在控制单元中

    否则if(IR [8] == 0)////这应该是(IR [8] == 1)?我想或者是正确的吗?
    begin
    PC_E = 1;
    MUX1_Sel = 1;
    end
    else
    begin
    PC_E = 1;
    MUX1_Sel = 0;
    end
    end
    end
    终点

    回复删除
    答案
    1. 没有。代码已经是正确的。 IR [8] == 1 =>mux1_sel = 0选择IR [7:0]跳转或分支指令(IR [8] = 1)。否则(IR [8] == 0),MUX1_SEL = 1以增加1(ADDER_OUT)。检查mux1代码。

      删除
  11. 此代码是否会在Vivado 2017.4中执行

    回复删除
    答案
    1. 当然。您可以使用Vivado进行此项目。

      删除
    2. 我必须在测试台中提供的输入是什么,我可以有测试台的代码....在上面提供的代码(第3部分)我收到CLK和SEL波形作为输出

      删除
    3. 提供试验台。输入是您将放入程序存储器的说明。验证操作,运行模拟并检查寄存器和内存内容。

      删除
  12. 您好,我面临的问题_mem。没有找到DAT

    回复删除
  13. 先生
    你能在模拟上拍一个视频吗?

    回复删除
  14. 为什么执行设置为MSB的倒数?

    回复删除

趋势FPGA项目