Verilog——串口指令处理器(状态机)

串口指令处理器:

电路图:

cmd_pro指令集格式:
每次连续接收三个字节,第一字节为指令CMD,第二字节为操作数A,第三字节为操作数B;
指令集:

                        CMD                        操作
                        8‘h0a                        A+B
                        8'h0b                        A-B
                        8'h0c                        A&B
                        8'h0d                        A|B

状态流程图:

Verilog代码:

cmd_pro模块

module cmd_pro(
							clk,
							res,
							din_pro,
							en_din_pro,
							dout_pro,
							en_dout_pro,
							rdy
							);
input 				        clk;
input					    res;
input[7:0] 		            din_pro;//指令和数据输入端口;
input 				        en_din_pro;//输入使能;
output[7:0]		            dout_pro;//指令执行结果
output				        en_dout_pro;//指令输出使能
output				        rdy;//串口发送模块空闲标志,0表示空闲

parameter			add_ab=8'h0a;
parameter			sub_ab=8'h0b;
parameter			and_ab=8'h0c;
parameter			or_ab =8'h0d;

reg[2:0]			state;//主状态机寄存器;不知道几个状态是,多设置几位
reg[7:0]			cmd_reg,A_reg,B_reg;//存放指令、A和B;
reg[7:0]			dout_pro;
reg                 en_dout_pro;

always@(posedge clk or negedge res)
if(~res)begin
	state<=0;cmd_reg<=0;A_reg<=0;B_reg<=0;dout_pro<=0;
en_dout_pro<=0;
	end
else begin
	case(state)
	0://等指令
	begin
		en_dout_pro<=0;
		if(en_din_pro)begin
				cmd_reg<=din_pro;
				state<=1;
		end
	end
	1://收A;
	begin
	if(en_din_pro)begin
				A_reg<=din_pro;
				state<=2;
		end
	end
	2://收B;
	begin
	if(en_din_pro)begin
				B_reg<=din_pro;
				state<=3;
		end
	end
	3://指令译码和执行
	begin
	state<=4;
		case(cmd_reg)
		add_ab:begin dout_pro<=A_reg+B_reg;end
		sub_ab:begin dout_pro<=A_reg-B_reg;end
		and_ab:begin dout_pro<=A_reg&B_reg;end
		or_ab: begin  dout_pro<=A_reg|B_reg;end//规整性
        endcase
	end
	4://发送指令执行结果;
	begin
		if(~rdy)begin
			en_dout_pro<=1;
			state<=0;
		end
	end
	default://
	begin
			state<=0;
			en_dout_pro<=0;
	end
    endcase
end

endmodule

UART_top:

`timescale 1ns/10ps
module UART_top(
				clk,
				res,
				RX,
				TX
				);
input		clk;
input		res;
input		RX;
output	TX;

//在这里例化三个模块
//需要定义RX,TX模块与cmd模块联系的5个中间信号,信号名以cmd为准
//因为这五个信号都是连接信号,定义为wire类型
wire[7:0]				din_pro;
wire						en_din_pro;
wire[7:0]				dout_pro;
wire						en_dout_pro;
wire						rdy;

//封装顶层的时候,不管谁是输入,谁是输出,从顶层看都是连线,纯连接wire类型
//做testbench时,会改变模块的输入,所以要定义为reg类型

//异名例化

//串口数据接收
UART_RXer UART_RXer(
							.clk(clk),
							.res(res),
							.RX(RX),
							.data_out(din_pro),
							.en_data_out(en_din_pro)
							);

//串口数据发送
UART_TXer UART_TXer(
							.clk(clk),
							.res(res),
							.data_in(dout_pro),
							.en_data_in(en_dout_pro),
							.TX(TX),
							.rdy(rdy)
								);
//指令处理
cmd_pro cmd_pro(
							.clk(clk),
							.res(res),
							.din_pro(din_pro),
							.en_din_pro(en_din_pro),
							.dout_pro(dout_pro),
							.en_dout_pro(en_dout_pro),
							.rdy(rdy)
							);
endmodule

测试代码:

//------testbench----

module UART_top_tb;

reg			        clk,res;
wire		        RX; 
wire		        TX; 

reg[45:0]			RX_send;//里面装有串口字节发送数据
assign				RX=RX_send[0];//连接RX
reg[12:0]			con;


UART_top UART_top(
				    clk,
				    res,
				    RX,
				    TX
				);

initial begin
					clk<=0;res<=0;con<=0;
					RX_send<={1'b1,8'h09,1'b0,1'b1,8'h06,1'b0,1'b1,8'h0a,1'b0,16'hffff};
					//发送的数据8'h09,8'h06,发送的操作符8'h0a;
		#17			res<=1;
		#1000		$stop;//仿真结束
end

always #5 clk<=~clk;

//发送数据
//连续右移
always@(posedge clk)begin

	if(con==5000-1)begin
		con<=0
	end
	else begin
		con<=con+1;
	end

	if(con==0)begin
		RX_send[44:0]<=RX_send[45:1];//错一项
		RX_send[45]<=RX_send[0];//反复右移旋转
	end
end

endmodule

编译:

先把几个模块编译,然后编译top

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值